Skip to content

Commit

Permalink
inference: refine setglobal! rt for invalid assignments (#56622)
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk authored Nov 21, 2024
1 parent 0ded536 commit 859c25a
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 15 deletions.
34 changes: 19 additions & 15 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2419,8 +2419,8 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
if isa(M, Const) && isa(s, Const)
M, s = M.val, s.val
if M isa Module && s isa Symbol
exct = global_assignment_exct(interp, sv, saw_latestworld, GlobalRef(M, s), v)
return CallMeta(v, exct, Effects(setglobal!_effects, nothrow=exct===Bottom), NoCallInfo())
rt, exct = global_assignment_rt_exct(interp, sv, saw_latestworld, GlobalRef(M, s), v)
return CallMeta(rt, exct, Effects(setglobal!_effects, nothrow=exct===Bottom), NoCallInfo())
end
return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
end
Expand Down Expand Up @@ -2485,7 +2485,7 @@ function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntSta
if binding_kind(partition) == BINDING_KIND_GLOBAL
T = partition_restriction(partition)
end
exct = Union{rte.exct, global_assignment_binding_exct(partition, v)}
exct = Union{rte.exct, global_assignment_binding_rt_exct(interp, partition, v)[2]}
effects = merge_effects(rte.effects, Effects(setglobal!_effects, nothrow=exct===Bottom))
sg = CallMeta(Any, exct, effects, NoCallInfo())
else
Expand Down Expand Up @@ -3401,31 +3401,35 @@ function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, saw_
return ret
end

function global_assignment_exct(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, g::GlobalRef, @nospecialize(newty))
function global_assignment_rt_exct(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, g::GlobalRef, @nospecialize(newty))
if saw_latestworld
return Union{ErrorException, TypeError}
return Pair{Any,Any}(newty, Union{ErrorException, TypeError})
end
partition = abstract_eval_binding_partition!(interp, g, sv)
return global_assignment_binding_exct(partition, newty)
return global_assignment_binding_rt_exct(interp, partition, newty)
end

function global_assignment_binding_exct(partition::Core.BindingPartition, @nospecialize(newty))
function global_assignment_binding_rt_exct(interp::AbstractInterpreter, partition::Core.BindingPartition, @nospecialize(newty))
kind = binding_kind(partition)
if is_some_guard(kind) || is_some_const_binding(kind)
return ErrorException
if is_some_guard(kind)
return Pair{Any,Any}(newty, ErrorException)
elseif is_some_const_binding(kind)
return Pair{Any,Any}(Bottom, ErrorException)
end

ty = partition_restriction(partition)
if !(widenconst(newty) <: ty)
return TypeError
wnewty = widenconst(newty)
if !hasintersect(wnewty, ty)
return Pair{Any,Any}(Bottom, TypeError)
elseif !(wnewty <: ty)
retty = tmeet(typeinf_lattice(interp), newty, ty)
return Pair{Any,Any}(retty, TypeError)
end

return Union{}
return Pair{Any,Any}(newty, Bottom)
end

function handle_global_assignment!(interp::AbstractInterpreter, frame::InferenceState, saw_latestworld::Bool, lhs::GlobalRef, @nospecialize(newty))
effect_free = ALWAYS_FALSE
nothrow = global_assignment_exct(interp, frame, saw_latestworld, lhs, ignorelimited(newty)) === Union{}
nothrow = global_assignment_rt_exct(interp, frame, saw_latestworld, lhs, ignorelimited(newty))[2] === Union{}
inaccessiblememonly = ALWAYS_FALSE
if !nothrow
sub_curr_ssaflag!(frame, IR_FLAG_NOTHROW)
Expand Down
9 changes: 9 additions & 0 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6088,3 +6088,12 @@ function issue56387(nt::NamedTuple, field::Symbol=:a)
types[index]
end
@test Base.infer_return_type(issue56387, (typeof((;a=1)),)) == Type{Int}

global setglobal!_refine::Int
@test Base.infer_return_type((Integer,)) do x
setglobal!(@__MODULE__, :setglobal!_refine, x)
end === Int
global setglobal!_must_throw::Int = 42
@test Base.infer_return_type((String,)) do x
setglobal!(@__MODULE__, :setglobal!_must_throw, x)
end === Union{}

0 comments on commit 859c25a

Please sign in to comment.