From fce9a3b82e89102965f3e10a7ee527af558b24a2 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 10 Jan 2023 20:53:17 -0500 Subject: [PATCH] WIP: fix #47658, state stack overflow on unions containing typevars --- src/subtype.c | 16 ++++++++++++++++ test/subtype.jl | 20 ++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 7af4e8b28b934..6ac247465d76b 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1243,6 +1243,19 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in return ans; } +static int equal_unions(jl_uniontype_t *x, jl_uniontype_t *y, jl_stenv_t *e) +{ + jl_value_t *saved=NULL; jl_savedenv_t se; + JL_GC_PUSH1(&saved); + save_env(e, &saved, &se); + int eq = forall_exists_equal(x->a, y->a, e) && forall_exists_equal(x->b, y->b, e); + if (!eq) + restore_env(e, saved, &se); + free_env(&se); + JL_GC_POP(); + return eq; +} + // `param` means we are currently looking at a parameter of a type constructor // (as opposed to being outside any type constructor, or comparing variable bounds). // this is used to record the positions where type variables occur for the @@ -1432,6 +1445,9 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) (is_definite_length_tuple_type(x) && is_indefinite_length_tuple_type(y))) return 0; + if (jl_is_uniontype(x) && jl_is_uniontype(y) && equal_unions((jl_uniontype_t*)x, (jl_uniontype_t*)y, e)) + return 1; + jl_saved_unionstate_t oldLunions; push_unionstate(&oldLunions, &e->Lunions); e->Lunions.used = 0; int sub; diff --git a/test/subtype.jl b/test/subtype.jl index a182bb99909ee..d364c2f6292a4 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2352,6 +2352,16 @@ let S = Tuple{Type{T1}, T1, Val{T1}} where T1<:(Val{S1} where S1<:Val), @test_broken I2 <: T end +@test only(intersection_env(Val{Union{Val{Val{T}} where {T},Int}}, Val{Union{T,Int}} where T)[2]) === Val{Val{T}} where {T} + +# issue 47654 +Vec47654{T} = Union{AbstractVector{T}, AbstractVector{Union{T,Nothing}}} +struct Wrapper47654{T, V<:Vec47654{T}} + v::V +end +abstract type P47654{A} end +@test Wrapper47654{P47654, Vector{Union{P47654,Nothing}}} <: Wrapper47654 + @testset "known subtype/intersect issue" begin #issue 45874 # Causes a hang due to jl_critical_error calling back into malloc... @@ -2362,7 +2372,7 @@ end # end #issue 44395 - @test_broken typeintersect( + @test typeintersect( Tuple{Type{T}, T} where {T <: Vector{Union{T, R}} where {R<:Real, T<:Real}}, Tuple{Type{Vector{Union{T, R}}}, Matrix{Union{T, R}}} where {R<:Real, T<:Real}, ) === Union{} @@ -2389,7 +2399,7 @@ end @test_broken typeintersect(Tuple{Type{Tuple{T,Val{T}}}, Val{T}} where T, Tuple{Type{Tuple{Val{T},T}}, Val{T}} where T) <: Any # issue 24333 - @test_broken (Type{Union{Ref,Cvoid}} <: Type{Union{T,Cvoid}} where T) + @test (Type{Union{Ref,Cvoid}} <: Type{Union{T,Cvoid}} where T) # issue 22123 t1 = Ref{Ref{Ref{Union{Int64, T}}} where T} @@ -2400,6 +2410,12 @@ end @test_broken (Tuple{T1,T1} where T1<:(Val{T2} where T2)) <: (Tuple{Val{S},Val{S}} where S) end +# issue #47658 +let T = Ref{NTuple{8, Ref{Union{Int, P}}}} where P, + S = Ref{NTuple{8, Ref{Union{Int, P}}}} where P + @test T <: Union{Int, S} +end + @test !(Tuple{Any, Any, Any} <: Tuple{Any, Vararg{T}} where T) abstract type MyAbstract47877{C}; end