-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[Bug #21513] Raise on converting endless range to set #13902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on this.
range.c
Outdated
range_to_set(VALUE range) | ||
{ | ||
if (NIL_P(RANGE_END(range))) { | ||
rb_raise(rb_eRangeError, "cannot convert endless range to a set"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that endless range error should be the same error type as beginless range error. Calling to_set
on a beginless range currently raises TypeError
. This method should probably have beginless range raise RangeError
instead, and include a test and an example for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Should we also tweak Range#to_a
to raise RangeError
in both cases?
./ruby -e '(..1).to_a'
-e:1:in 'Range#each': can't iterate from NilClass (TypeError)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Should we also tweak
Range#to_a
to raiseRangeError
in both cases?
@nobu what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels clearer for me.
@knu Any thoughts?
If we will change it too, maybe ruby/spec also needs to be updated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should perhaps check the size of a given Enumerable in Set.new and raise an error when it is infinity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should perhaps check the size of a given Enumerable in Set.new and raise an error when it is infinity.
Seems good to me. I'll try to follow this path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried out this idea and it seems to work fine (we now raise ArgumentError
error for any endless enumerable, e.g. 1.upto(Float::INFINITY)
.
$ ./ruby -e 'Set.new((1..nil))'
-e:1:in 'Set#initialize': cannot initialize Set from a enumerable with infinite size (ArgumentError)
from -e:1:in '<main>'
$ ./ruby -e '(1..nil).to_set'
-e:1:in 'Enumerable#to_set': cannot initialize Set from a enumerable with infinite size (ArgumentError)
from -e:1:in '<main>'
4b9f122
to
31a3861
Compare
There's a SEGV in the ZJIT test suite: https://github.com/ruby/ruby/actions/runs/16305765996/job/46051383888?pr=13902 Not sure if it's related to my changes |
31a3861
to
a5a7db6
Compare
ZJIT error seems entirely unrelated to your change from a quick glance |
Looks like a weird GC issue related to marking though so paging in @k0kubun for good measure |
a5a7db6
to
e1b6f53
Compare
e1b6f53
to
ca35402
Compare
❌ Tests Failed✖️no tests failed ✔️62191 tests passed(1 flake) |
I agree that it's probably not related to the changes. We're looking into GC issues with ZJIT. |
7753557
to
2de1bf0
Compare
Could someone please take a look? |
2de1bf0
to
36e3cee
Compare
set.c
Outdated
@@ -494,6 +494,14 @@ set_i_initialize(int argc, VALUE *argv, VALUE set) | |||
rb_check_arity(argc, 0, 1); | |||
|
|||
if (argc > 0 && (other = argv[0]) != Qnil) { | |||
ID id_size = rb_intern("size"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should move this to the following else
block, so it won't be called for arrays, as arrays never have infinite size.
set.c
Outdated
if (rb_respond_to(other, id_size)) { | ||
VALUE size = rb_funcall(other, id_size, 0); | ||
if (RB_TYPE_P(size, T_FLOAT) && RFLOAT_VALUE(size) == INFINITY) { | ||
rb_raise(rb_eArgError, "cannot initialize Set from a enumerable with infinite size"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You aren't checking that the argument is enumerable, only that the size is infinite. It would be more correct to say "an object" instead of "a enumerable". Even if you keep the current wording, it should be "an enumerable" instead of "a enumerable".
ref: https://bugs.ruby-lang.org/issues/21513 Before this patch, trying to convert endless range (e.g. `(1..)`) to set (using `to_set`) would hang
36e3cee
to
f9dce06
Compare
@jeremyevans thank you very much for helping me with that! ❤️ |
Before this patch, trying to convert endless range (e.g.
(1..)
or any other inifinte enumerable) to set (usingto_set
) would hang