Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inference: follow up the Vararg fix in abstract_call_unionall #51403

Merged
merged 1 commit into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 36 additions & 30 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1853,44 +1853,50 @@ 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])
if na ≤ 2
return CallMeta(Any, EFFECTS_THROWS, call.info)
elseif na > 4
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
end
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)
Expand Down
8 changes: 8 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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