diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 49f21f59936041..cbe82ffd81e8c5 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1169,26 +1169,22 @@ function analyze_single_call!( end end - # if the signature is fully covered and there is only one applicable method, + # if the signature is fully or mostly covered and there is only one applicable method, # we can try to inline it even if the signature is not a dispatch tuple - if atype <: signature_union - if length(cases) == 0 && only_method isa Method - if length(infos) > 1 - (metharg, methsp) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), - atype, only_method.sig)::SimpleVector - match = MethodMatch(metharg, methsp, only_method, true) - else - meth = meth::MethodLookupResult - @assert length(meth) == 1 - match = meth[1] - end - item = analyze_method!(match, argtypes, state, flag) - item === nothing && return - push!(cases, InliningCase(match.spec_types, item)) - fully_covered = true + if length(cases) == 0 && only_method isa Method + if length(infos) > 1 + (metharg, methsp) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), + atype, only_method.sig)::SimpleVector + match = MethodMatch(metharg, methsp, only_method, true) + else + meth = meth::MethodLookupResult + @assert length(meth) == 1 + match = meth[1] end - else - fully_covered = false + item = analyze_method!(match, argtypes, state, flag) + item === nothing && return + push!(cases, InliningCase(match.spec_types, item)) + fully_covered = atype <: match.spec_types end # If we only have one case and that case is fully covered, we may either diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 36acf4a8d299f2..2e5cd1d621d034 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -817,3 +817,33 @@ let invoke(xs) = validate_unionsplit_inlining(true, xs[1]) @test invoke(Any[10]) === false end + +# issue 43104 + +@inline isGoodType(@nospecialize x::Type) = + x !== Any && !(@noinline Base.has_free_typevars(x)) +let # aggressive static dispatch of single, abstract method match + src = code_typed((Type, Any,)) do x, y + isGoodType(x), isGoodType(y) + end |> only |> first + # both callsite should be inlined + @test count(isinvoke(:has_free_typevars), src.code) == 2 + # `isGoodType(y::Any)` isn't fully covered, thus a runtime type check and fallback dynamic dispatch should be inserted + @test count(iscall((src,isGoodType)), src.code) == 1 +end + +@noinline function checkBadType!(@nospecialize x::Type) + if x === Any || Base.has_free_typevars(x) + println(x) + end + return nothing +end +let # aggressive inlining of single, abstract method match + src = code_typed((Type, Any,)) do x, y + checkBadType!(x), checkBadType!(y) + end |> only |> first + # both callsite should be resolved statically + @test count(isinvoke(:checkBadType!), src.code) == 2 + # `checkBadType!(y::Any)` isn't fully covered, thus a runtime type check and fallback dynamic dispatch should be inserted + @test count(iscall((src,checkBadType!)), src.code) == 1 +end