@@ -2395,7 +2395,8 @@ function abstract_eval_getglobal(interp::AbstractInterpreter, sv::AbsIntState, s
2395
2395
if M isa Const && s isa Const
2396
2396
M, s = M. val, s. val
2397
2397
if M isa Module && s isa Symbol
2398
- return CallMeta (abstract_eval_globalref (interp, GlobalRef (M, s), saw_latestworld, sv), NoCallInfo ())
2398
+ (ret, bpart) = abstract_eval_globalref (interp, GlobalRef (M, s), saw_latestworld, sv)
2399
+ return CallMeta (ret, bpart === nothing ? NoCallInfo () : GlobalAccessInfo (bpart))
2399
2400
end
2400
2401
return CallMeta (Union{}, TypeError, EFFECTS_THROWS, NoCallInfo ())
2401
2402
elseif ! hasintersect (widenconst (M), Module) || ! hasintersect (widenconst (s), Symbol)
@@ -2473,8 +2474,8 @@ function abstract_eval_setglobal!(interp::AbstractInterpreter, sv::AbsIntState,
2473
2474
if isa (M, Const) && isa (s, Const)
2474
2475
M, s = M. val, s. val
2475
2476
if M isa Module && s isa Symbol
2476
- rt, exct = global_assignment_rt_exct (interp, sv, saw_latestworld, GlobalRef (M, s), v)
2477
- return CallMeta (rt, exct, Effects (setglobal!_effects, nothrow= exct=== Bottom), NoCallInfo ( ))
2477
+ ( rt, exct), partition = global_assignment_rt_exct (interp, sv, saw_latestworld, GlobalRef (M, s), v)
2478
+ return CallMeta (rt, exct, Effects (setglobal!_effects, nothrow= exct=== Bottom), GlobalAccessInfo (partition ))
2478
2479
end
2479
2480
return CallMeta (Union{}, TypeError, EFFECTS_THROWS, NoCallInfo ())
2480
2481
end
@@ -2512,15 +2513,15 @@ function abstract_eval_swapglobal!(interp::AbstractInterpreter, sv::AbsIntState,
2512
2513
scm = abstract_eval_setglobal! (interp, sv, saw_latestworld, M, s, v)
2513
2514
scm. rt === Bottom && return scm
2514
2515
gcm = abstract_eval_getglobal (interp, sv, saw_latestworld, M, s)
2515
- return CallMeta (gcm. rt, Union{scm. exct,gcm. exct}, merge_effects (scm. effects, gcm. effects), NoCallInfo () )
2516
+ return CallMeta (gcm. rt, Union{scm. exct,gcm. exct}, merge_effects (scm. effects, gcm. effects), scm . info )
2516
2517
end
2517
2518
2518
2519
function abstract_eval_swapglobal! (interp:: AbstractInterpreter , sv:: AbsIntState , saw_latestworld:: Bool ,
2519
2520
@nospecialize (M), @nospecialize (s), @nospecialize (v), @nospecialize (order))
2520
2521
scm = abstract_eval_setglobal! (interp, sv, saw_latestworld, M, s, v, order)
2521
2522
scm. rt === Bottom && return scm
2522
2523
gcm = abstract_eval_getglobal (interp, sv, saw_latestworld, M, s, order)
2523
- return CallMeta (gcm. rt, Union{scm. exct,gcm. exct}, merge_effects (scm. effects, gcm. effects), NoCallInfo () )
2524
+ return CallMeta (gcm. rt, Union{scm. exct,gcm. exct}, merge_effects (scm. effects, gcm. effects), scm . info )
2524
2525
end
2525
2526
2526
2527
function abstract_eval_swapglobal! (interp:: AbstractInterpreter , sv:: AbsIntState , saw_latestworld:: Bool , argtypes:: Vector{Any} )
@@ -2569,7 +2570,7 @@ function abstract_eval_replaceglobal!(interp::AbstractInterpreter, sv::AbsIntSta
2569
2570
end
2570
2571
exct = Union{rte. exct, global_assignment_binding_rt_exct (interp, partition, v)[2 ]}
2571
2572
effects = merge_effects (rte. effects, Effects (setglobal!_effects, nothrow= exct=== Bottom))
2572
- sg = CallMeta (Any, exct, effects, NoCallInfo ( ))
2573
+ sg = CallMeta (Any, exct, effects, GlobalAccessInfo (partition ))
2573
2574
else
2574
2575
sg = abstract_eval_setglobal! (interp, sv, saw_latestworld, M, s, v)
2575
2576
end
@@ -2637,21 +2638,14 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
2637
2638
elseif f === Core. getfield && argtypes_are_actually_getglobal (argtypes)
2638
2639
return Future (abstract_eval_getglobal (interp, sv, si. saw_latestworld, argtypes))
2639
2640
elseif f === Core. isdefined && argtypes_are_actually_getglobal (argtypes)
2640
- exct = Bottom
2641
- if length (argtypes) == 4
2642
- order = argtypes[4 ]
2643
- exct = global_order_exct (order, #= loading=# true , #= storing=# false )
2644
- if ! (isa (order, Const) && get_atomic_order (order. val, #= loading=# true , #= storing=# false ). x >= MEMORY_ORDER_UNORDERED. x)
2645
- exct = Union{exct, ConcurrencyViolationError}
2646
- end
2647
- end
2648
- return Future (merge_exct (CallMeta (abstract_eval_isdefined (
2649
- interp,
2650
- GlobalRef ((argtypes[2 ]:: Const ). val:: Module ,
2651
- (argtypes[3 ]:: Const ). val:: Symbol ),
2652
- si. saw_latestworld,
2653
- sv),
2654
- NoCallInfo ()), exct))
2641
+ return Future (abstract_eval_isdefinedglobal (interp, argtypes[2 ], argtypes[3 ], Const (true ),
2642
+ length (argtypes) == 4 ? argtypes[4 ] : Const (:unordered ),
2643
+ si. saw_latestworld, sv))
2644
+ elseif f === Core. isdefinedglobal && 3 <= length (argtypes) <= 5
2645
+ return Future (abstract_eval_isdefinedglobal (interp, argtypes[2 ], argtypes[3 ],
2646
+ length (argtypes) >= 4 ? argtypes[4 ] : Const (true ),
2647
+ length (argtypes) >= 5 ? argtypes[5 ] : Const (:unordered ),
2648
+ si. saw_latestworld, sv))
2655
2649
elseif f === Core. get_binding_type
2656
2650
return Future (abstract_eval_get_binding_type (interp, sv, argtypes))
2657
2651
end
@@ -2944,7 +2938,8 @@ function abstract_eval_special_value(interp::AbstractInterpreter, @nospecialize(
2944
2938
return RTEffects (sv. ir. argtypes[e. n], Union{}, EFFECTS_TOTAL) # TODO frame_argtypes(sv)[e.n] and remove the assertion
2945
2939
end
2946
2940
elseif isa (e, GlobalRef)
2947
- return abstract_eval_globalref (interp, e, sstate. saw_latestworld, sv)
2941
+ # No need for an edge since an explicit GlobalRef will be picked up by the source scan
2942
+ return abstract_eval_globalref (interp, e, sstate. saw_latestworld, sv)[1 ]
2948
2943
end
2949
2944
if isa (e, QuoteNode)
2950
2945
e = e. value
@@ -3200,24 +3195,10 @@ function abstract_eval_isdefined_expr(interp::AbstractInterpreter, e::Expr, ssta
3200
3195
end
3201
3196
return RTEffects (rt, Union{}, EFFECTS_TOTAL)
3202
3197
end
3203
- return abstract_eval_isdefined (interp, sym, sstate. saw_latestworld, sv)
3204
- end
3205
-
3206
- function abstract_eval_isdefined (interp:: AbstractInterpreter , @nospecialize (sym), saw_latestworld:: Bool , sv:: AbsIntState )
3207
3198
rt = Bool
3208
3199
effects = EFFECTS_TOTAL
3209
3200
exct = Union{}
3210
- isa (sym, Symbol) && (sym = GlobalRef (frame_module (sv), sym))
3211
- if isa (sym, GlobalRef)
3212
- rte = abstract_eval_globalref (interp, sym, saw_latestworld, sv)
3213
- if rte. exct == Union{}
3214
- rt = Const (true )
3215
- elseif rte. rt === Union{} && rte. exct === UndefVarError
3216
- rt = Const (false )
3217
- else
3218
- effects = Effects (EFFECTS_TOTAL; consistent= ALWAYS_FALSE)
3219
- end
3220
- elseif isexpr (sym, :static_parameter )
3201
+ if isexpr (sym, :static_parameter )
3221
3202
n = sym. args[1 ]:: Int
3222
3203
if 1 <= n <= length (sv. sptypes)
3223
3204
sp = sv. sptypes[n]
@@ -3229,10 +3210,73 @@ function abstract_eval_isdefined(interp::AbstractInterpreter, @nospecialize(sym)
3229
3210
end
3230
3211
else
3231
3212
effects = EFFECTS_UNKNOWN
3213
+ exct = Any
3232
3214
end
3233
3215
return RTEffects (rt, exct, effects)
3234
3216
end
3235
3217
3218
+ const generic_isdefinedglobal_effects = Effects (EFFECTS_TOTAL, consistent= ALWAYS_FALSE, nothrow= false )
3219
+ function abstract_eval_isdefinedglobal (interp:: AbstractInterpreter , mod:: Module , sym:: Symbol , allow_import:: Union{Bool, Nothing} , saw_latestworld:: Bool , sv:: AbsIntState )
3220
+ rt = Bool
3221
+ if saw_latestworld
3222
+ return CallMeta (RTEffects (rt, Union{}, Effects (generic_isdefinedglobal_effects, nothrow= true )), NoCallInfo ())
3223
+ end
3224
+
3225
+ effects = EFFECTS_TOTAL
3226
+ partition = lookup_binding_partition! (interp, GlobalRef (mod, sym), sv)
3227
+ if allow_import != = true && is_some_imported (binding_kind (partition))
3228
+ if allow_import === false
3229
+ rt = Const (false )
3230
+ else
3231
+ effects = Effects (generic_isdefinedglobal_effects, nothrow= true )
3232
+ end
3233
+ else
3234
+ partition = walk_binding_partition! (interp, partition, sv)
3235
+ rte = abstract_eval_partition_load (interp, partition)
3236
+ if rte. exct == Union{}
3237
+ rt = Const (true )
3238
+ elseif rte. rt === Union{} && rte. exct === UndefVarError
3239
+ rt = Const (false )
3240
+ else
3241
+ effects = Effects (generic_isdefinedglobal_effects, nothrow= true )
3242
+ end
3243
+ end
3244
+ return CallMeta (RTEffects (rt, Union{}, effects), GlobalAccessInfo (partition))
3245
+ end
3246
+
3247
+ function abstract_eval_isdefinedglobal (interp:: AbstractInterpreter , @nospecialize (M), @nospecialize (s), @nospecialize (allow_import_arg), @nospecialize (order_arg), saw_latestworld:: Bool , sv:: AbsIntState )
3248
+ exct = Bottom
3249
+ allow_import = true
3250
+ if allow_import_arg != = nothing
3251
+ if ! isa (allow_import_arg, Const)
3252
+ allow_import = nothing
3253
+ if widenconst (allow_import_arg) != Bool
3254
+ exct = Union{exct, TypeError}
3255
+ end
3256
+ else
3257
+ allow_import = allow_import_arg. val
3258
+ end
3259
+ end
3260
+ if order_arg != = nothing
3261
+ exct = global_order_exct (order_arg, #= loading=# true , #= storing=# false )
3262
+ if ! (isa (order_arg, Const) && get_atomic_order (order_arg. val, #= loading=# true , #= storing=# false ). x >= MEMORY_ORDER_UNORDERED. x)
3263
+ exct = Union{exct, ConcurrencyViolationError}
3264
+ end
3265
+ end
3266
+ if M isa Const && s isa Const
3267
+ M, s = M. val, s. val
3268
+ if M isa Module && s isa Symbol
3269
+ return merge_exct (abstract_eval_isdefinedglobal (interp, M, s, allow_import, saw_latestworld, sv), exct)
3270
+ end
3271
+ return CallMeta (Union{}, TypeError, EFFECTS_THROWS, NoCallInfo ())
3272
+ elseif ! hasintersect (widenconst (M), Module) || ! hasintersect (widenconst (s), Symbol)
3273
+ return CallMeta (Union{}, TypeError, EFFECTS_THROWS, NoCallInfo ())
3274
+ elseif M ⊑ Module && s ⊑ Symbol
3275
+ return CallMeta (Bool, Union{exct, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo ())
3276
+ end
3277
+ return CallMeta (Bool, Union{exct, TypeError, UndefVarError}, generic_isdefinedglobal_effects, NoCallInfo ())
3278
+ end
3279
+
3236
3280
function abstract_eval_throw_undef_if_not (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState , sv:: AbsIntState )
3237
3281
condt = abstract_eval_value (interp, e. args[2 ], sstate, sv)
3238
3282
condval = maybe_extract_const_bool (condt)
@@ -3443,22 +3487,31 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
3443
3487
return partition_restriction (partition)
3444
3488
end
3445
3489
3446
- function abstract_eval_binding_partition ! (interp:: AbstractInterpreter , g:: GlobalRef , sv:: AbsIntState )
3490
+ function lookup_binding_partition ! (interp:: AbstractInterpreter , g:: GlobalRef , sv:: AbsIntState )
3447
3491
force_binding_resolution! (g)
3448
3492
partition = lookup_binding_partition (get_inference_world (interp), g)
3449
3493
update_valid_age! (sv, WorldRange (partition. min_world, partition. max_world))
3494
+ partition
3495
+ end
3450
3496
3497
+ function walk_binding_partition! (interp:: AbstractInterpreter , partition:: Core.BindingPartition , sv:: AbsIntState )
3451
3498
while is_some_imported (binding_kind (partition))
3452
3499
imported_binding = partition_restriction (partition):: Core.Binding
3453
3500
partition = lookup_binding_partition (get_inference_world (interp), imported_binding)
3454
3501
update_valid_age! (sv, WorldRange (partition. min_world, partition. max_world))
3455
3502
end
3503
+ return partition
3504
+ end
3456
3505
3506
+ function abstract_eval_binding_partition! (interp:: AbstractInterpreter , g:: GlobalRef , sv:: AbsIntState )
3507
+ partition = lookup_binding_partition! (interp, g, sv)
3508
+ partition = walk_binding_partition! (interp, partition, sv)
3457
3509
return partition
3458
3510
end
3459
3511
3460
3512
function abstract_eval_partition_load (interp:: AbstractInterpreter , partition:: Core.BindingPartition )
3461
- if is_some_guard (binding_kind (partition))
3513
+ kind = binding_kind (partition)
3514
+ if is_some_guard (kind) || kind == BINDING_KIND_UNDEF_CONST
3462
3515
if InferenceParams (interp). assume_bindings_static
3463
3516
return RTEffects (Union{}, UndefVarError, EFFECTS_THROWS)
3464
3517
else
@@ -3468,38 +3521,40 @@ function abstract_eval_partition_load(interp::AbstractInterpreter, partition::Co
3468
3521
end
3469
3522
end
3470
3523
3471
- if is_some_const_binding ( binding_kind (partition) )
3524
+ if is_defined_const_binding (kind )
3472
3525
rt = Const (partition_restriction (partition))
3473
3526
return RTEffects (rt, Union{}, Effects (EFFECTS_TOTAL, inaccessiblememonly= is_mutation_free_argtype (rt) ? ALWAYS_TRUE : ALWAYS_FALSE))
3474
3527
end
3475
3528
3476
3529
rt = partition_restriction (partition)
3477
-
3478
3530
return RTEffects (rt, UndefVarError, generic_getglobal_effects)
3479
3531
end
3480
3532
3481
3533
function abstract_eval_globalref (interp:: AbstractInterpreter , g:: GlobalRef , saw_latestworld:: Bool , sv:: AbsIntState )
3482
3534
if saw_latestworld
3483
- return RTEffects ( Any, Any, generic_getglobal_effects)
3535
+ return Pair { RTEffects, Union{Nothing, Core.BindingPartition}} ( RTEffects ( Any, Any, generic_getglobal_effects), nothing )
3484
3536
end
3485
3537
partition = abstract_eval_binding_partition! (interp, g, sv)
3486
3538
ret = abstract_eval_partition_load (interp, partition)
3487
3539
if ret. rt != = Union{} && ret. exct === UndefVarError && InferenceParams (interp). assume_bindings_static
3488
3540
if isdefined (g, :binding ) && isdefined (g. binding, :value )
3489
- return RTEffects (ret. rt, Union{}, Effects (generic_getglobal_effects, nothrow= true ))
3541
+ ret = RTEffects (ret. rt, Union{}, Effects (generic_getglobal_effects, nothrow= true ))
3490
3542
end
3491
3543
# We do not assume in general that assigned global bindings remain assigned.
3492
3544
# The existence of pkgimages allows them to revert in practice.
3493
3545
end
3494
- return ret
3546
+ return Pair {RTEffects, Union{Nothing, Core.BindingPartition}} ( ret, partition)
3495
3547
end
3496
3548
3497
3549
function global_assignment_rt_exct (interp:: AbstractInterpreter , sv:: AbsIntState , saw_latestworld:: Bool , g:: GlobalRef , @nospecialize (newty))
3498
3550
if saw_latestworld
3499
- return Pair {Any,Any} (newty, Union{ErrorException, TypeError})
3551
+ return Pair {Pair{Any,Any}, Union{Core.BindingPartition, Nothing}} (
3552
+ Pair {Any,Any} (newty, Union{ErrorException, TypeError}), nothing )
3500
3553
end
3501
3554
partition = abstract_eval_binding_partition! (interp, g, sv)
3502
- return global_assignment_binding_rt_exct (interp, partition, newty)
3555
+ return Pair {Pair{Any,Any}, Union{Core.BindingPartition, Nothing}} (
3556
+ global_assignment_binding_rt_exct (interp, partition, newty),
3557
+ partition)
3503
3558
end
3504
3559
3505
3560
function global_assignment_binding_rt_exct (interp:: AbstractInterpreter , partition:: Core.BindingPartition , @nospecialize (newty))
@@ -3520,18 +3575,6 @@ function global_assignment_binding_rt_exct(interp::AbstractInterpreter, partitio
3520
3575
return Pair {Any,Any} (newty, Bottom)
3521
3576
end
3522
3577
3523
- function handle_global_assignment! (interp:: AbstractInterpreter , frame:: InferenceState , saw_latestworld:: Bool , lhs:: GlobalRef , @nospecialize (newty))
3524
- effect_free = ALWAYS_FALSE
3525
- nothrow = global_assignment_rt_exct (interp, frame, saw_latestworld, lhs, ignorelimited (newty))[2 ] === Union{}
3526
- inaccessiblememonly = ALWAYS_FALSE
3527
- if ! nothrow
3528
- sub_curr_ssaflag! (frame, IR_FLAG_NOTHROW)
3529
- end
3530
- sub_curr_ssaflag! (frame, IR_FLAG_EFFECT_FREE)
3531
- merge_effects! (interp, frame, Effects (EFFECTS_TOTAL; effect_free, nothrow, inaccessiblememonly))
3532
- return nothing
3533
- end
3534
-
3535
3578
abstract_eval_ssavalue (s:: SSAValue , sv:: InferenceState ) = abstract_eval_ssavalue (s, sv. ssavaluetypes)
3536
3579
3537
3580
function abstract_eval_ssavalue (s:: SSAValue , ssavaluetypes:: Vector{Any} )
0 commit comments