-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Fix some vararg-related subtyping issues #31698
Conversation
d14696e
to
df87943
Compare
Rebased on master to pick up the gc root fix. |
I have more cases to fix that partially correct what's here, so let's do them all at once. |
Current set of tests, I'm trying to fix, beyond what's in this PR:
|
c67d1b5
to
acec9b5
Compare
Note to self: The following is still wrong on this branch:
|
Looks like I need to put the vararg subtyping check back for things like |
We should try to avoid that, since forming those types should not be allowed. |
It comes up in situations like the following:
for which the compiled signature is |
@JeffBezanson This is ready for re-review. |
Linking #30995 here for the |
if (npx != npy || vx || vy) { | ||
if (!vy) { | ||
if (npx != npy || vx != JL_VARARG_NONE || vy) { | ||
if ((vx == JL_VARARG_NONE || vx == JL_VARARG_UNBOUND) && !vy) { |
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.
I think UNBOUND
is computed incorrectly for subtyping's use (iirc, it was introduced for gf.c's heuristic type signature limiting), since it doesn't count number of uses. Consider Tuple{Vararg{NTuple{N}, N} where N}
. To be conservative, just consider jl_is_long
vs jl_is_typevar
in this fast-path.
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.
What the problem with that case? If the RHS is not a vararg, then if we have a unionall here it can't possibly be a subtype.
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.
I don't know. I just don't trust this code to do any counting of TypeVar uses.
I think this fixes #31805? Would be good to add that test case. |
src/subtype.c
Outdated
jl_vararg_kind_t vx = JL_VARARG_NONE; | ||
jl_value_t *vxt = NULL; | ||
int vy = 0; | ||
int vnpx = npx; |
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.
vnpx seems like an odd (too long) mash of letters, since it appears to actually be the number of required (non-var) parameters (nfx for "n fields/fixed of x")
if (npx != npy || vx || vy) { | ||
if (!vy) { | ||
if (npx != npy || vx != JL_VARARG_NONE || vy) { | ||
if ((vx == JL_VARARG_NONE || vx == JL_VARARG_UNBOUND) && !vy) { |
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.
I don't know. I just don't trust this code to do any counting of TypeVar uses.
base/compiler/typelimits.jl
Outdated
return t # t isn't something new | ||
else | ||
ut = unwrap_unionall(t) | ||
if isa(ut, DataType) && ut.name !== unwrap_unionall(Vararg).name && isa(c, Type) && c !== Union{} && c <: t |
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.
Can use Base._va_typename
here.
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.
(Core.Compiler.) _va_typename
, but yes
PkgEval reveals the following incorrect intersection on this branch:
( |
…ararg Upon construction, we normalize `Vararg{T, N} where {T,N}` to `Vararg{T where T, N} where N`, thus there can be at most one UnionAll wrapper around a Vararg. In subtyping we were already assuming that there can be at most two such wrappers, so simply adjust that and add an appropriate assertion to make sure we catch any cases where this ever goes wrong.
Co-Authored-By: Keno <[email protected]>
In subtyping proper, variables introduced on the left (i.e. forall variables) don't have any equality constraints, because we have no syntax for creating them. However, intersection does sometimes create such environments, so we need to handle it in subtyping.
PkgEval is clean now. Will merge. |
Let's backport this to fix #32607 |
* Fix jl_obvious_subtype with INT vararg constraint * Fix a vararg-related non-transitivity in subtyping * Fix another vararg subtype issue * Take advantage of their being at most one UnionAll wrapped around a Vararg Upon construction, we normalize `Vararg{T, N} where {T,N}` to `Vararg{T where T, N} where N`, thus there can be at most one UnionAll wrapper around a Vararg. In subtyping we were already assuming that there can be at most two such wrappers, so simply adjust that and add an appropriate assertion to make sure we catch any cases where this ever goes wrong. * Rewrite subtype_tuple to fix extra cases * Put back the case for naked varargs * Update test/subtype.jl Co-Authored-By: Keno <[email protected]> * Add test for #31805 * Fix style review comments * Rename variable * In person review changes * Fix bug * Handle integer bounds on left arguments in the environment In subtyping proper, variables introduced on the left (i.e. forall variables) don't have any equality constraints, because we have no syntax for creating them. However, intersection does sometimes create such environments, so we need to handle it in subtyping. (Cherry-picked from 4a38e79)
Running PkgEval with the backports branch suggests that this didn't fix the issue |
This is a backport from (a local version of) #31681. Turns out the same subtyping issues I addressed there exist on master, but we just tend to not see those types a whole lot.