From 4e60aa2dbe7cf2045fd8be1b6be5e3d8f88a2ffb Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 22 Jun 2018 15:20:39 -0400 Subject: [PATCH 01/11] small workaround checks against incorrect subtyping for kind types for isa_tfunc --- base/compiler/tfuncs.jl | 15 ++++++++++----- base/compiler/typeutils.jl | 8 +++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 036959ccdde9a..22ed40a662b1c 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -53,12 +53,15 @@ add_tfunc(throw, 1, 1, (@nospecialize(x)) -> Bottom, 0) # returns (type, isexact) # if isexact is false, the actual runtime type may (will) be a subtype of t function instanceof_tfunc(@nospecialize(t)) - if t === Bottom || t === typeof(Bottom) - return Bottom, true - elseif isa(t, Const) + if isa(t, Const) if isa(t.val, Type) return t.val, true end + return Bottom, true + end + t = widenconst(t) + if t === Bottom || t === typeof(Bottom) || typeintersect(t, Type) === Bottom + return Bottom, true elseif isType(t) tp = t.parameters[1] return tp, !has_free_typevars(tp) @@ -391,7 +394,7 @@ add_tfunc(isa, 2, 2, if t === Bottom return Const(false) elseif v ⊑ t - if isexact + if isexact && isnotbrokensubtype(v, t) return Const(true) end elseif isa(v, Const) || isa(v, Conditional) || isdispatchelem(v) @@ -399,7 +402,9 @@ add_tfunc(isa, 2, 2, # (ensuring the isa is precise) return Const(false) elseif isexact && typeintersect(v, t) === Bottom - if !iskindtype(v) #= subtyping currently intentionally answers this query incorrectly for kinds =# + # similar to `isnotbrokensubtype` check above, `typeintersect(v, t)` + # can't be trusted for kind types so we do an extra check here + if !iskindtype(v) return Const(false) end end diff --git a/base/compiler/typeutils.jl b/base/compiler/typeutils.jl index 92243ee62dc41..3df1a6d011ff7 100644 --- a/base/compiler/typeutils.jl +++ b/base/compiler/typeutils.jl @@ -31,6 +31,12 @@ function issingletontype(@nospecialize t) return false end +# Subtyping currently intentionally answers certain queries incorrectly for kind types. For +# some of these queries, this check can be used to somewhat protect against making incorrect +# decisions based on incorrect subtyping. Note that this check, itself, is broken for +# certain combinations of `a` and `b` where one/both isa/are `Union`/`UnionAll` type(s)s. +isnotbrokensubtype(a, b) = (!iskindtype(b) || !isType(a) || issingletontype(a.parameters[1])) + argtypes_to_type(argtypes::Array{Any,1}) = Tuple{anymap(widenconst, argtypes)...} function isknownlength(t::DataType) @@ -52,7 +58,7 @@ end # return an upper-bound on type `a` with type `b` removed # such that `return <: a` && `Union{return, b} == Union{a, b}` function typesubtract(@nospecialize(a), @nospecialize(b)) - if a <: b + if a <: b && isnotbrokensubtype(a, b) return Bottom end if isa(a, Union) From 9f71211c6df522ee9c8d43b3af9e7d8478aa076a Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 22 Jun 2018 15:43:50 -0400 Subject: [PATCH 02/11] disable broken emit_isa codegen optimization --- src/cgutils.cpp | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 231655db1f469..5026e63abd3e4 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1060,26 +1060,33 @@ static void emit_type_error(jl_codectx_t &ctx, const jl_cgval_t &x, Value *type, static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *type, const std::string *msg) { - Optional known_isa; jl_value_t *intersected_type = type; - if (x.constant) - known_isa = jl_isa(x.constant, type); - else if (jl_subtype(x.typ, type)) - known_isa = true; - else { - intersected_type = jl_type_intersection(x.typ, type); - if (intersected_type == (jl_value_t*)jl_bottom_type) - known_isa = false; - } - if (known_isa) { - if (!*known_isa && msg) { - emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg); - ctx.builder.CreateUnreachable(); - BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx.f); - ctx.builder.SetInsertPoint(failBB); - } - return std::make_pair(ConstantInt::get(T_int1, *known_isa), true); - } + + // TODO: This optimization suffers from incorrectness issues due to broken subtyping for + // kind types (see https://github.com/JuliaLang/julia/issues/27078). For actual `isa` + // calls, this optimization should already have been performed upstream anyway, but + // having this optimization in codegen might still be beneficial for `typeassert`s + // if we can make it correct. + // + // Optional known_isa; + // if (x.constant) + // known_isa = jl_isa(x.constant, type); + // else if (jl_subtype(x.typ, type)) + // known_isa = true; + // else { + // intersected_type = jl_type_intersection(x.typ, type); + // if (intersected_type == (jl_value_t*)jl_bottom_type) + // known_isa = false; + // } + // if (known_isa) { + // if (!*known_isa && msg) { + // emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg); + // ctx.builder.CreateUnreachable(); + // BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx.f); + // ctx.builder.SetInsertPoint(failBB); + // } + // return std::make_pair(ConstantInt::get(T_int1, *known_isa), true); + // } // intersection with Type needs to be handled specially if (jl_has_intersect_type_not_kind(type)) { From cdf698750ac10de4c56fd2d47cb91905a2b071f3 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 22 Jun 2018 16:28:16 -0400 Subject: [PATCH 03/11] add test for #27078 --- test/compiler/compiler.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 96b14f9b81333..55c2c8c1187ce 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1717,3 +1717,8 @@ Base.iterate(i::Iterator27434, ::Val{2}) = i.z, Val(3) Base.iterate(::Iterator27434, ::Any) = nothing @test @inferred splat27434(Iterator27434(1, 2, 3)) == (1, 2, 3) @test Core.Compiler.return_type(splat27434, Tuple{typeof(Iterators.repeated(1))}) == Union{} + +# issue #27078 +f27078(T::Type{S}) where {S} = isa(T, UnionAll) ? f27078(T.body) : T +T27078 = Vector{Vector{T}} where T +@test f27078(T27078) === T27078.body From 7bec88005ba455e1623a4f3c4001d5d284245049 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 22 Jun 2018 17:48:51 -0400 Subject: [PATCH 04/11] re-enable the nonbroken part of the codegen emit_isa optimization --- src/cgutils.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 5026e63abd3e4..0c3d2c7f3ff29 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1062,15 +1062,16 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, { jl_value_t *intersected_type = type; - // TODO: This optimization suffers from incorrectness issues due to broken subtyping for - // kind types (see https://github.com/JuliaLang/julia/issues/27078). For actual `isa` - // calls, this optimization should already have been performed upstream anyway, but - // having this optimization in codegen might still be beneficial for `typeassert`s - // if we can make it correct. - // - // Optional known_isa; - // if (x.constant) - // known_isa = jl_isa(x.constant, type); + // TODO: The commented-out part of this optimization suffers from incorrectness issues + // due to broken subtyping for kind types (see + // https://github.com/JuliaLang/julia/issues/27078). For actual `isa` calls, this + // optimization should already have been performed upstream anyway, but having this + // optimization in codegen might still be beneficial for `typeassert`s if we can make it + // correct. + Optional known_isa; + if (x.constant) { + known_isa = jl_isa(x.constant, type); + } // else if (jl_subtype(x.typ, type)) // known_isa = true; // else { @@ -1078,15 +1079,15 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, // if (intersected_type == (jl_value_t*)jl_bottom_type) // known_isa = false; // } - // if (known_isa) { - // if (!*known_isa && msg) { - // emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg); - // ctx.builder.CreateUnreachable(); - // BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx.f); - // ctx.builder.SetInsertPoint(failBB); - // } - // return std::make_pair(ConstantInt::get(T_int1, *known_isa), true); - // } + if (known_isa) { + if (!*known_isa && msg) { + emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg); + ctx.builder.CreateUnreachable(); + BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx.f); + ctx.builder.SetInsertPoint(failBB); + } + return std::make_pair(ConstantInt::get(T_int1, *known_isa), true); + } // intersection with Type needs to be handled specially if (jl_has_intersect_type_not_kind(type)) { From a074009db8777bdb5c8f3071310357a2daa22086 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Mon, 25 Jun 2018 15:44:27 -0400 Subject: [PATCH 05/11] update compiler tests --- test/compiler/compiler.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 55c2c8c1187ce..badff30f70dea 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1179,7 +1179,7 @@ let isa_tfunc = Core.Compiler.T_FFUNC_VAL[ @test isa_tfunc(Array{Real}, Type{AbstractArray{Int}}) === Const(false) @test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Real, 2})) === Const(true) @test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Int, 2})) === Const(false) - @test isa_tfunc(DataType, Int) === Bool # could be improved + @test isa_tfunc(DataType, Int) === Const(false) @test isa_tfunc(DataType, Const(Type{Int})) === Bool @test isa_tfunc(DataType, Const(Type{Array})) === Bool @test isa_tfunc(UnionAll, Const(Type{Int})) === Bool # could be improved @@ -1245,7 +1245,7 @@ let subtype_tfunc = Core.Compiler.T_FFUNC_VAL[ @test subtype_tfunc(Type{Union{}}, Union{Type{Int64}, Type{Float64}}) === Const(true) @test subtype_tfunc(Type{Union{}}, Union{Type{T}, Type{Float64}} where T) === Const(true) let c = Conditional(Core.SlotNumber(0), Const(Union{}), Const(Union{})) - @test subtype_tfunc(c, Const(Bool)) === Bool # any result is ok + @test subtype_tfunc(c, Const(Bool)) === Const(true) # any result is ok end @test subtype_tfunc(Type{Val{1}}, Type{Val{T}} where T) === Bool @test subtype_tfunc(Type{Val{1}}, DataType) === Bool From 27d484b32803909bb5e117c0e621873c6721e1e0 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Mon, 25 Jun 2018 16:00:17 -0400 Subject: [PATCH 06/11] fix pretty crazy bug where Type{T}s were inferred as Ts --- base/compiler/abstractinterpretation.jl | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 4c02fbc059b47..5b5e6dac121fd 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -638,19 +638,20 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt if !isa(body, Type) && !isa(body, TypeVar) return Any end - has_free_typevars(body) || return body - if isa(argtypes[2], Const) - tv = argtypes[2].val - elseif isa(argtypes[2], PartialTypeVar) - ptv = argtypes[2] - tv = ptv.tv - canconst = false - else - return Any + if has_free_typevars(body) + if isa(argtypes[2], Const) + tv = argtypes[2].val + elseif isa(argtypes[2], PartialTypeVar) + ptv = argtypes[2] + tv = ptv.tv + canconst = false + else + return Any + end + !isa(tv, TypeVar) && return Any + body = UnionAll(tv, body) end - !isa(tv, TypeVar) && return Any - theunion = UnionAll(tv, body) - ret = canconst ? AbstractEvalConstant(theunion) : Type{theunion} + ret = canconst ? AbstractEvalConstant(body) : Type{body} return ret end return Any From 2f0ff8734d63461fa172575b1d62e33293d48f12 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Sun, 1 Jul 2018 12:30:39 +0200 Subject: [PATCH 07/11] uncomment harmless branch --- src/cgutils.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 0c3d2c7f3ff29..9c4cf3eb90b8c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1062,16 +1062,23 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, { jl_value_t *intersected_type = type; - // TODO: The commented-out part of this optimization suffers from incorrectness issues - // due to broken subtyping for kind types (see - // https://github.com/JuliaLang/julia/issues/27078). For actual `isa` calls, this - // optimization should already have been performed upstream anyway, but having this - // optimization in codegen might still be beneficial for `typeassert`s if we can make it - // correct. Optional known_isa; if (x.constant) { known_isa = jl_isa(x.constant, type); + } else { + intersected_type = jl_type_intersection(x.typ, type); + if (intersected_type == (jl_value_t*)jl_bottom_type) + known_isa = false; } + + // TODO: This commented-out version of the above check suffers from incorrectness + // issues due to broken subtyping for kind types (see + // https://github.com/JuliaLang/julia/issues/27078). For actual `isa` calls, this + // optimization should already have been performed upstream anyway, but having this + // optimization in codegen might still be beneficial for `typeassert`s if we can make it + // correct. + // if (x.constant) { + // known_isa = jl_isa(x.constant, type); // else if (jl_subtype(x.typ, type)) // known_isa = true; // else { @@ -1079,6 +1086,7 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, // if (intersected_type == (jl_value_t*)jl_bottom_type) // known_isa = false; // } + if (known_isa) { if (!*known_isa && msg) { emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg); From daf03d495e60c342eca3c2ff04c057603068edce Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Sun, 1 Jul 2018 13:13:08 +0200 Subject: [PATCH 08/11] make emit_isa change more minimal --- src/cgutils.cpp | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 9c4cf3eb90b8c..af0ca83f28b58 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1060,33 +1060,22 @@ static void emit_type_error(jl_codectx_t &ctx, const jl_cgval_t &x, Value *type, static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *type, const std::string *msg) { - jl_value_t *intersected_type = type; - + // TODO: The subtype check below suffers from incorrectness issues due to broken + // subtyping for kind types (see https://github.com/JuliaLang/julia/issues/27078). For + // actual `isa` calls, this optimization should already have been performed upstream + // anyway, but having this optimization in codegen might still be beneficial for + // `typeassert`s if we can make it correct. Optional known_isa; - if (x.constant) { + jl_value_t *intersected_type = type; + if (x.constant) known_isa = jl_isa(x.constant, type); + else if (jl_subtype(x.typ, type)) { + // known_isa = true; } else { intersected_type = jl_type_intersection(x.typ, type); if (intersected_type == (jl_value_t*)jl_bottom_type) known_isa = false; } - - // TODO: This commented-out version of the above check suffers from incorrectness - // issues due to broken subtyping for kind types (see - // https://github.com/JuliaLang/julia/issues/27078). For actual `isa` calls, this - // optimization should already have been performed upstream anyway, but having this - // optimization in codegen might still be beneficial for `typeassert`s if we can make it - // correct. - // if (x.constant) { - // known_isa = jl_isa(x.constant, type); - // else if (jl_subtype(x.typ, type)) - // known_isa = true; - // else { - // intersected_type = jl_type_intersection(x.typ, type); - // if (intersected_type == (jl_value_t*)jl_bottom_type) - // known_isa = false; - // } - if (known_isa) { if (!*known_isa && msg) { emit_type_error(ctx, x, literal_pointer_val(ctx, type), *msg); From 1811e9163452908ff729122f08dbff7505a41f86 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 6 Jul 2018 15:58:01 +0200 Subject: [PATCH 09/11] try working around broken subtyping in known_isa codegen optimization --- src/cgutils.cpp | 4 ++-- src/julia.h | 1 + src/subtype.c | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index af0ca83f28b58..1d106c5e0c9cc 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1069,8 +1069,8 @@ static std::pair emit_isa(jl_codectx_t &ctx, const jl_cgval_t &x, jl_value_t *intersected_type = type; if (x.constant) known_isa = jl_isa(x.constant, type); - else if (jl_subtype(x.typ, type)) { - // known_isa = true; + else if (jl_is_not_broken_subtype(x.typ, type) && jl_subtype(x.typ, type)) { + known_isa = true; } else { intersected_type = jl_type_intersection(x.typ, type); if (intersected_type == (jl_value_t*)jl_bottom_type) diff --git a/src/julia.h b/src/julia.h index 0540226fe7811..c3d13c3bf31de 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1067,6 +1067,7 @@ JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t); JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, int envsz); JL_DLLEXPORT int jl_isa(jl_value_t *a, jl_value_t *t); JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT; +JL_DLLEXPORT int jl_is_not_broken_subtype(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n); JL_DLLEXPORT jl_value_t *jl_type_intersection(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT int jl_has_empty_intersection(jl_value_t *x, jl_value_t *y); diff --git a/src/subtype.c b/src/subtype.c index e50c8b8c0cb8c..e7dda3aa78a55 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1165,6 +1165,13 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) return jl_subtype(a, b) && jl_subtype(b, a); } +JL_DLLEXPORT int jl_is_not_broken_subtype(jl_value_t *a, jl_value_t *b) +{ + // TODO: the final commented out check here isn't correct; it should be closer to the + // `issingletype` check used by `isnotbrokensubtype` in `base/compiler/typeutils.jl` + return !jl_is_kind(b) || !jl_is_type_type(a); // || jl_is_datatype_singleton((jl_datatype_t*)jl_tparam0(a)); +} + int jl_tuple_isa(jl_value_t **child, size_t cl, jl_datatype_t *pdt) { if (jl_is_tuple_type(pdt) && !jl_is_va_tuple(pdt)) { From 870562262d15de75388bf433866310ed2b9cacaa Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Fri, 6 Jul 2018 17:08:43 +0200 Subject: [PATCH 10/11] a test that was checking for exact/optimal inference result is now broken Justification for allowing this test to remain broken for now: - benchmarking the expression (including downstream toy calculations on the output, e.g. broadcast sin) using BenchmarkTools reveals no actual performance difference - inference returning an optimal result before was probably reliant on the broken subtyping behavior; correctness >>> performance - inference is still returning a fairly tightly bounded, correct Union type --- test/sets.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/sets.jl b/test/sets.jl index 631e2d69c295e..3db0d195e4e1a 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -557,7 +557,8 @@ end x = @inferred replace(x -> x > 1, [1, 2], missing) @test isequal(x, [1, missing]) && x isa Vector{Union{Int, Missing}} - x = @inferred replace([1, missing], missing=>2) + @test_broken @inferred replace([1, missing], missing=>2) + x = replace([1, missing], missing=>2) @test x == [1, 2] && x isa Vector{Int} x = @inferred replace([1, missing], missing=>2, count=1) @test x == [1, 2] && x isa Vector{Union{Int, Missing}} From 223b797e17a76b72f96807e7e94218778e095293 Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Sat, 7 Jul 2018 00:27:12 +0200 Subject: [PATCH 11/11] fix 9765 test --- base/compiler/tfuncs.jl | 18 ++++++++++++------ test/compiler/compiler.jl | 6 +++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 22ed40a662b1c..df72955368341 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -388,12 +388,18 @@ add_tfunc(typeassert, 2, 2, return typeintersect(v, t) end, 4) add_tfunc(isa, 2, 2, - function (@nospecialize(v), @nospecialize(t)) - t, isexact = instanceof_tfunc(t) + function (@nospecialize(v), @nospecialize(tt)) + t, isexact = instanceof_tfunc(tt) + if t === Bottom + # check if t could be equivalent to typeof(Bottom), since that's valid in `isa`, but the set of `v` is empty + # if `t` cannot have instances, it's also invalid on the RHS of isa + if typeintersect(widenconst(tt), Type) === Union{} + return Union{} + end + return Const(false) + end if !has_free_typevars(t) - if t === Bottom - return Const(false) - elseif v ⊑ t + if v ⊑ t if isexact && isnotbrokensubtype(v, t) return Const(true) end @@ -401,7 +407,7 @@ add_tfunc(isa, 2, 2, # this tests for knowledge of a leaftype appearing on the LHS # (ensuring the isa is precise) return Const(false) - elseif isexact && typeintersect(v, t) === Bottom + elseif typeintersect(v, t) === Bottom # similar to `isnotbrokensubtype` check above, `typeintersect(v, t)` # can't be trusted for kind types so we do an extra check here if !iskindtype(v) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index badff30f70dea..93917154f5c52 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1179,7 +1179,7 @@ let isa_tfunc = Core.Compiler.T_FFUNC_VAL[ @test isa_tfunc(Array{Real}, Type{AbstractArray{Int}}) === Const(false) @test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Real, 2})) === Const(true) @test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Int, 2})) === Const(false) - @test isa_tfunc(DataType, Int) === Const(false) + @test isa_tfunc(DataType, Int) === Union{} @test isa_tfunc(DataType, Const(Type{Int})) === Bool @test isa_tfunc(DataType, Const(Type{Array})) === Bool @test isa_tfunc(UnionAll, Const(Type{Int})) === Bool # could be improved @@ -1189,7 +1189,7 @@ let isa_tfunc = Core.Compiler.T_FFUNC_VAL[ @test isa_tfunc(typeof(Union{}), Const(Int)) === Const(false) # any result is ok @test isa_tfunc(typeof(Union{}), Const(Union{})) === Const(false) @test isa_tfunc(typeof(Union{}), typeof(Union{})) === Const(false) - @test isa_tfunc(typeof(Union{}), Union{}) === Const(false) # any result is ok + @test isa_tfunc(typeof(Union{}), Union{}) === Union{} # any result is ok @test isa_tfunc(typeof(Union{}), Type{typeof(Union{})}) === Const(true) @test isa_tfunc(typeof(Union{}), Const(typeof(Union{}))) === Const(true) let c = Conditional(Core.SlotNumber(0), Const(Union{}), Const(Union{})) @@ -1204,7 +1204,7 @@ let isa_tfunc = Core.Compiler.T_FFUNC_VAL[ @test isa_tfunc(Val{1}, Type{Val{T}} where T) === Bool @test isa_tfunc(Val{1}, DataType) === Bool @test isa_tfunc(Any, Const(Any)) === Const(true) - @test isa_tfunc(Any, Union{}) === Const(false) # any result is ok + @test isa_tfunc(Any, Union{}) === Union{} # any result is ok @test isa_tfunc(Any, Type{Union{}}) === Const(false) @test isa_tfunc(Union{Int64, Float64}, Type{Real}) === Const(true) @test isa_tfunc(Union{Int64, Float64}, Type{Integer}) === Bool