From 35729d9fc588d14db92596cbc78ae2818e441661 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 18 Dec 2024 00:49:21 +0900 Subject: [PATCH] inference: handle cases where `:the_exception` is used independently (#56836) `Expr(:the_exception)` is handled by the interpreter in all cases, however, inference assumes it is only used within frames containing `try/catch`. This commit corrects that assumption. --- Compiler/src/abstractinterpretation.jl | 12 ++++++++++-- Compiler/test/inference.jl | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Compiler/src/abstractinterpretation.jl b/Compiler/src/abstractinterpretation.jl index 2efd8a2b7264f..0d0d4a2f80e9e 100644 --- a/Compiler/src/abstractinterpretation.jl +++ b/Compiler/src/abstractinterpretation.jl @@ -3240,8 +3240,16 @@ function abstract_eval_throw_undef_if_not(interp::AbstractInterpreter, e::Expr, end function abstract_eval_the_exception(::AbstractInterpreter, sv::InferenceState) - (;handlers, handler_at) = sv.handler_info::HandlerInfo - return the_exception_info(handlers[handler_at[sv.currpc][2]].exct) + (;handler_info) = sv + if handler_info === nothing + return the_exception_info(Any) + end + (;handlers, handler_at) = handler_info + handler_id = handler_at[sv.currpc][2] + if handler_id === 0 + return the_exception_info(Any) + end + return the_exception_info(handlers[handler_id].exct) end abstract_eval_the_exception(::AbstractInterpreter, ::IRInterpretationState) = the_exception_info(Any) the_exception_info(@nospecialize t) = RTEffects(t, Union{}, Effects(EFFECTS_TOTAL; consistent=ALWAYS_FALSE)) diff --git a/Compiler/test/inference.jl b/Compiler/test/inference.jl index e272ff6de8d99..132e1e2c14bad 100644 --- a/Compiler/test/inference.jl +++ b/Compiler/test/inference.jl @@ -6125,3 +6125,17 @@ function func_swapglobal!_must_throw(x) end @test Base.infer_return_type(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) === Union{} @test !Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) ) + +@eval get_exception() = $(Expr(:the_exception)) +@test Base.infer_return_type() do + get_exception() +end <: Any +@test @eval Base.infer_return_type((Float64,)) do x + out = $(Expr(:the_exception)) + try + out = sin(x) + catch + out = $(Expr(:the_exception)) + end + return out +end == Union{Float64,DomainError}