Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tuple.new isn't considered an Enumerable #12487

Open
mattrberry opened this issue Sep 15, 2022 · 4 comments
Open

Tuple.new isn't considered an Enumerable #12487

mattrberry opened this issue Sep 15, 2022 · 4 comments

Comments

@mattrberry
Copy link
Contributor

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

@HertzDevil
Copy link
Contributor

HertzDevil commented Sep 15, 2022

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.

@asterite
Copy link
Member

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.

@HertzDevil
Copy link
Contributor

How would unions between them work if they are no longer covariant?

@asterite
Copy link
Member

They would be normal unions. Their types wouldn't merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants