From 7442e1843a37d9804bf85382f1464c6b48e93eec Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Sat, 2 Mar 2024 15:29:18 +0800 Subject: [PATCH] typeintersect: more organized innervar wrapping --- src/subtype.c | 39 +++++++++++++++++++++++++++++++++++---- test/subtype.jl | 3 +-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index fddcd036a72a79..f2faca2f054d5a 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -3018,7 +3018,8 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind } if (vb->innervars != NULL) { - for (size_t i = 0; i < jl_array_nrows(vb->innervars); i++) { + size_t len = jl_array_nrows(vb->innervars), count = 0; + for (size_t i = 0; i < len; i++) { jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i); // the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are // iterating 2 trees at once), so once we set `wrap`, there might remain other branches @@ -3033,10 +3034,40 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind if (wrap->innervars == NULL) wrap->innervars = jl_alloc_array_1d(jl_array_any_type, 0); jl_array_ptr_1d_push(wrap->innervars, (jl_value_t*)var); + jl_array_ptr_set(vb->innervars, i, (jl_value_t*)NULL); } - else if (res != jl_bottom_type) { - if (jl_has_typevar(res, var)) - res = jl_type_unionall((jl_tvar_t*)var, res); + } + for (size_t i = 0; i < len; i++) { + jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i); + if (var) { + if (count < i) + jl_array_ptr_set(vb->innervars, count, (jl_value_t*)var); + count++; + } + } + if (count != len) + jl_array_del_end(vb->innervars, len - count); + if (res != jl_bottom_type) { + while (count > 1) { + int changed = 0; + for (size_t i = 0; i < count - 1; i++) { + jl_tvar_t *vari = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i); + for (size_t j = i+1; j < count; j++) { + jl_tvar_t *varj = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, j); + if (jl_has_typevar(varj->lb, vari) || jl_has_typevar(varj->ub, vari)) { + jl_array_ptr_set(vb->innervars, j, (jl_value_t*)vari); + jl_array_ptr_set(vb->innervars, i, (jl_value_t*)varj); + changed = 1; + break; + } + } + if (changed) break; + } + if (!changed) break; + } + for (size_t i = 0; i < count; i++) { + jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i); + res = jl_type_unionall(var, res); } } } diff --git a/test/subtype.jl b/test/subtype.jl index 65661c439683d1..6f0d40dc5e1427 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1216,8 +1216,7 @@ let a = Tuple{T1,T1} where T1, end let a = Val{Tuple{T1,T1}} where T1, b = Val{Tuple{Val{S2},S6}} where S2 where S6 - # @testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T) - @test_broken !Base.has_free_typevars(typeintersect(b, a)) + @testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T) end let a = Tuple{Float64,T3,T4} where T4 where T3, b = Tuple{S2,Tuple{S3},S3} where S2 where S3