Skip to content

Commit

Permalink
inference: add missing modeling for swapglobal! (#56623)
Browse files Browse the repository at this point in the history
This was missed from #56299.
  • Loading branch information
aviatesk authored Nov 21, 2024
1 parent c31710a commit 873a1e4
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 11 deletions.
51 changes: 40 additions & 11 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2329,13 +2329,13 @@ function abstract_throw_methoderror(interp::AbstractInterpreter, argtypes::Vecto
elseif !isvarargtype(argtypes[2])
MethodError
else
= join(typeinf_lattice(interp))
MethodError ArgumentError
Union{MethodError, ArgumentError}
end
return Future(CallMeta(Union{}, exct, EFFECTS_THROWS, NoCallInfo()))
end

const generic_getglobal_effects = Effects(EFFECTS_THROWS, consistent=ALWAYS_FALSE, inaccessiblememonly=ALWAYS_FALSE)
const generic_getglobal_exct = Union{ArgumentError, TypeError, ConcurrencyViolationError, UndefVarError}
function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, @nospecialize(M), @nospecialize(s))
= partialorder(typeinf_lattice(interp))
if M isa Const && s isa Const
Expand Down Expand Up @@ -2373,8 +2373,7 @@ function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, s
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 5
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
else
return CallMeta(Any, Union{ArgumentError, UndefVarError, TypeError, ConcurrencyViolationError},
generic_getglobal_effects, NoCallInfo())
return CallMeta(Any, generic_getglobal_exct, generic_getglobal_effects, NoCallInfo())
end
end

Expand Down Expand Up @@ -2440,6 +2439,8 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
return merge_exct(cm, goe)
end

const generic_setglobal!_exct = Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}

function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
if length(argtypes) == 4
return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
Expand All @@ -2448,7 +2449,35 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
else
return CallMeta(Any, Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}, setglobal!_effects, NoCallInfo())
return CallMeta(Any, generic_setglobal!_exct, setglobal!_effects, NoCallInfo())
end
end

function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool,
@nospecialize(M), @nospecialize(s), @nospecialize(v))
scm = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v)
scm.rt === Bottom && return scm
gcm = abstract_eval_getglobal(interp, sv, saw_latestworld, M, s)
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), NoCallInfo())
end

function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool,
@nospecialize(M), @nospecialize(s), @nospecialize(v), @nospecialize(order))
scm = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v, order)
scm.rt === Bottom && return scm
gcm = abstract_eval_getglobal(interp, sv, saw_latestworld, M, s, order)
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), NoCallInfo())
end

function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
if length(argtypes) == 4
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
elseif length(argtypes) == 5
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5])
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
else
return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo())
end
end

Expand All @@ -2467,20 +2496,18 @@ function abstract_eval_setglobalonce!(interp::AbstractInterpreter, sv::AbsIntSta
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
else
return CallMeta(Bool, Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}, setglobal!_effects, NoCallInfo())
return CallMeta(Bool, generic_setglobal!_exct, setglobal!_effects, NoCallInfo())
end
end

function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
if length(argtypes) in (5, 6, 7)
(M, s, x, v) = argtypes[2], argtypes[3], argtypes[4], argtypes[5]

T = nothing
if isa(M, Const) && isa(s, Const)
M, s = M.val, s.val
if !(M isa Module && s isa Symbol)
return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
end
M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
partition = abstract_eval_binding_partition!(interp, GlobalRef(M, s), sv)
rte = abstract_eval_partition_load(interp, partition)
if binding_kind(partition) == BINDING_KIND_GLOBAL
Expand All @@ -2507,7 +2534,7 @@ function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntSta
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 8
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
else
return CallMeta(Any, Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}, setglobal!_effects, NoCallInfo())
return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo())
end
end

Expand Down Expand Up @@ -2547,6 +2574,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
return Future(abstract_eval_getglobal(interp, sv, si.saw_latestworld, argtypes))
elseif f === Core.setglobal!
return Future(abstract_eval_setglobal!(interp, sv, si.saw_latestworld, argtypes))
elseif f === Core.swapglobal!
return Future(abstract_eval_swapglobal!(interp, sv, si.saw_latestworld, argtypes))
elseif f === Core.setglobalonce!
return Future(abstract_eval_setglobalonce!(interp, sv, si.saw_latestworld, argtypes))
elseif f === Core.replaceglobal!
Expand Down
19 changes: 19 additions & 0 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6097,3 +6097,22 @@ global setglobal!_must_throw::Int = 42
@test Base.infer_return_type((String,)) do x
setglobal!(@__MODULE__, :setglobal!_must_throw, x)
end === Union{}

global swapglobal!_xxx::Int = 42
@test Base.infer_return_type((Int,)) do x
swapglobal!(@__MODULE__, :swapglobal!_xxx, x)
end === Int
@test Base.infer_return_type((String,)) do x
swapglobal!(@__MODULE__, :swapglobal!_xxx, x)
end === Union{}

global swapglobal!_must_throw
@newinterp SwapGlobalInterp
let CC = Base.Compiler
CC.InferenceParams(::SwapGlobalInterp) = CC.InferenceParams(; assume_bindings_static=true)
end
function func_swapglobal!_must_throw(x)
swapglobal!(@__MODULE__, :swapglobal!_must_throw, x)
end
@test Base.infer_return_type(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) === Union{}
@test !Base.Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) )

3 comments on commit 873a1e4

@DilumAluthge
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nanosoldier runtests(["PackageCompiler"])

@DilumAluthge
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nanosoldier runtests(["PackageCompiler"])

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package evaluation job you requested has completed - possible issues were detected.
The full report is available.

Please sign in to comment.