Skip to content

Commit

Permalink
inference: update exc_bestguess when seeing unsafe GotoIfNot (Jul…
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk authored and mkitti committed Dec 9, 2023
1 parent 5d0d300 commit e0dfd9b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 29 deletions.
60 changes: 31 additions & 29 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3073,16 +3073,38 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState,
end
end

function propagate_to_error_handler!(frame::InferenceState, currpc::Int, W::BitSet, 𝕃ᵢ::AbstractLattice, currstate::VarTable)
function update_exc_bestguess!(@nospecialize(exct), frame::InferenceState, 𝕃ₚ::AbstractLattice)
cur_hand = frame.handler_at[frame.currpc][1]
if cur_hand == 0
if !(𝕃ₚ, exct, frame.exc_bestguess)
frame.exc_bestguess = tmerge(𝕃ₚ, frame.exc_bestguess, exct)
update_cycle_worklists!(frame) do caller::InferenceState, caller_pc::Int
caller_handler = caller.handler_at[caller_pc][1]
caller_exct = caller_handler == 0 ?
caller.exc_bestguess : caller.handlers[caller_handler].exct
return caller_exct !== Any
end
end
else
handler_frame = frame.handlers[cur_hand]
if !(𝕃ₚ, exct, handler_frame.exct)
handler_frame.exct = tmerge(𝕃ₚ, handler_frame.exct, exct)
enter = frame.src.code[handler_frame.enter_idx]::Expr
exceptbb = block_for_inst(frame.cfg, enter.args[1]::Int)
push!(frame.ip, exceptbb)
end
end
end

function propagate_to_error_handler!(currstate::VarTable, frame::InferenceState, 𝕃ᵢ::AbstractLattice)
# If this statement potentially threw, propagate the currstate to the
# exception handler, BEFORE applying any state changes.
cur_hand = frame.handler_at[currpc][1]
cur_hand = frame.handler_at[frame.currpc][1]
if cur_hand != 0
enter = frame.src.code[frame.handlers[cur_hand].enter_idx]::Expr
l = enter.args[1]::Int
exceptbb = block_for_inst(frame.cfg, l)
exceptbb = block_for_inst(frame.cfg, enter.args[1]::Int)
if update_bbstate!(𝕃ᵢ, frame, exceptbb, currstate)
push!(W, exceptbb)
push!(frame.ip, exceptbb)
end
end
end
Expand Down Expand Up @@ -3152,7 +3174,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
if nothrow
add_curr_ssaflag!(frame, IR_FLAG_NOTHROW)
else
propagate_to_error_handler!(frame, currpc, W, 𝕃ᵢ, currstate)
update_exc_bestguess!(TypeError, frame, ipo_lattice(interp))
propagate_to_error_handler!(currstate, frame, 𝕃ᵢ)
merge_effects!(interp, frame, EFFECTS_THROWS)
end

Expand Down Expand Up @@ -3233,31 +3256,10 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
(; changes, rt, exct) = abstract_eval_basic_statement(interp,
stmt, currstate, frame)
if exct !== Union{}
𝕃ₚ = ipo_lattice(interp)
cur_hand = frame.handler_at[currpc][1]
if cur_hand == 0
if !(𝕃ₚ, exct, frame.exc_bestguess)
frame.exc_bestguess = tmerge(𝕃ₚ, frame.exc_bestguess, exct)
update_cycle_worklists!(frame) do caller::InferenceState, caller_pc::Int
caller_handler = caller.handler_at[caller_pc][1]
caller_exct = caller_handler == 0 ?
caller.exc_bestguess : caller.handlers[caller_handler].exct
return caller_exct !== Any
end
end
else
handler_frame = frame.handlers[cur_hand]
if !(𝕃ₚ, exct, handler_frame.exct)
handler_frame.exct = tmerge(𝕃ₚ, handler_frame.exct, exct)
enter = frame.src.code[handler_frame.enter_idx]::Expr
l = enter.args[1]::Int
exceptbb = block_for_inst(frame.cfg, l)
push!(W, exceptbb)
end
end
update_exc_bestguess!(exct, frame, ipo_lattice(interp))
end
if (get_curr_ssaflag(frame) & IR_FLAG_NOTHROW) != IR_FLAG_NOTHROW
propagate_to_error_handler!(frame, currpc, W, 𝕃ᵢ, currstate)
propagate_to_error_handler!(currstate, frame, 𝕃ᵢ)
end
if rt === Bottom
ssavaluetypes[currpc] = Bottom
Expand Down
5 changes: 5 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5587,3 +5587,8 @@ end
return err
end
end |> only === Float64

# exception type from GotoIfNot
@test Base.infer_exception_type(c::Bool -> c ? 1 : 2) == Union{}
@test Base.infer_exception_type(c::Missing -> c ? 1 : 2) == TypeError
@test Base.infer_exception_type(c::Any -> c ? 1 : 2) == TypeError

0 comments on commit e0dfd9b

Please sign in to comment.