Skip to content

Freeze singleton class chain #10245

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jeremyevans
Copy link
Contributor

The following code:

x = Object.new
sc1 = x.singleton_class
sc2 = sc1.singleton_class
x.freeze

Would freeze sc1 but not sc2, even though sc1 would be frozen.

Not freezing the entire singleton class chain is expected, because at a certain point, the singleton class is shared. However, you can walk the the attached object chain for each singleton class, and only freeze if it results in the original object. This way, only non-shared singleton classes are frozen.

Fixes [Bug #20319]

The following code:

```ruby
x = Object.new
sc1 = x.singleton_class
sc2 = sc1.singleton_class
x.freeze
```

Would freeze sc1 but not sc2, even though sc1 would be frozen.

Not freezing the entire singleton class chain is expected, because
at a certain point, the singleton class is shared.  However, you
can walk the the attached object chain for each singleton class,
and only freeze if it results in the original object.  This way,
only non-shared singleton classes are frozen.

Fixes [Bug #20319]
@jeremyevans jeremyevans force-pushed the freeze-singleton-class-chain-20319 branch from f4f8f51 to ff2b943 Compare March 14, 2024 01:48
@jeremyevans jeremyevans requested a review from nobu April 11, 2024 19:55
@eregon
Copy link
Member

eregon commented Apr 18, 2024

Not freezing the entire singleton class chain is expected, because at a certain point, the singleton class is shared. However, you can walk the the attached object chain for each singleton class, and only freeze if it results in the original object. This way, only non-shared singleton classes are frozen.

Right, by "shared singleton class" that's actually only internal CRuby state, i.e., before the singleton class of that class has been needed (e.g. by calling .singleton_class). It's basically a case of "doesn't have a singleton class yet, so instead the superclass is stored in the RBasic->klass field).
Maybe there is even a macro in CRuby to check that more explicitly than RCLASS_ATTACHED_OBJECT.

I think it this is a good way to fix the inconsistency shown in https://bugs.ruby-lang.org/issues/20319

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants