An important point as well is that in Crystal currently if you have
class Subtype < Type
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:
(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.