self in the type grammar inside class Class refers to the instance (Int32) instead of the metaclass (Int32.class).
This makes type restrictions : self on return type of Class methods arkward.
If we use it as we would with other types to represent the metaclass of the self instance, we get a type error.
For example in this implementation of dup the type grammar self should be equivalent to typeof(self) in the normal code.
class Class
def dup : self # Error: method Int32.dup must return Int32 but it is returning Int32.class
self
end
end
Int32.dup
As a workaround, we can change the return type to self.class. This works correctly then, but it's very surprising compared to the behaviour in any other type.
class Class
def dup : self.class
self
end
end
Int32.dup
Furthermore, it complicates things when inheriting methods from other types. Class inherits from Value which already defines #dup. If we add a : self return type restriction to Value#dup, that would be invalid for the Class#dup instantiation.
So we must override Class#dup with a custom implementation returning self.class.
Another practical example is #17009, where we'd like to add type restriction : self to Object#should and #should_not, but when the target is a Class instance, this type restriction is broken.
Inside class Class, one method uses self as referring to the instance class: Class#cast(other) : self
I suppose that's a legitimate use case. And there is (currently) no workaround like self.class to express this instance class relation.
So I suppose this definition of self inside class Class has its merit. But it's still very surprising.
Slightly related:
Add a 👍 reaction to issues you find important.
selfin the type grammar insideclass Classrefers to the instance (Int32) instead of the metaclass (Int32.class).This makes type restrictions
: selfon return type ofClassmethods arkward.If we use it as we would with other types to represent the metaclass of the
selfinstance, we get a type error.For example in this implementation of
dupthe type grammar self should be equivalent totypeof(self)in the normal code.As a workaround, we can change the return type to
self.class. This works correctly then, but it's very surprising compared to the behaviour in any other type.Furthermore, it complicates things when inheriting methods from other types.
Classinherits fromValuewhich already defines#dup. If we add a: selfreturn type restriction toValue#dup, that would be invalid for theClass#dupinstantiation.So we must override
Class#dupwith a custom implementation returningself.class.Another practical example is #17009, where we'd like to add type restriction
: selftoObject#shouldand#should_not, but when the target is aClassinstance, this type restriction is broken.Inside
class Class, one method usesselfas referring to the instance class:Class#cast(other) : selfI suppose that's a legitimate use case. And there is (currently) no workaround like
self.classto express this instance class relation.So I suppose this definition of
selfinsideclass Classhas its merit. But it's still very surprising.Slightly related:
is_a?fails when usingself.class#15775Add a 👍 reaction to issues you find important.