Subtyping issue

Isn’t String a subtype of Object this making this assignment valid?

In src/djot/signed_token.cr:19:7

 19 | @payload = payload
      ^-------
Error: instance variable '@payload' of Djot::SignedToken must be Hash(String, Object), not Hash(String, String)

Hi! You can’t have a Hash of Object.

Can you show us your full code?

You are probably doing something like this:

struct Test
  @payload : Hash(String, Object)

  def initialize
    @payload = {"test" => "test"}
  end
end

This don’t work because you are assigning a Hash(String, String) to a Hash(String, Object). You need to specify the type like this: @payload = {"test" => "test} of String => Object. See Inheritance - Crystal.

But then as @asterite said you got this error:

Error: can’t use Object as generic type argument yet, use a more specific type

An important point as well is that in Crystal currently if you have

class Type
end

class Subtype < Type
end

You have an “is a” relationship such that (Subtype.new).is_a? Type (note: the #is_a? method works on objects of a type, not the type itself).

However, the generic system does not extend that within generic type variables. So you end up with this:

class Generic(T)
end

(Generic(Subtype).new).is_a? Generic(Type) # => false

I think the most relevant reason for this behavior is that it would be harder to implement what you’re expecting (and would make the compiler slower), but this behavior does work once you understand and expect it.


Side note: we as a community need a document somewhere that we can point to explaining how this behavior works and why it works that way. There are discussions about generics and inheritance regularly on the Gitter, here, and in GitHub issues, and I’ve picked up the little I just wrote in those places, but someone who really understands the relevant issues (and can properly use terms with “variance” in them) needs to write (or start) a definitive, clear document somewhere so that people can contribute to and refine it. That way we can have a direct, clear response to questions like this one.

You found Covariance and contravariance · Issue #3803 · crystal-lang/crystal · GitHub More at Covariance and contravariance (computer science) - Wikipedia :)

1 Like