Skip to content

Commit c894e04

Browse files
authored
improve robustness of Vararg checks in newly added abstract_eval_xxx (#58325)
Otherwise these subroutines may raise `unhandled Vararg` errors when compiling e.g. CassetteOverlay for complex call graphs.
1 parent 7c40a71 commit c894e04

File tree

2 files changed

+122
-70
lines changed

2 files changed

+122
-70
lines changed

Compiler/src/abstractinterpretation.jl

Lines changed: 109 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2426,11 +2426,15 @@ function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, s
24262426
end
24272427

24282428
function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
2429-
if length(argtypes) == 3
2430-
return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3])
2431-
elseif length(argtypes) == 4
2432-
return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2433-
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 5
2429+
if !isvarargtype(argtypes[end])
2430+
if length(argtypes) == 3
2431+
return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3])
2432+
elseif length(argtypes) == 4
2433+
return abstract_eval_getglobal(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2434+
else
2435+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2436+
end
2437+
elseif length(argtypes) > 5
24342438
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
24352439
else
24362440
return CallMeta(Any, generic_getglobal_exct, generic_getglobal_effects, NoCallInfo())
@@ -2471,12 +2475,17 @@ end
24712475
end
24722476

24732477
function abstract_eval_get_binding_type(interp::AbstractInterpreter, sv::AbsIntState, argtypes::Vector{Any})
2474-
if length(argtypes) == 3
2475-
return abstract_eval_get_binding_type(interp, sv, argtypes[2], argtypes[3])
2476-
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 4
2478+
if !isvarargtype(argtypes[end])
2479+
if length(argtypes) == 3
2480+
return abstract_eval_get_binding_type(interp, sv, argtypes[2], argtypes[3])
2481+
else
2482+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2483+
end
2484+
elseif length(argtypes) > 4
24772485
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2486+
else
2487+
return CallMeta(Type, Union{TypeError, ArgumentError}, EFFECTS_THROWS, NoCallInfo())
24782488
end
2479-
return CallMeta(Type, Union{TypeError, ArgumentError}, EFFECTS_THROWS, NoCallInfo())
24802489
end
24812490

24822491
const setglobal!_effects = Effects(EFFECTS_TOTAL; effect_free=ALWAYS_FALSE, nothrow=false, inaccessiblememonly=ALWAYS_FALSE)
@@ -2509,11 +2518,15 @@ end
25092518
const generic_setglobal!_exct = Union{ArgumentError, TypeError, ErrorException, ConcurrencyViolationError}
25102519

25112520
function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
2512-
if length(argtypes) == 4
2513-
return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2514-
elseif length(argtypes) == 5
2515-
return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5])
2516-
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
2521+
if !isvarargtype(argtypes[end])
2522+
if length(argtypes) == 4
2523+
return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2524+
elseif length(argtypes) == 5
2525+
return abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5])
2526+
else
2527+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2528+
end
2529+
elseif length(argtypes) > 6
25172530
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
25182531
else
25192532
return CallMeta(Any, generic_setglobal!_exct, setglobal!_effects, NoCallInfo())
@@ -2537,75 +2550,87 @@ function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState,
25372550
end
25382551

25392552
function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
2540-
if length(argtypes) == 4
2541-
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2542-
elseif length(argtypes) == 5
2543-
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5])
2544-
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
2553+
if !isvarargtype(argtypes[end])
2554+
if length(argtypes) == 4
2555+
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2556+
elseif length(argtypes) == 5
2557+
return abstract_eval_swapglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4], argtypes[5])
2558+
else
2559+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2560+
end
2561+
elseif length(argtypes) > 6
25452562
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
25462563
else
25472564
return CallMeta(Any, Union{generic_getglobal_exct,generic_setglobal!_exct}, setglobal!_effects, NoCallInfo())
25482565
end
25492566
end
25502567

