diff --git a/Compiler/src/abstractinterpretation.jl b/Compiler/src/abstractinterpretation.jl index 8fe30d4891e9b..058476dac0096 100644 --- a/Compiler/src/abstractinterpretation.jl +++ b/Compiler/src/abstractinterpretation.jl @@ -2426,11 +2426,15 @@ function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, s end function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any}) - if length(argtypes) == 3 - return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3]) - elseif length(argtypes) == 4 - return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4]) - elseif !isvarargtype(argtypes[end]) || length(argtypes) > 5 + if !isvarargtype(argtypes[end]) + if length(argtypes) == 3 + return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3]) + elseif length(argtypes) == 4 + return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4]) + else + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + end + elseif length(argtypes) > 5 return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) else return CallMeta(Any, generic_getglobal_exct, generic_getglobal_effects, NoCallInfo()) @@ -2471,12 +2475,17 @@ end end function abstract_eval_get_binding_type(interp::AbstractInterpreter, sv::AbsIntState, argtypes::Vector{Any}) - if length(argtypes) == 3 - return abstract_eval_get_binding_type(interp, sv, argtypes[2], argtypes[3]) - elseif !isvarargtype(argtypes[end]) || length(argtypes) > 4 + if !isvarargtype(argtypes[end]) + if length(argtypes) == 3 + return abstract_eval_get_binding_type(interp, sv, argtypes[2], argtypes[3]) + else + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + end + elseif length(argtypes) > 4 return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + else + return CallMeta(Type, Union{TypeError, ArgumentError}, EFFECTS_THROWS, NoCallInfo()) end - return CallMeta(Type, Union{TypeError, ArgumentError}, EFFECTS_THROWS, NoCallInfo()) end const setglobal!_effects = Effects(EFFECTS_TOTAL; effect_free=ALWAYS_FALSE, nothrow=false, inaccessiblememonly=ALWAYS_FALSE) @@ -2509,11 +2518,15 @@ 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]) - elseif length(argtypes) == 5 - return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5]) - elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6 + if !isvarargtype(argtypes[end]) + if length(argtypes) == 4 + return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4]) + elseif length(argtypes) == 5 + return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5]) + else + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + end + elseif length(argtypes) > 6 return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) else return CallMeta(Any, generic_setglobal!_exct, setglobal!_effects, NoCallInfo()) @@ -2537,11 +2550,15 @@ function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, 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 + if !isvarargtype(argtypes[end]) + 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]) + else + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + end + elseif length(argtypes) > 6 return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) else return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo()) @@ -2549,18 +2566,22 @@ function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, end function abstract_eval_setglobalonce!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any}) - if length(argtypes) in (4, 5, 6) - cm = abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4]) - if length(argtypes) >= 5 - goe = global_order_exct(argtypes[5], #=loading=#true, #=storing=#true) - cm = merge_exct(cm, goe) - end - if length(argtypes) == 6 - goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#false) - cm = merge_exct(cm, goe) - end - return CallMeta(Bool, cm.exct, cm.effects, cm.info) - elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6 + if !isvarargtype(argtypes[end]) + if length(argtypes) in (4, 5, 6) + cm = abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4]) + if length(argtypes) >= 5 + goe = global_order_exct(argtypes[5], #=loading=#true, #=storing=#true) + cm = merge_exct(cm, goe) + end + if length(argtypes) == 6 + goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#false) + cm = merge_exct(cm, goe) + end + return CallMeta(Bool, cm.exct, cm.effects, cm.info) + else + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + end + elseif length(argtypes) > 7 return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) else return CallMeta(Bool, generic_setglobal!_exct, setglobal!_effects, NoCallInfo()) @@ -2568,44 +2589,48 @@ function abstract_eval_setglobalonce!(interp::AbstractInterpreter, sv::AbsIntSta 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 - M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo()) - s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo()) - gr = GlobalRef(M, s) - v′ = RefValue{Any}(v) - (valid_worlds, (rte, T)) = scan_leaf_partitions(interp, gr, sv.world) do interp::AbstractInterpreter, binding::Core.Binding, partition::Core.BindingPartition - partition_T = nothing - partition_rte = abstract_eval_partition_load(interp, binding, partition) - if binding_kind(partition) == PARTITION_KIND_GLOBAL - partition_T = partition_restriction(partition) + if !isvarargtype(argtypes[end]) + 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 + M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo()) + s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo()) + gr = GlobalRef(M, s) + v′ = RefValue{Any}(v) + (valid_worlds, (rte, T)) = scan_leaf_partitions(interp, gr, sv.world) do interp::AbstractInterpreter, binding::Core.Binding, partition::Core.BindingPartition + partition_T = nothing + partition_rte = abstract_eval_partition_load(interp, binding, partition) + if binding_kind(partition) == PARTITION_KIND_GLOBAL + partition_T = partition_restriction(partition) + end + partition_exct = Union{partition_rte.exct, global_assignment_binding_rt_exct(interp, partition, v′[])[2]} + partition_rte = RTEffects(partition_rte.rt, partition_exct, partition_rte.effects) + Pair{RTEffects, Any}(partition_rte, partition_T) end - partition_exct = Union{partition_rte.exct, global_assignment_binding_rt_exct(interp, partition, v′[])[2]} - partition_rte = RTEffects(partition_rte.rt, partition_exct, partition_rte.effects) - Pair{RTEffects, Any}(partition_rte, partition_T) + update_valid_age!(sv, valid_worlds) + effects = merge_effects(rte.effects, Effects(setglobal!_effects, nothrow=rte.exct===Bottom)) + sg = CallMeta(Any, rte.exct, effects, GlobalAccessInfo(convert(Core.Binding, gr))) + else + sg = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v) + end + if length(argtypes) >= 6 + goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#true) + sg = merge_exct(sg, goe) + end + if length(argtypes) == 7 + goe = global_order_exct(argtypes[7], #=loading=#true, #=storing=#false) + sg = merge_exct(sg, goe) end - update_valid_age!(sv, valid_worlds) - effects = merge_effects(rte.effects, Effects(setglobal!_effects, nothrow=rte.exct===Bottom)) - sg = CallMeta(Any, rte.exct, effects, GlobalAccessInfo(convert(Core.Binding, gr))) + rt = T === nothing ? + ccall(:jl_apply_cmpswap_type, Any, (Any,), S) where S : + ccall(:jl_apply_cmpswap_type, Any, (Any,), T) + return CallMeta(rt, sg.exct, sg.effects, sg.info) else - sg = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v) - end - if length(argtypes) >= 6 - goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#true) - sg = merge_exct(sg, goe) - end - if length(argtypes) == 7 - goe = global_order_exct(argtypes[7], #=loading=#true, #=storing=#false) - sg = merge_exct(sg, goe) + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) end - rt = T === nothing ? - ccall(:jl_apply_cmpswap_type, Any, (Any,), S) where S : - ccall(:jl_apply_cmpswap_type, Any, (Any,), T) - return CallMeta(rt, sg.exct, sg.effects, sg.info) - elseif !isvarargtype(argtypes[end]) || length(argtypes) > 8 + elseif length(argtypes) > 8 return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) else return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo()) @@ -2662,11 +2687,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), return Future(abstract_eval_isdefinedglobal(interp, argtypes[2], argtypes[3], Const(true), length(argtypes) == 4 ? argtypes[4] : Const(:unordered), si.saw_latestworld, sv)) - elseif f === Core.isdefinedglobal && 3 <= length(argtypes) <= 5 - return Future(abstract_eval_isdefinedglobal(interp, argtypes[2], argtypes[3], - length(argtypes) >= 4 ? argtypes[4] : Const(true), - length(argtypes) >= 5 ? argtypes[5] : Const(:unordered), - si.saw_latestworld, sv)) + elseif f === Core.isdefinedglobal + return Future(abstract_eval_isdefinedglobal(interp, sv, si.saw_latestworld, argtypes)) elseif f === Core.get_binding_type return Future(abstract_eval_get_binding_type(interp, sv, argtypes)) end @@ -3347,6 +3369,23 @@ function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, @nospecializ return CallMeta(Bool, Union{exct, TypeError, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo()) end +function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any}) + if !isvarargtype(argtypes[end]) + if 3 <= length(argtypes) <= 5 + return abstract_eval_isdefinedglobal(interp, argtypes[2], argtypes[3], + length(argtypes) >= 4 ? argtypes[4] : Const(true), + length(argtypes) >= 5 ? argtypes[5] : Const(:unordered), + saw_latestworld, sv) + else + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + end + elseif length(argtypes) > 6 + return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo()) + else + return CallMeta(Bool, Union{ConcurrencyViolationError, TypeError, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo()) + end +end + function abstract_eval_throw_undef_if_not(interp::AbstractInterpreter, e::Expr, sstate::StatementState, sv::AbsIntState) condt = abstract_eval_value(interp, e.args[2], sstate, sv) condval = maybe_extract_const_bool(condt) diff --git a/Compiler/test/inference.jl b/Compiler/test/inference.jl index 8333b191c75c9..45f67129039f4 100644 --- a/Compiler/test/inference.jl +++ b/Compiler/test/inference.jl @@ -6486,4 +6486,17 @@ function ss57873(a::Vector{String}, pref) end @test ss57873(["a", "b", "c"], ("",)) == String[] +@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs + getglobal(m, n, xs...) +end <: Any +@test Base.infer_return_type((Module,Symbol,Any,Vector{Any})) do m, n, v, xs + setglobal!(m, n, v, xs...) +end <: Any +@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs + isdefinedglobal(m, n, xs...) +end <: Bool +@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs + Core.get_binding_type(m, n, xs...) +end <: Type + end # module inference