Skip to content

Commit

Permalink
inference: fix JuliaLang#42090, make sure not to wrap Conditional i…
Browse files Browse the repository at this point in the history
…n `PartialStruct` (JuliaLang#42091)
  • Loading branch information
aviatesk authored and LilithHafner committed Feb 22, 2022
1 parent 7ee4fd6 commit cfefebe
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
2 changes: 1 addition & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1536,7 +1536,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
anyconst = false
allconst = true
for i = 2:length(e.args)
at = abstract_eval_value(interp, e.args[i], vtypes, sv)
at = widenconditional(abstract_eval_value(interp, e.args[i], vtypes, sv))
if !anyconst
anyconst = has_nontrivial_const_info(at)
end
Expand Down
33 changes: 28 additions & 5 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1827,16 +1827,39 @@ end
return c, d # ::Tuple{Int,Int}
end == Any[Tuple{Int,Int}]

# shouldn't use the old constraint when the subject of condition has changed
# should invalidate old constraint when the subject of condition has changed
@test Base.return_types((Union{Nothing,Int},)) do a
b = a === nothing
c = b ? 0 : a # c::Int
cond = a === nothing
r1 = cond ? 0 : a # r1::Int
a = 0
d = b ? a : 1 # d::Int, not d::Union{Nothing,Int}
return c, d # ::Tuple{Int,Int}
r2 = cond ? a : 1 # r2::Int, not r2::Union{Nothing,Int}
return r1, r2 # ::Tuple{Int,Int}
end == Any[Tuple{Int,Int}]
end

# https://github.com/JuliaLang/julia/issues/42090#issuecomment-911824851
# `PartialStruct` shoudln't wrap `Conditional`
let M = Module()
@eval M begin
struct BePartialStruct
val::Int
cond
end
end

rt = @eval M begin
Base.return_types((Union{Nothing,Int},)) do a
cond = a === nothing
obj = $(Expr(:new, M.BePartialStruct, 42, :cond))
r1 = getfield(obj, :cond) ? 0 : a # r1::Union{Nothing,Int}, not r1::Int (because PartialStruct doesn't wrap Conditional)
a = $(gensym(:anyvar))::Any
r2 = getfield(obj, :cond) ? a : nothing # r2::Any, not r2::Const(nothing) (we don't need to worry about constrait invalidation here)
return r1, r2 # ::Tuple{Union{Nothing,Int},Any}
end |> only
end
@test rt == Tuple{Union{Nothing,Int},Any}
end

@testset "conditional constraint propagation from non-`Conditional` object" begin
@test Base.return_types((Bool,)) do b
if b
Expand Down

0 comments on commit cfefebe

Please sign in to comment.