-
Notifications
You must be signed in to change notification settings - Fork 196
Override freeze-related behaviour in RubyRange for compatibility with Ruby 3.0 #2570
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
Override freeze-related behaviour in RubyRange for compatibility with Ruby 3.0 #2570
Conversation
|
Is this to handle freeze state in |
1550895 to
dc37253
Compare
|
Extra context is that because This is preliminary work to fixing the frozen behaviour of Note that another conversation to have is that |
|
Ah, yes, not all Range are frozen, only instances of Range but not instances of subclasses of Ranges: https://bugs.ruby-lang.org/issues/15504#note-19 I think this is something to fix in CRuby at some point, it's a weird exception to immutable classes (https://gist.github.com/eregon/bce555fa9e9133ed27fbfc1deb181573). |
So we'd have |
No, in |
|
Benoit and I briefly chatted in the Graal Slack. I'm going to go ahead and update this PR with additional changes that bring in the |
Yeah, that could work. It'd still increase the footprint for all instances of these. I'm not sure which builtin classes are likely to be frozen (but not always frozen) and/or object_id, would be good to have some data on that. |
1f8f02d to
4da431a
Compare
chrisseaton
left a comment
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.
Need to fix the spec.
2f07b6d to
94cfbac
Compare
| range.begin, | ||
| range.end); | ||
| range.end, | ||
| range.frozen); |
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.
.dup should actually create an unfrozen copy:
irb(main):001:0> RUBY_VERSION
=> "3.0.2"
irb(main):002:0> (1..2).frozen?
=> true
irb(main):003:0> (1..2).dup.frozen?
=> false
Could you add specs for that (if there isn't already) and fix the behavior?
For the int and long ranges, we need to create non-frozen variants as well then (or create RubyObjectRange, but that seems not advantageous).
94cfbac to
50115c4
Compare
eregon
left a comment
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.
This looks great, thank you for the PR!
|
|
||
| it "is not frozen if duplicated" do | ||
| (42..).dup.should_not.frozen? | ||
| end |
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.
This should move to spec/ruby/core/range/dup_spec.rb, I'll do that.
|
I just remembered, there is a follow-up optimization related to this, range literals can be embedded in the AST: However this is a problem for AST sharing (sharing the same AST for multiple execution contexts, which have different Ruby classes, etc), because RubyRange objects are currently not context-independent, they point to a given RubyClass ( @MattAlp Would you like to try that (separate PR of course) or you would prefer if somebody else works on that? It is a bit more involved than the change here but I think also not very difficult either. => moved to #2622 |
…bility with Ruby 3.0 (#2570) PullRequest: truffleruby/3120
|
Sure, I'll take it @eregon |
Update
As stated in the discussion below, this PR is now an optimization + compatibility change that modifies the behaviour of RubyRange and how it is used.
While working on #2453 and updating
Range's behaviour to comply with 3.0, I discovered thatRubyRangeinherits fromRubyDynamicObject, which exportsfreezeandisFrozenmethods that dynamically set thefrozen?property on the object.This proposed change implements the same pattern as seen in
RubyString, which exposes afrozenparameter in the constructor and overrides thefreezeandisFrozenmethods to explicitly work on theboolean frozenfield. By doing so, the field is always present on the object and can default totrue, rather than needing to be instantiated as a dynamic property. This also allows us to set the property at the appropriate call sites (i.e. tofalsewhen creating an object in Ruby that inherits fromRange).