25512568
function abstract_eval_setglobalonce!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
2552-
if length(argtypes) in (4, 5, 6)
2553-
cm = abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2554-
if length(argtypes) >= 5
2555-
goe = global_order_exct(argtypes[5], #=loading=#true, #=storing=#true)
2556-
cm = merge_exct(cm, goe)
2557-
end
2558-
if length(argtypes) == 6
2559-
goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#false)
2560-
cm = merge_exct(cm, goe)
2561-
end
2562-
return CallMeta(Bool, cm.exct, cm.effects, cm.info)
2563-
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 6
2569+
if !isvarargtype(argtypes[end])
2570+
if length(argtypes) in (4, 5, 6)
2571+
cm = abstract_eval_setglobal!(interp, sv, saw_latestworld, argtypes[2], argtypes[3], argtypes[4])
2572+
if length(argtypes) >= 5
2573+
goe = global_order_exct(argtypes[5], #=loading=#true, #=storing=#true)
2574+
cm = merge_exct(cm, goe)
2575+
end
2576+
if length(argtypes) == 6
2577+
goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#false)
2578+
cm = merge_exct(cm, goe)
2579+
end
2580+
return CallMeta(Bool, cm.exct, cm.effects, cm.info)
2581+
else
2582+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
2583+
end
2584+
elseif length(argtypes) > 7
25642585
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
25652586
else
25662587
return CallMeta(Bool, generic_setglobal!_exct, setglobal!_effects, NoCallInfo())
25672588
end
25682589
end
25692590

25702591
function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
2571-
if length(argtypes) in (5, 6, 7)
2572-
(M, s, x, v) = argtypes[2], argtypes[3], argtypes[4], argtypes[5]
2573-
T = nothing
2574-
if isa(M, Const) && isa(s, Const)
2575-
M, s = M.val, s.val
2576-
M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
2577-
s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
2578-
gr = GlobalRef(M, s)
2579-
v′ = RefValue{Any}(v)
2580-
(valid_worlds, (rte, T)) = scan_leaf_partitions(interp, gr, sv.world) do interp::AbstractInterpreter, binding::Core.Binding, partition::Core.BindingPartition
2581-
partition_T = nothing
2582-
partition_rte = abstract_eval_partition_load(interp, binding, partition)
2583-
if binding_kind(partition) == PARTITION_KIND_GLOBAL
2584-
partition_T = partition_restriction(partition)
2592+
if !isvarargtype(argtypes[end])
2593+
if length(argtypes) in (5, 6, 7)
2594+
(M, s, x, v) = argtypes[2], argtypes[3], argtypes[4], argtypes[5]
2595+
T = nothing
2596+
if isa(M, Const) && isa(s, Const)
2597+
M, s = M.val, s.val
2598+
M isa Module || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
2599+
s isa Symbol || return CallMeta(Union{}, TypeError, EFFECTS_THROWS, NoCallInfo())
2600+
gr = GlobalRef(M, s)
2601+
v′ = RefValue{Any}(v)
2602+
(valid_worlds, (rte, T)) = scan_leaf_partitions(interp, gr, sv.world) do interp::AbstractInterpreter, binding::Core.Binding, partition::Core.BindingPartition
2603+
partition_T = nothing
2604+
partition_rte = abstract_eval_partition_load(interp, binding, partition)
2605+
if binding_kind(partition) == PARTITION_KIND_GLOBAL
2606+
partition_T = partition_restriction(partition)
2607+
end
2608+
partition_exct = Union{partition_rte.exct, global_assignment_binding_rt_exct(interp, partition, v′[])[2]}
2609+
partition_rte = RTEffects(partition_rte.rt, partition_exct, partition_rte.effects)
2610+
Pair{RTEffects, Any}(partition_rte, partition_T)
25852611
end
2586-
partition_exct = Union{partition_rte.exct, global_assignment_binding_rt_exct(interp, partition, v′[])[2]}
2587-
partition_rte = RTEffects(partition_rte.rt, partition_exct, partition_rte.effects)
2588-
Pair{RTEffects, Any}(partition_rte, partition_T)
2612+
update_valid_age!(sv, valid_worlds)
2613+
effects = merge_effects(rte.effects, Effects(setglobal!_effects, nothrow=rte.exct===Bottom))
2614+
sg = CallMeta(Any, rte.exct, effects, GlobalAccessInfo(convert(Core.Binding, gr)))
2615+
else
2616+
sg = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v)
2617+
end
2618+
if length(argtypes) >= 6
2619+
goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#true)
2620+
sg = merge_exct(sg, goe)
2621+
end
2622+
if length(argtypes) == 7
2623+
goe = global_order_exct(argtypes[7], #=loading=#true, #=storing=#false)
2624+
sg = merge_exct(sg, goe)
25892625
end
2590-
update_valid_age!(sv, valid_worlds)
2591-
effects = merge_effects(rte.effects, Effects(setglobal!_effects, nothrow=rte.exct===Bottom))
2592-
sg = CallMeta(Any, rte.exct, effects, GlobalAccessInfo(convert(Core.Binding, gr)))
2626+
rt = T === nothing ?
2627+
ccall(:jl_apply_cmpswap_type, Any, (Any,), S) where S :
2628+
ccall(:jl_apply_cmpswap_type, Any, (Any,), T)
2629+
return CallMeta(rt, sg.exct, sg.effects, sg.info)
25932630
else
2594-
sg = abstract_eval_setglobal!(interp, sv, saw_latestworld, M, s, v)
2595-
end
2596-
if length(argtypes) >= 6
2597-
goe = global_order_exct(argtypes[6], #=loading=#true, #=storing=#true)
2598-
sg = merge_exct(sg, goe)
2599-
end
2600-
if length(argtypes) == 7
2601-
goe = global_order_exct(argtypes[7], #=loading=#true, #=storing=#false)
2602-
sg = merge_exct(sg, goe)
2631+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
26032632
end
2604-
rt = T === nothing ?
2605-
ccall(:jl_apply_cmpswap_type, Any, (Any,), S) where S :
2606-
ccall(:jl_apply_cmpswap_type, Any, (Any,), T)
2607-
return CallMeta(rt, sg.exct, sg.effects, sg.info)
2608-
elseif !isvarargtype(argtypes[end]) || length(argtypes) > 8
2633+
elseif length(argtypes) > 8
26092634
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
26102635
else
26112636
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),
26622687
return Future(abstract_eval_isdefinedglobal(interp, argtypes[2], argtypes[3], Const(true),
26632688
length(argtypes) == 4 ? argtypes[4] : Const(:unordered),
26642689
si.saw_latestworld, sv))
2665-
elseif f === Core.isdefinedglobal && 3 <= length(argtypes) <= 5
2666-
return Future(abstract_eval_isdefinedglobal(interp, argtypes[2], argtypes[3],
2667-
length(argtypes) >= 4 ? argtypes[4] : Const(true),
2668-
length(argtypes) >= 5 ? argtypes[5] : Const(:unordered),
2669-
si.saw_latestworld, sv))
2690+
elseif f === Core.isdefinedglobal
2691+
return Future(abstract_eval_isdefinedglobal(interp, sv, si.saw_latestworld, argtypes))
26702692
elseif f === Core.get_binding_type
26712693
return Future(abstract_eval_get_binding_type(interp, sv, argtypes))
26722694
end
@@ -3347,6 +3369,23 @@ function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, @nospecializ
33473369
return CallMeta(Bool, Union{exct, TypeError, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo())
33483370
end
33493371

3372+
function abstract_eval_isdefinedglobal(interp::AbstractInterpreter, sv::AbsIntState, saw_latestworld::Bool, argtypes::Vector{Any})
3373+
if !isvarargtype(argtypes[end])
3374+
if 3 <= length(argtypes) <= 5
3375+
return abstract_eval_isdefinedglobal(interp, argtypes[2], argtypes[3],
3376+
length(argtypes) >= 4 ? argtypes[4] : Const(true),
3377+
length(argtypes) >= 5 ? argtypes[5] : Const(:unordered),
3378+
saw_latestworld, sv)
3379+
else
3380+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
3381+
end
3382+
elseif length(argtypes) > 6
3383+
return CallMeta(Union{}, ArgumentError, EFFECTS_THROWS, NoCallInfo())
3384+
else
3385+
return CallMeta(Bool, Union{ConcurrencyViolationError, TypeError, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo())
3386+
end
3387+
end
3388+
33503389
function abstract_eval_throw_undef_if_not(interp::AbstractInterpreter, e::Expr, sstate::StatementState, sv::AbsIntState)
33513390
condt = abstract_eval_value(interp, e.args[2], sstate, sv)
33523391
condval = maybe_extract_const_bool(condt)

Compiler/test/inference.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6486,4 +6486,17 @@ function ss57873(a::Vector{String}, pref)
64866486
end
64876487
@test ss57873(["a", "b", "c"], ("",)) == String[]
64886488

6489+
@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs
6490+
getglobal(m, n, xs...)
6491+
end <: Any
6492+
@test Base.infer_return_type((Module,Symbol,Any,Vector{Any})) do m, n, v, xs
6493+
setglobal!(m, n, v, xs...)
6494+
end <: Any
6495+
@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs
6496+
isdefinedglobal(m, n, xs...)
6497+
end <: Bool
6498+
@test Base.infer_return_type((Module,Symbol,Vector{Any})) do m, n, xs
6499+
Core.get_binding_type(m, n, xs...)
6500+
end <: Type
6501+
64896502
end # module inference

0 commit comments

Comments
 (0)