crystal
crystal copied to clipboard
`Tuple.new` isn't considered an `Enumerable`
foo : Enumerable(String) = Tuple.new # => Error: type must be Enumerable(String), not Tuple()
I'd expect an empty tuple to be considered an enumerable of any type. Compare this to the following, which works as expected
foo : Enumerable(String) = Tuple(String).new("")
Tested on Crystal 1.5.1
Enumerable
is invariant, so there is no relationship between Enumerable(String)
and Enumerable(NoReturn)
, which Tuple()
is a subtype of. See #3803. Similarly it can be shown that the subtyping relationship isn't transitive:
class Foo; end
class Bar < Foo; end
{% Tuple(Bar) <= Tuple(Foo) %} # => true
{% Tuple(Foo) <= Enumerable(Foo) %} # => true
{% Tuple(Bar) <= Enumerable(Foo) %} # => false
This is actually quite problematic.
For Crystal 2.0 I'd like it if we could remove the special subtyping rules of Tuple and NamedTuple. They just make things too complex and inconsistent.
How would unions between them work if they are no longer covariant?
They would be normal unions. Their types wouldn't merge.