Skip to content

Commit 873a1e4

Browse files
authored
inference: add missing modeling for swapglobal! (#56623)
This was missed from #56299.
1 parent c31710a commit 873a1e4

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

Compiler/src/abstractinterpretation.jl

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,13 +2329,13 @@ function abstract_throw_methoderror(interp::AbstractInterpreter, argtypes::Vecto
23292329
elseif !isvarargtype(argtypes[2])
23302330
MethodError
23312331
else
2332-
= join(typeinf_lattice(interp))
2333-
MethodError ArgumentError
2332+
Union{MethodError, ArgumentError}
23342333
end
23352334
return Future(CallMeta(Union{}, exct, EFFECTS_THROWS, NoCallInfo()))
23362335
end
23372336

23382337
const generic_getglobal_effects = Effects(EFFECTS_THROWS, consistent=ALWAYS_FALSE, inaccessiblememonly=ALWAYS_FALSE)
2338+
const generic_getglobal_exct = Union{ArgumentError, TypeError, ConcurrencyViolationError, UndefVarError}
23392339
function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, @nospecialize(M), @nospecialize(s))
23402340
= partialorder(typeinf_lattice(interp))
23412341
if M isa Const && s isa Const
@@ -2373,8 +2373,7 @@ function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, s
23732373
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 5
23742374
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
23752375
else
2376-
return CallMeta(Any, Union{ArgumentError, UndefVarError, TypeError, ConcurrencyViolationError},
2377-
generic_getglobal_effects, NoCallInfo())
2376+
return CallMeta(Any, generic_getglobal_exct, generic_getglobal_effects, NoCallInfo())
23782377
end
23792378
end
23802379

@@ -2440,6 +2439,8 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
24402439
return merge_exct(cm, goe)
24412440
end
24422441

2442+
const generic_setglobal!_exct = Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}
2443+
24432444
function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
24442445
if length(argtypes) == 4
24452446
return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
@@ -2448,7 +2449,35 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
24482449
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
24492450
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
24502451
else
2451-
return CallMeta(Any, Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}, setglobal!_effects, NoCallInfo())
2452+
return CallMeta(Any, generic_setglobal!_exct, setglobal!_effects, NoCallInfo())
2453+
end
2454+
end
2455+
2456+
function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool,
2457+
@nospecialize(M), @nospecialize(s), @nospecialize(v))
2458+
scm = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v)
2459+
scm.rt === Bottom && return scm
2460+
gcm = abstract_eval_getglobal(interp, sv, saw_latestworld, M, s)
2461+
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), NoCallInfo())
2462+
end
2463+
2464+
function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool,
2465+
@nospecialize(M), @nospecialize(s), @nospecialize(v), @nospecialize(order))
2466+
scm = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v, order)
2467+
scm.rt === Bottom && return scm
2468+
gcm = abstract_eval_getglobal(interp, sv, saw_latestworld, M, s, order)
2469+
return CallMeta(gcm.rt, Union{scm.exct,gcm.exct}, merge_effects(scm.effects, gcm.effects), NoCallInfo())
2470+
end
2471+
2472+
function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
2473+
if length(argtypes) == 4
2474+
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2475+
elseif length(argtypes) == 5
2476+
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5])
2477+
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
2478+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2479+
else
2480+
return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo())
24522481
end
24532482
end
24542483

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

24742503
function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
24752504
if length(argtypes) in (5, 6, 7)
24762505
(M, s, x, v) = argtypes[2], argtypes[3], argtypes[4], argtypes[5]
2477-
24782506
T = nothing
24792507
if isa(M, Const) && isa(s, Const)
24802508
M, s = M.val, s.val
2481-
if !(M isa Module && s isa Symbol)
2482-
return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
2483-
end
2509+
M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
2510+
s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
24842511
partition = abstract_eval_binding_partition!(interp, GlobalRef(M, s), sv)
24852512
rte = abstract_eval_partition_load(interp, partition)
24862513
if binding_kind(partition) == BINDING_KIND_GLOBAL
@@ -2507,7 +2534,7 @@ function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntSta
25072534
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 8
25082535
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
25092536
else
2510-
return CallMeta(Any, Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}, setglobal!_effects, NoCallInfo())
2537+
return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo())
25112538
end
25122539
end
25132540

@@ -2547,6 +2574,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
25472574
return Future(abstract_eval_getglobal(interp, sv, si.saw_latestworld, argtypes))
25482575
elseif f === Core.setglobal!
25492576
return Future(abstract_eval_setglobal!(interp, sv, si.saw_latestworld, argtypes))
2577+
elseif f === Core.swapglobal!
2578+
return Future(abstract_eval_swapglobal!(interp, sv, si.saw_latestworld, argtypes))
25502579
elseif f === Core.setglobalonce!
25512580
return Future(abstract_eval_setglobalonce!(interp, sv, si.saw_latestworld, argtypes))
25522581
elseif f === Core.replaceglobal!

Compiler/test/inference.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6097,3 +6097,22 @@ global setglobal!_must_throw::Int = 42
60976097
@test Base.infer_return_type((String,)) do x
60986098
setglobal!(@__MODULE__, :setglobal!_must_throw, x)
60996099
end === Union{}
6100+
6101+
global swapglobal!_xxx::Int = 42
6102+
@test Base.infer_return_type((Int,)) do x
6103+
swapglobal!(@__MODULE__, :swapglobal!_xxx, x)
6104+
end === Int
6105+
@test Base.infer_return_type((String,)) do x
6106+
swapglobal!(@__MODULE__, :swapglobal!_xxx, x)
6107+
end === Union{}
6108+
6109+
global swapglobal!_must_throw
6110+
@newinterp SwapGlobalInterp
6111+
let CC = Base.Compiler
6112+
CC.InferenceParams(::SwapGlobalInterp) = CC.InferenceParams(; assume_bindings_static=true)
6113+
end
6114+
function func_swapglobal!_must_throw(x)
6115+
swapglobal!(@__MODULE__, :swapglobal!_must_throw, x)
6116+
end
6117+
@test Base.infer_return_type(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) === Union{}
6118+
@test !Base.Compiler.is_effect_free(Base.infer_effects(func_swapglobal!_must_throw, (Int,); interp=SwapGlobalInterp()) )

0 commit comments

Comments
 (0)