From 388d82f6c4e6003a9923fb7d02d885d5de3500ec Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Fri, 14 Jul 2023 22:27:37 +0800 Subject: [PATCH] Also record chained `innervars` 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. --- src/subtype.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-- test/subtype.jl | 7 ++++++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 5b05bb288ffc4a..395ac165a0b2bf 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -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; @@ -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) { diff --git a/test/subtype.jl b/test/subtype.jl index de11689e9e7c46..19901897ebaaad 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -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