From 162521dc71b96c39ba06a9c52e62e0b024474507 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Wed, 20 Sep 2023 22:00:16 +0900 Subject: [PATCH] inference: follow up the `Vararg` fix in `abstract_call_unionall` Follows up #51393. --- base/compiler/abstractinterpretation.jl | 62 +++++++++++++------------ test/compiler/inference.jl | 8 ++++ 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index e82e1e974df489..038feae44e699a 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1853,44 +1853,46 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs end function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{Any}, call::CallMeta) - if length(argtypes) == 3 - canconst = true + na = length(argtypes) + if isvarargtype(argtypes[end]) + 3 ≤ na ≤ 4 || return CallMeta(Any, EFFECTS_THROWS, call.info) + a2 = argtypes[2] + a3 = unwrapva(argtypes[3]) + nothrow = false + elseif na == 3 a2 = argtypes[2] a3 = argtypes[3] ⊑ᵢ = ⊑(typeinf_lattice(interp)) - if isvarargtype(a3) - a3 = unwrapva(a3) - nothrow = false - else - nothrow = a2 ⊑ᵢ TypeVar && (a3 ⊑ᵢ Type || a3 ⊑ᵢ TypeVar) - end - if isa(a3, Const) - body = a3.val - elseif isType(a3) - body = a3.parameters[1] + nothrow = a2 ⊑ᵢ TypeVar && (a3 ⊑ᵢ Type || a3 ⊑ᵢ TypeVar) + else + return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo()) + end + canconst = true + if isa(a3, Const) + body = a3.val + elseif isType(a3) + body = a3.parameters[1] + canconst = false + else + return CallMeta(Any, Effects(EFFECTS_TOTAL; nothrow), call.info) + end + if !(isa(body, Type) || isa(body, TypeVar)) + return CallMeta(Any, EFFECTS_THROWS, call.info) + end + if has_free_typevars(body) + if isa(a2, Const) + tv = a2.val + elseif isa(a2, PartialTypeVar) + tv = a2.tv canconst = false else - return CallMeta(Any, Effects(EFFECTS_TOTAL; nothrow), call.info) - end - if !(isa(body, Type) || isa(body, TypeVar)) return CallMeta(Any, EFFECTS_THROWS, call.info) end - if has_free_typevars(body) - if isa(a2, Const) - tv = a2.val - elseif isa(a2, PartialTypeVar) - tv = a2.tv - canconst = false - else - return CallMeta(Any, EFFECTS_THROWS, call.info) - end - isa(tv, TypeVar) || return CallMeta(Any, EFFECTS_THROWS, call.info) - body = UnionAll(tv, body) - end - ret = canconst ? Const(body) : Type{body} - return CallMeta(ret, Effects(EFFECTS_TOTAL; nothrow), call.info) + isa(tv, TypeVar) || return CallMeta(Any, EFFECTS_THROWS, call.info) + body = UnionAll(tv, body) end - return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo()) + ret = canconst ? Const(body) : Type{body} + return CallMeta(ret, Effects(EFFECTS_TOTAL; nothrow), call.info) end function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, si::StmtInfo, sv::AbsIntState) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index e69b7ed864e9a4..822f5a9a1aa221 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5235,3 +5235,11 @@ end |> only == Val{true} @test code_typed() do b{c} = d... end |> only |> first isa Core.CodeInfo + +abstract_call_unionall_vararg(some::Some{Any}) = UnionAll(some.value...) +@test only(Base.return_types(abstract_call_unionall_vararg)) !== Union{} +let TV = TypeVar(:T) + t = Vector{TV} + some = Some{Any}((TV, t)) + @test abstract_call_unionall_vararg(some) isa UnionAll +end