Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Aug 9, 2021
1 parent 9368bad commit f3ec252
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 10 deletions.
6 changes: 5 additions & 1 deletion base/compiler/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ function subst_trivial_bounds(@nospecialize(atypes))
end
v = atypes.var
if isconcretetype(v.ub) || v.lb === v.ub
return subst_trivial_bounds(atypes{v.ub})
try
return subst_trivial_bounds(atypes{v.ub})
catch
# Note in rare cases a var bound might not be valid to substitute.
end
end
return UnionAll(v, subst_trivial_bounds(atypes.body))
end
Expand Down
16 changes: 9 additions & 7 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ typedef struct jl_varbinding_t {
int8_t concrete; // 1 if another variable has a constraint forcing this one to be concrete
// constraintkind: in covariant position, we try three different ways to compute var ∩ type:
// let ub = var.ub ∩ type
// 0 - var.ub <: type ? (var.ub = ub; return var) : ub
// 0 - var.ub <: type ? var : ub
// 1 - var.ub = ub; return var
// 2 - either (var.ub = ub; return var), or return ub
int8_t constraintkind;
Expand Down Expand Up @@ -2289,7 +2289,6 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int
if (bb->constraintkind == 0) {
JL_GC_PUSH1(&ub);
if (!jl_is_typevar(a) && try_subtype_in_env(bb->ub, a, e, 0, d)) {
set_bound(&bb->ub, ub, b, e);
JL_GC_POP();
return (jl_value_t*)b;
}
Expand Down Expand Up @@ -2352,7 +2351,7 @@ static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want
}

// Caller might not have rooted `res`
static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbinding_t *vb, jl_stenv_t *e)
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_tvar_t *newvar = vb->var;
Expand All @@ -2365,7 +2364,10 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
// given x<:T<:x, substitute x for T
varval = vb->ub;
}
else if (!vb->occurs_inv && is_leaf_bound(vb->ub)) {
// TODO: `vb.occurs_cov == 1` here allows substituting Tuple{<:X} => Tuple{X},
// which is valid but changes some ambiguity errors so we don't need to do it yet.
else if ((/*vb->occurs_cov == 1 || */is_leaf_bound(vb->ub)) &&
!var_occurs_invariant(u->body, u->var, 0)) {
// replace T<:x with x in covariant position when possible
varval = vb->ub;
}
Expand Down Expand Up @@ -2554,7 +2556,7 @@ static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv
}
if (res != jl_bottom_type)
// res is rooted by callee
res = finish_unionall(res, vb, e);
res = finish_unionall(res, vb, u, e);
JL_GC_POP();
return res;
}
Expand Down Expand Up @@ -2977,9 +2979,9 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa
else
lb = simple_join(xlb, ylb);
if (yy) {
if (!subtype_by_bounds(lb, y, e))
if (!reachable_var(lb, (jl_tvar_t*)y, e))
yy->lb = lb;
if (!subtype_by_bounds(y, ub, e))
if (!reachable_var(ub, (jl_tvar_t*)y, e))
yy->ub = ub;
assert(yy->ub != y);
assert(yy->lb != y);
Expand Down
14 changes: 12 additions & 2 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,10 @@ function test_intersection()
Bottom)
@testintersect(Tuple{Type{Z},Z} where Z,
Tuple{Type{Ref{T}} where T, Ref{Float64}},
Tuple{Type{Ref{Float64}}, Ref{Float64}})
!Bottom)
@test_broken typeintersect(Tuple{Type{Z},Z} where Z,
Tuple{Type{Ref{T}} where T, Ref{Float64}}) ==
Tuple{Type{Ref{Float64}},Ref{Float64}}

# issue #32607
@testintersect(Type{<:Tuple{Integer,Integer}},
Expand Down Expand Up @@ -1801,7 +1804,7 @@ let X1 = Tuple{AlmostLU, Vector{T}} where T,
# TODO: the quality of this intersection is not great; for now just test that it
# doesn't stack overflow
@test I<:X1 || I<:X2
actual = Tuple{AlmostLU{S, X} where X<:Matrix{S}, Vector{S}} where S<:Union{Float32, Float64}
actual = Tuple{Union{AlmostLU{S, X} where X<:Matrix{S}, AlmostLU{S, <:Matrix}}, Vector{S}} where S<:Union{Float32, Float64}
@test I == actual
end

Expand Down Expand Up @@ -1938,3 +1941,10 @@ let A = Tuple{Dict{I,T}, I, T} where T where I,
# TODO: we should probably have I == T here
@test typeintersect(A, B) == Tuple{Dict{I,T}, I, T} where {I, T}
end

let A = Tuple{UnionAll, Vector{Any}},
B = Tuple{Type{T}, T} where T<:AbstractArray,
I = typeintersect(A, B)
@test !isconcretetype(I)
@test_broken I == Tuple{Type{T}, Vector{Any}} where T<:AbstractArray
end

0 comments on commit f3ec252

Please sign in to comment.