Skip to content

Type grammar self inside class Class refers to instance, not metaclass #17019

Description

@straight-shoota

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions