diff --git a/src/subtype.c b/src/subtype.c index 95c2f01ed6faf..9f6f6cb0add67 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1423,11 +1423,42 @@ static int is_definite_length_tuple_type(jl_value_t *x) static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int *count, int *noRmore); +static int may_contain_union_decision(jl_value_t *x, jl_stenv_t *e, jl_typeenv_t *log) JL_NOTSAFEPOINT +{ + if (x == NULL || x == (jl_value_t*)jl_any_type || x == jl_bottom_type) + return 0; + if (jl_is_unionall(x)) + return may_contain_union_decision(((jl_unionall_t *)x)->body, e, log); + if (jl_is_datatype(x)) { + jl_datatype_t *xd = (jl_datatype_t *)x; + for (int i = 0; i < jl_nparams(xd); i++) { + jl_value_t *param = jl_tparam(xd, i); + if (jl_is_vararg(param)) + param = jl_unwrap_vararg(param); + if (may_contain_union_decision(param, e, log)) + return 1; + } + return 0; + } + if (!jl_is_typevar(x)) + return 1; + jl_typeenv_t *t = log; + while (t != NULL) { + if (x == (jl_value_t *)t->var) + return 1; + t = t->prev; + } + jl_typeenv_t newlog = { (jl_tvar_t*)x, NULL, log }; + jl_varbinding_t *xb = lookup(e, (jl_tvar_t *)x); + return may_contain_union_decision(xb ? xb->lb : ((jl_tvar_t *)x)->lb, e, &newlog) || + may_contain_union_decision(xb ? xb->ub : ((jl_tvar_t *)x)->ub, e, &newlog); +} + static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int limit_slow) { int16_t oldRmore = e->Runions.more; int sub; - if (pick_union_decision(e, 1) == 0) { + if (may_contain_union_decision(y, e, NULL) && pick_union_decision(e, 1) == 0) { jl_saved_unionstate_t oldRunions; push_unionstate(&oldRunions, &e->Runions); e->Lunions.used = e->Runions.used = 0; e->Lunions.depth = e->Runions.depth = 0; diff --git a/test/subtype.jl b/test/subtype.jl index 48b609f7327a0..674608c4d0451 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2436,3 +2436,7 @@ let A = Tuple{Type{T}, T} where T, C = Tuple{Type{MyType47877{W, V} where V<:Union{MyAbstract47877{W}, Base.BitInteger}}, MyType47877{W, V} where V<:Union{MyAbstract47877{W}, Base.BitInteger}} where W<:Base.BitInteger @test typeintersect(B, A) == C end + +let a = (isodd(i) ? Pair{Char, String} : Pair{String, String} for i in 1:2000) + @test Tuple{Type{Pair{Union{Char, String}, String}}, a...} <: Tuple{Type{Pair{K, V}}, Vararg{Pair{A, B} where B where A}} where V where K +end