diff --git a/spec/core/range/size_spec.rb b/spec/core/range/size_spec.rb index 379939891c..a1fe3ce17d 100644 --- a/spec/core/range/size_spec.rb +++ b/spec/core/range/size_spec.rb @@ -76,23 +76,21 @@ ruby_version_is "3.4" do it 'raises TypeError if a range is not iterable' do - NATFIXME 'it raises TypeError if a range is not iterable' do - -> { (1.0..16.0).size }.should raise_error(TypeError, /can't iterate from/) - -> { (1.0...16.0).size }.should raise_error(TypeError, /can't iterate from/) - -> { (1.0..15.9).size }.should raise_error(TypeError, /can't iterate from/) - -> { (1.1..16.0).size }.should raise_error(TypeError, /can't iterate from/) - -> { (1.1..15.9).size }.should raise_error(TypeError, /can't iterate from/) - -> { (16.0..0.0).size }.should raise_error(TypeError, /can't iterate from/) - -> { (Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/) - -> { (-Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/) - -> { (-Float::INFINITY..Float::INFINITY).size }.should raise_error(TypeError, /can't iterate from/) - -> { (..1).size }.should raise_error(TypeError, /can't iterate from/) - -> { (...0.5).size }.should raise_error(TypeError, /can't iterate from/) - -> { (..nil).size }.should raise_error(TypeError, /can't iterate from/) - -> { (...'o').size }.should raise_error(TypeError, /can't iterate from/) - -> { eval("(0.5...)").size }.should raise_error(TypeError, /can't iterate from/) - -> { eval("([]...)").size }.should raise_error(TypeError, /can't iterate from/) - end + -> { (1.0..16.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.0...16.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.0..15.9).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.1..16.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.1..15.9).size }.should raise_error(TypeError, /can't iterate from/) + -> { (16.0..0.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (-Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (-Float::INFINITY..Float::INFINITY).size }.should raise_error(TypeError, /can't iterate from/) + -> { (..1).size }.should raise_error(TypeError, /can't iterate from/) + -> { (...0.5).size }.should raise_error(TypeError, /can't iterate from/) + -> { (..nil).size }.should raise_error(TypeError, /can't iterate from/) + -> { (...'o').size }.should raise_error(TypeError, /can't iterate from/) + -> { eval("(0.5...)").size }.should raise_error(TypeError, /can't iterate from/) + -> { eval("([]...)").size }.should raise_error(TypeError, /can't iterate from/) end end diff --git a/src/match_data_object.cpp b/src/match_data_object.cpp index 397a75795b..b4ae59a1b8 100644 --- a/src/match_data_object.cpp +++ b/src/match_data_object.cpp @@ -344,10 +344,12 @@ ArrayObject *MatchDataObject::values_at(Env *env, Args &&args) { env->raise("RangeError", "{} out of range", range->inspect_str(env)); auto append = ref(env, range); result->concat(env, { append }); - auto size = range->send(env, "size"_s); - if (append->is_array() && size->is_integer() && size->as_integer()->to_nat_int_t() > static_cast(append->as_array()->size())) { - for (nat_int_t i = append->as_array()->size(); i < size->as_integer()->to_nat_int_t(); i++) - result->push(NilObject::the()); + if (range->begin()->is_integer()) { + auto size = range->send(env, "size"_s); + if (append->is_array() && size->is_integer() && size->as_integer()->to_nat_int_t() > static_cast(append->as_array()->size())) { + for (nat_int_t i = append->as_array()->size(); i < size->as_integer()->to_nat_int_t(); i++) + result->push(NilObject::the()); + } } } else { result->push(ref(env, key)); diff --git a/src/range.rb b/src/range.rb index 85d7fc36d7..b6aba79695 100644 --- a/src/range.rb +++ b/src/range.rb @@ -122,23 +122,21 @@ def minmax(&block) end def size + raise TypeError, "can't iterate from #{self.begin.class}" unless self.begin.respond_to?(:succ) return if self.begin.nil? && !self.end.is_a?(Numeric) - return Float::INFINITY if self.begin.nil? return unless self.begin.is_a?(Numeric) return Float::INFINITY if self.end.nil? - return unless self.end.is_a?(Numeric) return 0 if self.end < self.begin - return Float::INFINITY if self.begin.is_a?(Float) && self.begin.infinite? return Float::INFINITY if self.end.is_a?(Float) && self.end.infinite? size = self.end - self.begin size += 1 unless exclude_end? - return size.floor if size.is_a?(Float) size end def reverse_each raise TypeError, "can't iterate from #{self.end.class}" if self.end.nil? return super unless self.end.respond_to?(:pred) + size = self.begin.nil? ? Float::INFINITY : self.size return enum_for(:reverse_each) { size } unless block_given? item = self.end item = item.pred if exclude_end?