-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fix access of class vars from generic metaclass #6348
Fix access of class vars from generic metaclass #6348
Conversation
Aparte: you should put the explanation right into the commit message, not just on GitHub PR; Git log or blame, for example, would be very enriched :-) |
I'll do it, please don't merge yet 👍 |
8f837e5
to
9630c81
Compare
Updated! |
9630c81
to
1831f4e
Compare
So, after this change the code class vars are shared among all the instantiations class Foo(T)
@@counter = 0
def self.inc
@@counter += 1
end
def self.counter
@@counter
end
end
pp!({Foo.counter, Foo(Int32).counter, Foo(String).counter}) # => {0, 0, 0}
Foo.inc
pp!({Foo.counter, Foo(Int32).counter, Foo(String).counter}) # => {1, 1, 1}
Foo(Int32).inc
pp!({Foo.counter, Foo(Int32).counter, Foo(String).counter}) # => {2, 2, 2}
Foo(String).inc
pp!({Foo.counter, Foo(Int32).counter, Foo(String).counter}) # => {3, 3, 3} I came late to the discussion (holidays \o/) but I think a more proper behaviour would have been to let With the above proposed behavior user can share state among metaclasses instance with a dummy type and isolate state by declaring class vars directly inside the generic type. I found that would be even more consistent with respect non generic class hierarchy. class Bar
@@counter = 0
def self.inc
@@counter += 1
end
def self.counter
@@counter
end
end
class Baz < Bar
end
class Qux < Bar
end
pp!({Bar.counter, Baz.counter, Qux.counter}) # => {0, 0, 0}
Bar.inc
pp!({Bar.counter, Baz.counter, Qux.counter}) # => {1, 0, 0}
Baz.inc
pp!({Bar.counter, Baz.counter, Qux.counter}) # => {1, 1, 0}
Qux.inc
pp!({Bar.counter, Baz.counter, Qux.counter}) # => {1, 1, 1} |
Yeay! C# behaves as I proposed https://stackoverflow.com/questions/14748569/is-a-static-member-variable-common-for-all-c-sharp-generic-instantiations |
@bcardiff , I agree that this a good question to refer to language ideas. Which are a bit unclear for me after point of diverging from Ruby. With this PR it looks to be Java-like approach (any "class" regardless of it being generic or specialized represent single entity) and refer to |
Fixes #3719
Every type has a "class var owner": the type where a class var is stored, or which "owns" the class var. Metaclasses usually forward this responsibility to their instance type. Same goes with generic type instantiations. The problem happened with a metaclass of a generic instantiation: it should double forward the responsibility. So I just made sure to also ask the class var owner of the type we are forwarding to.