From 40c51653972c4103f29cc8a384641646f2f85b16 Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Wed, 10 Aug 2022 14:32:53 +0800 Subject: [PATCH 1/5] Remove unneeded branch `R` is always false here. --- src/subtype.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index c01ee54e683be..42330bb0b1e5a 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -800,10 +800,8 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // TODO: substitute the value (if any) of this variable into previous envout entries } } - else { - ans = R ? subtype(t, u->body, e, param) : - subtype(u->body, t, e, param); - } + else + ans = subtype(u->body, t, e, param); // handle the "diagonal dispatch" rule, which says that a type var occurring more // than once, and only in covariant position, is constrained to concrete types. E.g. From afff62ab39e23ecc5fe0200f37ce7edce7767bac Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Thu, 11 Aug 2022 10:45:40 +0800 Subject: [PATCH 2/5] Preserve all `envout` if there's remaining `Runions` --- src/subtype.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 42330bb0b1e5a..0f5ebc7139a5f 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1388,10 +1388,18 @@ static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_value_ e->Lunions.more = 0; if (subtype(x, y, e, param)) return 1; - restore_env(e, saved, se); int set = e->Runions.more; - if (!set) + if (set) { + // We preserve `envout` here as `subtype_unionall` needs previous assigned env values. + int oldidx = e->envidx; + e->envidx = e->envsz; + restore_env(e, saved, se); + e->envidx = oldidx; + } + else { + restore_env(e, saved, se); return 0; + } for (int i = set; i <= lastset; i++) statestack_set(&e->Runions, i, 0); lastset = set - 1; From 77610201d16704042ac73d95982c41cc62e2d611 Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Thu, 11 Aug 2022 10:54:15 +0800 Subject: [PATCH 3/5] Only update `envout` if `ans == true` --- src/subtype.c | 53 ++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 0f5ebc7139a5f..36c69069f09f1 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -773,33 +773,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // widen Type{x} to typeof(x) in argument position if (!vb.occurs_inv) vb.lb = widen_Type(vb.lb); - // fill variable values into `envout` up to `envsz` - if (e->envidx < e->envsz) { - jl_value_t *val; - if (vb.intvalued && vb.lb == (jl_value_t*)jl_any_type) - val = (jl_value_t*)jl_wrap_vararg(NULL, NULL); - else if (!vb.occurs_inv && vb.lb != jl_bottom_type) - val = is_leaf_bound(vb.lb) ? vb.lb : (jl_value_t*)jl_new_typevar(u->var->name, jl_bottom_type, vb.lb); - else if (vb.lb == vb.ub) - val = vb.lb; - else if (vb.lb != jl_bottom_type) - // TODO: for now return the least solution, which is what - // method parameters expect. - val = vb.lb; - else if (vb.lb == u->var->lb && vb.ub == u->var->ub) - val = (jl_value_t*)u->var; - else - val = (jl_value_t*)jl_new_typevar(u->var->name, vb.lb, vb.ub); - jl_value_t *oldval = e->envout[e->envidx]; - // if we try to assign different variable values (due to checking - // multiple union members), consider the value unknown. - if (oldval && !jl_egal(oldval, val)) - e->envout[e->envidx] = (jl_value_t*)u->var; - else - e->envout[e->envidx] = fix_inferred_var_bound(u->var, val); - // TODO: substitute the value (if any) of this variable into previous envout entries } - } else ans = subtype(u->body, t, e, param); @@ -848,6 +822,33 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 } } + // fill variable values into `envout` up to `envsz` + if (R && ans && e->envidx < e->envsz) { + jl_value_t *val; + if (vb.intvalued && vb.lb == (jl_value_t*)jl_any_type) + val = (jl_value_t*)jl_wrap_vararg(NULL, NULL); + else if (!vb.occurs_inv && vb.lb != jl_bottom_type) + val = is_leaf_bound(vb.lb) ? vb.lb : (jl_value_t*)jl_new_typevar(u->var->name, jl_bottom_type, vb.lb); + else if (vb.lb == vb.ub) + val = vb.lb; + else if (vb.lb != jl_bottom_type) + // TODO: for now return the least solution, which is what + // method parameters expect. + val = vb.lb; + else if (vb.lb == u->var->lb && vb.ub == u->var->ub) + val = (jl_value_t*)u->var; + else + val = (jl_value_t*)jl_new_typevar(u->var->name, vb.lb, vb.ub); + jl_value_t *oldval = e->envout[e->envidx]; + // if we try to assign different variable values (due to checking + // multiple union members), consider the value unknown. + if (oldval && !jl_egal(oldval, val)) + e->envout[e->envidx] = (jl_value_t*)u->var; + else + e->envout[e->envidx] = fix_inferred_var_bound(u->var, val); + // TODO: substitute the value (if any) of this variable into previous envout entries + } + JL_GC_POP(); return ans; } From 9026ee8aaf120a4f1b4808c40d4847238ce438fa Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Thu, 11 Aug 2022 10:45:35 +0800 Subject: [PATCH 4/5] Add test. Update subtype.jl --- test/arrayops.jl | 9 +++------ test/subtype.jl | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/test/arrayops.jl b/test/arrayops.jl index d4634a393aa86..40473a363f41f 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1203,10 +1203,9 @@ end @test o == fill(1, 3, 4) # issue #18524 - # m = mapslices(x->tuple(x), [1 2; 3 4], dims=1) # see variations of this below - # ERROR: fatal error in type inference (type bound), https://github.com/JuliaLang/julia/issues/43064 - # @test m[1,1] == ([1,3],) - # @test m[1,2] == ([2,4],) + m = mapslices(x->tuple(x), [1 2; 3 4], dims=1) # see variations of this below + @test m[1,1] == ([1,3],) + @test m[1,2] == ([2,4],) r = rand(Int8, 4,5,2) @test vec(mapslices(repr, r, dims=(2,1))) == map(repr, eachslice(r, dims=3)) @@ -1216,8 +1215,6 @@ end # failures @test_broken @inferred(mapslices(tuple, [1 2; 3 4], dims=1)) == [([1, 3],) ([2, 4],)] @test_broken @inferred(mapslices(transpose, r, dims=(1,3))) == permutedims(r, (3,2,1)) - # ERROR: fatal error in type inference (type bound), https://github.com/JuliaLang/julia/issues/43064 - @test_broken @inferred(mapslices(x -> tuple(x), [1 2; 3 4], dims=1)) == [([1, 3],) ([2, 4],)] # re-write, #40996 @test_throws ArgumentError mapslices(identity, rand(2,3), dims=0) # previously BoundsError diff --git a/test/subtype.jl b/test/subtype.jl index b13dcdfa7a83a..a9c54e8df30bc 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2020,3 +2020,30 @@ end #issue #43082 struct X43082{A, I, B<:Union{Ref{I},I}}; end @testintersect(Tuple{X43082{T}, Int} where T, Tuple{X43082{Int}, Any}, Tuple{X43082{Int}, Int}) + +# issue #43064 +let + env_tuple(@nospecialize(x), @nospecialize(y)) = (intersection_env(x, y)[2]...,) + all_var(x::UnionAll) = (x.var, all_var(x.body)...) + all_var(x::DataType) = () + TT0 = Tuple{Type{T},Union{Real,Missing,Nothing}} where {T} + TT1 = Union{Type{Int8},Type{Int16}} + @test env_tuple(Tuple{TT1,Missing}, TT0) === + env_tuple(Tuple{TT1,Nothing}, TT0) === + env_tuple(Tuple{TT1,Int}, TT0) === all_var(TT0) + + TT0 = Tuple{T1,T2,Union{Real,Missing,Nothing}} where {T1,T2} + TT1 = Tuple{T1,T2,Union{Real,Missing,Nothing}} where {T2,T1} + TT2 = Tuple{Union{Int,Int8},Union{Int,Int8},Int} + TT3 = Tuple{Int,Union{Int,Int8},Int} + @test env_tuple(TT2, TT0) === all_var(TT0) + @test env_tuple(TT2, TT1) === all_var(TT1) + @test env_tuple(TT3, TT0) === Base.setindex(all_var(TT0), Int, 1) + @test env_tuple(TT3, TT1) === Base.setindex(all_var(TT1), Int, 2) + + TT0 = Tuple{T1,T2,T1,Union{Real,Missing,Nothing}} where {T1,T2} + TT1 = Tuple{T1,T2,T1,Union{Real,Missing,Nothing}} where {T2,T1} + TT2 = Tuple{Int,Union{Int,Int8},Int,Int} + @test env_tuple(TT2, TT0) === Base.setindex(all_var(TT0), Int, 1) + @test env_tuple(TT2, TT1) === Base.setindex(all_var(TT1), Int, 2) +end From 17ded1f33f8f8cbc369b335ed5bdb38376ec441c Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Fri, 2 Sep 2022 13:46:28 +0800 Subject: [PATCH 5/5] add trailing newline --- test/subtype.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/subtype.jl b/test/subtype.jl index 24785760df5da..8bd720b5e86b0 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2160,4 +2160,4 @@ let TT2 = Tuple{Int,Union{Int,Int8},Int,Int} @test env_tuple(TT2, TT0) === Base.setindex(all_var(TT0), Int, 1) @test env_tuple(TT2, TT1) === Base.setindex(all_var(TT1), Int, 2) -end \ No newline at end of file +end