Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 40 additions & 11 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2328,13 +2328,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 @@ -2372,8 +2372,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 @@ -2439,6 +2438,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 @@ -2447,7 +2448,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 @@ -2466,20 +2495,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 @@ -2506,7 +2533,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 @@ -2546,6 +2573,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()) )