Skip to content

Commit

Permalink
Also record chained innervars
Browse files Browse the repository at this point in the history
At present we only record direct `innervars` (`T` -> `S<:Val{T}`). And chained `innervars` might be ignored (`T` -> `S<:Val{V<:T}`\
This commit fix it.
  • Loading branch information
N5N3 committed Jul 14, 2023
1 parent 7662661 commit 388d82f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
56 changes: 54 additions & 2 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -2770,9 +2770,9 @@ static jl_value_t *omit_bad_union(jl_value_t *u, jl_tvar_t *t)
// Caller might not have rooted `res`
static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbinding_t *vb, jl_unionall_t *u, jl_stenv_t *e)
{
jl_value_t *varval = NULL;
jl_value_t *varval = NULL, *ilb = NULL, *iub = NULL;
jl_tvar_t *newvar = vb->var;
JL_GC_PUSH2(&res, &newvar);
JL_GC_PUSH4(&res, &newvar, &ilb, &iub);
// try to reduce var to a single value
if (jl_is_long(vb->ub) && jl_is_typevar(vb->lb)) {
varval = vb->ub;
Expand Down Expand Up @@ -2868,6 +2868,58 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
btemp->ub = jl_new_struct(jl_unionall_type, vb->var, btemp->ub);
assert((jl_value_t*)btemp->var != btemp->ub);
}
// We have checked direct innervars above.
// But `btemp->innervars` might includes tvars depending on vb.
// Check them here.
if (btemp->innervars != NULL) {
for (size_t i = 0; i < jl_array_len(btemp->innervars); i++) {
jl_tvar_t *ivar = (jl_tvar_t*)jl_array_ptr_ref(btemp->innervars, i);
jl_value_t *ilb = ivar->lb, *iub = ivar->ub;
if (jl_has_typevar(btemp->lb, ivar) || jl_has_typevar(btemp->ub, ivar)) {
if (jl_has_typevar(ilb, vb->var)) {
if (varval) {
JL_TRY {
ilb = jl_substitute_var(ilb, vb->var, varval);
}
JL_CATCH {
res = jl_bottom_type;
}
}
else if (btemp->depth0 == vb->depth0 && !jl_has_typevar(vb->lb, btemp->var) && !jl_has_typevar(vb->ub, btemp->var)) {
if (newvar != vb->var)
ilb = jl_substitute_var(ilb, vb->var, (jl_value_t*)newvar);
wrap = btemp;
}
else {
// TODO: This doesn't make any sense.
ilb = jl_new_struct(jl_unionall_type, vb->var, ilb);
}
}
if (jl_has_typevar(iub, vb->var)) {
if (varval) {
JL_TRY {
iub = jl_substitute_var(iub, vb->var, varval);
}
JL_CATCH {
res = jl_bottom_type;
}
}
else if (btemp->depth0 == vb->depth0 && !jl_has_typevar(vb->lb, btemp->var) && !jl_has_typevar(vb->ub, btemp->var)) {
if (newvar != vb->var)
iub = jl_substitute_var(iub, vb->var, (jl_value_t*)newvar);
wrap = btemp;
}
else {
// TODO: This doesn't make any sense.
iub = jl_new_struct(jl_unionall_type, vb->var, iub);
}
}
if (ivar->lb != ilb || ivar->ub != iub) {
jl_array_ptr_set(btemp->innervars, i, (jl_value_t *)jl_new_typevar(ivar->name, ilb, iub));
}
}
}
}
}

if (wrap) {
Expand Down
7 changes: 6 additions & 1 deletion test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2552,8 +2552,13 @@ end
@test !<:(Type{Vector{Union{Base.BitInteger, Base.IEEEFloat, StridedArray, Missing, Nothing, Val{T}}}} where {T}, Type{Array{T}} where {T})

#issue 50195
T50195{S} = Pair{S,Set{S}}
let a = Tuple{Type{X} where X<:Union{Nothing, Val{X1} where {X4, X1<:(Pair{X2, Val{X2}} where X2<:Val{X4})}}},
b = Tuple{Type{Y} where Y<:(Val{Y1} where {Y4<:Src, Y1<:(Pair{Y2, Val{Y2}} where Y2<:Union{Val{Y4}, Y4})})} where Src
@test typeintersect(a, b) <: Any
end

#issue 50195
let a = Tuple{Union{Nothing, Type{Pair{T1}} where T1}}
b = Tuple{Type{X2} where X2<:(Pair{T2, Y2} where {Src, Z2<:Src, Y2<:Union{Val{Z2}, Z2}})} where T2
@test !Base.has_free_typevars(typeintersect(a, b))
end

0 comments on commit 388d82f

Please sign in to comment.