Skip to content

Commit

Permalink
inference: correctly handle rare cases when Const wraps `InterCondi…
Browse files Browse the repository at this point in the history
…tional` (#42434)

Otherwise, in rare cases, we may see this sort of weird behavior:
```julia
julia> @eval edgecase(_) = $(Core.Compiler.InterConditional(2, Int, Any))
edgecase (generic function with 1 method)

julia> code_typed((Any,)) do x
           edgecase(x) ? x : nothing
       end
1-element Vector{Any}:
 CodeInfo(
1 ─     goto #3 if not $(QuoteNode(Core.InterConditional(2, Int64, Any)))
2 ─     return x
3 ─     return Main.nothing
) => Any

julia> code_typed((Any,)) do x
           edgecase(x) ? x : nothing
       end
1-element Vector{Any}:
 CodeInfo(
1 ─      goto #3 if not $(QuoteNode(Core.InterConditional(2, Int64, Any)))
2 ─ %2 = π (x, Int64)
└──      return %2
3 ─      return Main.nothing
) => Union{Nothing, Int64}
```
  • Loading branch information
aviatesk authored Oct 1, 2021
1 parent 7f66828 commit d2289e6
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
6 changes: 4 additions & 2 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -785,11 +785,13 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize
rettype = code.rettype
if isdefined(code, :rettype_const)
rettype_const = code.rettype_const
# the second subtyping conditions are necessary to distinguish usual cases
# from rare cases when `Const` wrapped those extended lattice type objects
if isa(rettype_const, Vector{Any}) && !(Vector{Any} <: rettype)
return PartialStruct(rettype, rettype_const), mi
elseif rettype <: Core.OpaqueClosure && isa(rettype_const, PartialOpaque)
elseif isa(rettype_const, PartialOpaque) && rettype <: Core.OpaqueClosure
return rettype_const, mi
elseif isa(rettype_const, InterConditional)
elseif isa(rettype_const, InterConditional) && !(InterConditional <: rettype)
return rettype_const, mi
else
return Const(rettype_const), mi
Expand Down
12 changes: 12 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1819,6 +1819,18 @@ end
Meta.isexpr(x, :call) && return x # x::Expr
return nothing
end == Any[Union{Nothing,Expr}]

# handle the edge case
let ts = @eval Module() begin
edgecase(_) = $(Core.Compiler.InterConditional(2, Int, Any))
# create cache
Base.return_types(edgecase, (Any,))
Base.return_types((Any,)) do x
edgecase(x) ? x : nothing # ::Any
end
end
@test ts == Any[Any]
end
end

@testset "branching on conditional object" begin
Expand Down

0 comments on commit d2289e6

Please sign in to comment.