rbs icon indicating copy to clipboard operation
rbs copied to clipboard

Cannot specify type variables for `instance`

Open ParadoxV5 opened this issue 2 years ago • 7 comments

class MyWrapper[E]
  def self.of: (E) -> instance # RBS::UnknownTypeName (it’s not inferred from `MyWrapper[E]`)
  def self.of: (E) -> instance[E] # RBS::SyntaxError
  def self.of: [E] (E) -> instance # ok, but `[E]` is not used in practice (it’s not the same `[E]` as the one in `MyWrapper[E]`)
  def self.of: (untyped) -> instance # ok, but `untyped` is bad
end

Even Steep is aware of this limitation: https://github.com/soutaro/steep/blob/v1.5.3/lib/steep/subtyping/check.rb#L307

Proposal: instance[E]?

The problem might be significant for class as well: https://github.com/soutaro/steep/blob/v1.5.3/lib/steep/subtyping/check.rb#L322

ParadoxV5 avatar Sep 16 '23 04:09 ParadoxV5

I know there are some cases that requires that kind of types, but we don't have a plan to support it at least for now.

A class inheriting from a generic class may be non-generic, and what can we do for instance[T] (and maybe self[T]) types?

class Generic[T]
  def foo: () -> instance[Array[T]]
end

class NonGeneric < Generic[String]
end

# Even worse if it inherited by another generic class.
class AnotherGeneric[T] < NonGeneric
end

soutaro avatar Sep 16 '23 04:09 soutaro

def self.of: (E) -> instance # RBS::UnknownTypeName (it’s not inferred from `MyWrapper[E]`)

How about letting class methods pick up generics?

ParadoxV5 avatar Sep 16 '23 05:09 ParadoxV5

def self.of: (E) -> instance # RBS::UnknownTypeName (it’s not inferred from `MyWrapper[E]`)

How about letting class methods pick up generics?

Would this rather be a Steep job? Unless the RBS gem itself also involved…

ParadoxV5 avatar Sep 23 '23 01:09 ParadoxV5

How about letting class methods pick up generics?

Generics in RBS currently is for instance types.

I think no other programming language allows this. Do you know any example?

soutaro avatar Sep 28 '23 13:09 soutaro

The type you want would be this?

def self.of: [E, T < MyWrapper[E]] (E) -> T

Steep allows explicit type application, and it will help:

MyWrapper.of(123) #$ Integer, AnotherWrapper         # E=Integer, T=AnotherWrapper

soutaro avatar Sep 28 '23 13:09 soutaro

The type you want would be this?

def self.of: [E, T < MyWrapper[E]] (E) -> T

Almost. The strength of instance is that it indicates the ::of of MyWrapperSubclass[E] < MyWrapper[E] returns a MyWrapperSubclass[E] and not an unspecific MyWrapper[E].

Steep allows explicit type application, and it will help:

MyWrapper.of(123) #$ Integer, AnotherWrapper         # E=Integer, T=AnotherWrapper

Good to know more :+1:. Steep really lacks detailed and locatable docs for Ruby annotations, both in-line and #@type styles.

ParadoxV5 avatar Sep 28 '23 17:09 ParadoxV5