-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 covariance #357
Comments
👍 |
@asterite Why doesn't it work in the first place? Shouldn't Also, what does |
@zamith It doesn't work in the first place because the types don't match. It would seem that the types match at first, but when you write You can try to fix this, is you want :-) But I'll have to explain you much, much more than this, specially because the compiler's code is not documented at all. As for |
I think I understand the restriction part. The codegen not so much, there are so many overloads that I got lost. :P You can go ahead an fix it if you have time, I'll then look at the solution. |
@asterite You say "If you restrict String with Foo you get nil as result (no type matched), and that's where you would get a compile error." Could you please elaborate why |
@js-ojus I think it was just an example as to what the result of an unsuccesful restriction would be (Since it is evidently clear that Foo is not a String or vice versa). It doesn't actually happen in the example he brought up. |
Finally, this is now implemented. I also made the union of tuple types of the same size be smarter and more convenient. Previously I was reluctant to use tuples in some situations, for example: def foo
if 1 == 2
{true, "hello"}
else
{false, 1}
end
end
typeof(foo) # => {Bool, Int32 | String}
# before this change: ({Bool, Int32} | {Bool, String}) I think now it's more correct because the intention was probably to return |
I think the logic for tuple covariance is wrong, it breaks the type system in some unintuitive ways. I'll kind of revert that change but only let it work for class types... I'll comment later after I do it, and explain the reasons. |
I reverted the logic of merging unrelated tuple types into a common tuple type. It's wrong and makes things less obvious. For example: tup = rand() < 0.5 ? {1, 2} : {true, false}
tup.class The class must be However, assigning a "smaller" tuple type to a "bigger" tuple type works, which was the thing this issue was all about: a = [] of {Int32 | String, Int32}
a << {1, 2} # works And the same goes for class inheritance (putting a {Bar} where {Foo} is expected, if Bar < Foo). So this works like this (like before): def foo
if 1 == 2
{true, "hello"}
else
{false, 1}
end
end
typeof(foo) # => {Bool, Int32} | {Bool, String} |
I decided to revert it here. This needs a lot more thought and it's far from trivial to implement. |
We discussed this feature with @waj and decided we'll implement this. The way this will work is that a union of two tuples with the same size will return in a single tuple type of unions of types in each position. For example: def foo
if condition
{true, "hello"}
else
{'a', 1}
end
end
typeof(foo) # => {Bool | Char, String | Int32} I previously tried to implement that but stumbled upon some problems (#2524), though I stumbled upon the same problems with named tuples (#2573) and having them being compatible with regards to the keys and types, without having order matter. I fixed those problems for named tuples and the solution will be the same for tuples. This change will be a breaking change, though I believe a small one, because of this: def foo
if 1 == 1
{true, "hello"}
else
{'a', 1}
end
end
tuple = foo()
# Before
typeof(tuple) # => {Bool, String} | {Char, Int32}
tuple.class #=> {Bool, String}
tuple.is_a?({Bool, String}) # => true
# After this change
typeof(tuple) # => {Bool | String, Char | Int32}
tuple.class # => {Bool | String, Char | Int32}
tuple.is_a?({Bool, String}) # => false In a way, type information is lost. However, we could change the meaning of if tuple.is_a?({Bool, String})
typeof(tuple) # => {Bool, String}
end We'll probably implement this last bit later. |
I like the idea of changing the is_a? check on tuples accordingly. |
Maybe this should work:
A workaround is to use a record:
The text was updated successfully, but these errors were encountered: