-
-
Notifications
You must be signed in to change notification settings - Fork 415
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
Make tuples be subtypes of empty interfaces (like Any). #1937
Conversation
I've marked this as |
The crash in the tests is caused by the reachability map not being aware of the new subtyping relationship between tuples and empty interfaces. The code generator then believes that generating the The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This currently crashes when the tuple contains non-single types (eg union, intersection or tuple)
class C
class D
primitive P
fun apply(x: (C val | D val, C ref)) =>
let x': Any box = consume x
I think we can make (T1, T2) a subtype of Any cap
by checking if both T1
and T2
are subtypes of Any cap
, and it would take care of recursively checking through the types to check the capability
src/libponyc/type/subtype.c
Outdated
child != NULL; | ||
child = ast_sibling(child)) | ||
{ | ||
if(!is_sub_cap_and_eph(child, super, check_cap, errorf, opt)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of is_sub_cap_and_eph
, I would make this is_x_sub_x(child, super, ...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea - makes sense.
f66e0be
to
1f298e9
Compare
I've made the fix that @plietar pointed out, but @Praetonus, I'm a little confused on your point, so I was hoping you could give some more guidance. I looked at the source and call sites of the |
@jemc You're right, that's not the problem. I think that what's missing is a call to |
The problem here I think is that an However, since #1934, this method is generated only if it is reachable, and it will never be considered reachable for Note that #1934 also had a bug which leads to a similar crash. In the following example, when marking the let x : (((U8, U16) | None, U8) | None) = None
let y : (((U8, U16) | None, U8) | None) = None
x is y Unfortunately if we make tuples subtypes of |
I think you're right @plietar, the identity reachability isn't recursive when it should indeed be. I'll make a fix. |
@Praetonus - what about this part of @plietar's comment?
My takeaway from that comment is that if we make the change that this PR was opened to make, then we can't also have the optimization from #1934. So, if that's the case, we should likely just revert #1934, or come up with another solution for the tuple problem, instead of implementing tuple-sub-Any. |
I think we can have both tuple-sub-Any and the reachability optimisation. It won't be as efficient as before since Any now has more subtypes, but people who want performance shouldn't be using Any anyway. |
The bug should be fixed in #1947. |
@Praetonus what's the performance impact on Any usage? We have to use |
There would only be an impact on |
Once the other identity fixes get merged, I will bump the commit here so CI runs again, and merge this if it passes. |
#1947 has been merged. |
After this commit, a tuple is considered a subtype of `Any ${cap}` if all of the elements of the tuple are subcaps of the cap. This is a principle of least surprise issue, as it is surprising that a type param constraint of `Any #any` does not behave the same as an unconstrained type param, with the latter accepting tuple type args, and the latter not doing so. Previously, there was no way to allow tuples of any cardinality as a type argument, while restricting what caps were allowed to be in those tuples (such as for the concerns of aliasing or sendability). For example, `class List[A]` in the `collections` package allowed tuples as type args, but `class List[A: Any #share]` in the `collections/persistent` package did not. Now they both allow tuple type args, and the `Any #share` constrains the type arg so that all tuple elements must be shareable (`val` or `tag`). Resolves #1767.
1f298e9
to
47a03b5
Compare
I've rebased this PR for running on latest master. We'll see how CI goes this time. |
CI is good - I'm merging it. |
After this commit, a tuple is considered a subtype of
Any ${cap}
if all of the elements of the tuple are subcaps of the cap.
This is a principle of least surprise issue, as it is surprising
that a type param constraint of
Any #any
does not behave the sameas an unconstrained type param, with the latter accepting tuple
type args, and the latter not doing so.
Previously, there was no way to allow tuples of any cardinality
as a type argument, while restricting what caps were allowed to
be in those tuples (such as for the concerns of aliasing or
sendability). For example,
class List[A]
in thecollections
package allowed tuples as type args, but
class List[A: Any #share]
in the
collections/persistent
package did not. Now they bothallow tuple type args, and the
Any #share
constrains the type argso that all tuple elements must be shareable (
val
ortag
).Resolves #1767.