diff --git a/src/subtype.c b/src/subtype.c index 1c6d3ffb2e8de..7af4e8b28b934 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -477,12 +477,42 @@ static int obviously_disjoint(jl_value_t *a, jl_value_t *b, int specificity) return 0; } +static int is_any_like(jl_value_t* x, jl_typeenv_t *env) JL_NOTSAFEPOINT +{ + if (x == (jl_value_t *)jl_any_type) + return 1; + if (jl_is_uniontype(x)) + return is_any_like(((jl_uniontype_t*)x)->a, env) || + is_any_like(((jl_uniontype_t*)x)->b, env); + if (jl_is_unionall(x)) { + jl_unionall_t *ua = (jl_unionall_t*)x; + jl_typeenv_t newenv = { ua->var, NULL, env }; + return is_any_like(ua->body, &newenv); + } + if (jl_is_typevar(x) && env != NULL) { + jl_tvar_t *v = (jl_tvar_t *)x; + if (v->lb != jl_bottom_type) + return 0; + int in_env = 0; + jl_typeenv_t *vs = env; + while (vs != NULL) { + in_env = vs->var == v; + if (in_env) break; + vs = vs->prev; + } + return in_env && is_any_like(v->ub, env); + } + return 0; +} + // compute a least upper bound of `a` and `b` static jl_value_t *simple_join(jl_value_t *a, jl_value_t *b) { - if (a == jl_bottom_type || b == (jl_value_t*)jl_any_type || obviously_egal(a,b)) + if (is_any_like(a, NULL) || is_any_like(b, NULL)) + return (jl_value_t *)jl_any_type; + if (a == jl_bottom_type || obviously_egal(a,b)) return b; - if (b == jl_bottom_type || a == (jl_value_t*)jl_any_type) + if (b == jl_bottom_type) return a; if (!(jl_is_type(a) || jl_is_typevar(a)) || !(jl_is_type(b) || jl_is_typevar(b))) return (jl_value_t*)jl_any_type; diff --git a/test/subtype.jl b/test/subtype.jl index a88ba8e3f0f76..a182bb99909ee 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2317,6 +2317,12 @@ let S = Tuple{Int, Vararg{Val{C} where C<:Union{Complex{R}, R}}} where R @test_broken typeintersect(T, S) == I end +#issue #47874:case3 +let S = Tuple{Int, Tuple{Vararg{Val{C1} where C1<:Union{Complex{R1}, R1}}} where R1<:(Union{Real, V1} where V1), Tuple{Vararg{Val{C2} where C2<:Union{Complex{R2}, Complex{R3}, R3}}} where {R2<:(Union{Real, V2} where V2), R3<:Union{Complex{R2}, Real, R2}}}, + T = Tuple{Any, Tuple{Vararg{Val{CC1} where CC1<:Union{Complex{R}, R}}}, Tuple{Vararg{Val{CC2} where CC2<:Union{Complex{R}, R}}}} where R<:Real + @testintersect(S, T, !Union{}) +end + let S = Tuple{T2, V2} where {T2, N2, V2<:(Array{S2, N2} where {S2 <: T2})}, T = Tuple{V1, T1} where {T1, N1, V1<:(Array{S1, N1} where {S1 <: T1})} @testintersect(S, T, !Union{})