407407 if isa (a1, DataType) && ! isabstracttype (a1)
408408 if a1 === Module
409409 hasintersect (widenconst (sym), Symbol) || return Bottom
410- if isa (sym, Const) && isa (sym. val, Symbol) && isa (arg1, Const) &&
411- isdefinedconst_globalref (GlobalRef (arg1. val:: Module , sym. val:: Symbol ))
412- return Const (true )
413- end
410+ # isa(sym, Const) case intercepted in abstract interpretation
414411 elseif isa (sym, Const)
415412 val = sym. val
416413 if isa (val, Symbol)
@@ -1160,7 +1157,9 @@ end
11601157 if isa (sv, Module)
11611158 setfield && return Bottom
11621159 if isa (nv, Symbol)
1163- return abstract_eval_global (sv, nv)
1160+ # In ordinary inference, this case is intercepted early and
1161+ # re-routed to `getglobal`.
1162+ return Any
11641163 end
11651164 return Bottom
11661165 end
@@ -1407,8 +1406,9 @@ end
14071406 elseif ff === Core. modifyglobal!
14081407 o = unwrapva (argtypes[2 ])
14091408 f = unwrapva (argtypes[3 ])
1410- RT = modifyglobal!_tfunc (𝕃ᵢ, o, f, Any, Any, Symbol)
1411- TF = getglobal_tfunc (𝕃ᵢ, o, f, Symbol)
1409+ GT = abstract_eval_get_binding_type (interp, sv, o, f). rt
1410+ RT = isa (GT, Const) ? Pair{GT. val, GT. val} : Pair
1411+ TF = isa (GT, Const) ? GT. val : Any
14121412 elseif ff === Core. memoryrefmodify!
14131413 o = unwrapva (argtypes[2 ])
14141414 RT = memoryrefmodify!_tfunc (𝕃ᵢ, o, Any, Any, Symbol, Bool)
@@ -2277,20 +2277,6 @@ function _builtin_nothrow(𝕃::AbstractLattice, @nospecialize(f::Builtin), argt
22772277 elseif f === typeassert
22782278 na == 2 || return false
22792279 return typeassert_nothrow (𝕃, argtypes[1 ], argtypes[2 ])
2280- elseif f === getglobal
2281- if na == 2
2282- return getglobal_nothrow (argtypes[1 ], argtypes[2 ])
2283- elseif na == 3
2284- return getglobal_nothrow (argtypes[1 ], argtypes[2 ], argtypes[3 ])
2285- end
2286- return false
2287- elseif f === setglobal!
2288- if na == 3
2289- return setglobal!_nothrow (argtypes[1 ], argtypes[2 ], argtypes[3 ])
2290- elseif na == 4
2291- return setglobal!_nothrow (argtypes[1 ], argtypes[2 ], argtypes[3 ], argtypes[4 ])
2292- end
2293- return false
22942280 elseif f === Core. get_binding_type
22952281 na == 2 || return false
22962282 return get_binding_type_nothrow (𝕃, argtypes[1 ], argtypes[2 ])
@@ -2473,7 +2459,8 @@ function getfield_effects(𝕃::AbstractLattice, argtypes::Vector{Any}, @nospeci
24732459 end
24742460 end
24752461 if hasintersect (widenconst (obj), Module)
2476- inaccessiblememonly = getglobal_effects (argtypes, rt). inaccessiblememonly
2462+ # Modeled more precisely in abstract_eval_getglobal
2463+ inaccessiblememonly = ALWAYS_FALSE
24772464 elseif is_mutation_free_argtype (obj)
24782465 inaccessiblememonly = ALWAYS_TRUE
24792466 else
@@ -2482,24 +2469,7 @@ function getfield_effects(𝕃::AbstractLattice, argtypes::Vector{Any}, @nospeci
24822469 return Effects (EFFECTS_TOTAL; consistent, nothrow, inaccessiblememonly, noub)
24832470end
24842471
2485- function getglobal_effects (argtypes:: Vector{Any} , @nospecialize (rt))
2486- 2 ≤ length (argtypes) ≤ 3 || return EFFECTS_THROWS
2487- consistent = inaccessiblememonly = ALWAYS_FALSE
2488- nothrow = false
2489- M, s = argtypes[1 ], argtypes[2 ]
2490- if (length (argtypes) == 3 ? getglobal_nothrow (M, s, argtypes[3 ]) : getglobal_nothrow (M, s))
2491- nothrow = true
2492- # typeasserts below are already checked in `getglobal_nothrow`
2493- Mval, sval = (M:: Const ). val:: Module , (s:: Const ). val:: Symbol
2494- if isconst (Mval, sval)
2495- consistent = ALWAYS_TRUE
2496- if is_mutation_free_argtype (rt)
2497- inaccessiblememonly = ALWAYS_TRUE
2498- end
2499- end
2500- end
2501- return Effects (EFFECTS_TOTAL; consistent, nothrow, inaccessiblememonly)
2502- end
2472+
25032473
25042474"""
25052475 builtin_effects(𝕃::AbstractLattice, f::Builtin, argtypes::Vector{Any}, rt) -> Effects
@@ -2525,11 +2495,13 @@ function builtin_effects(𝕃::AbstractLattice, @nospecialize(f::Builtin), argty
25252495 if f === isdefined
25262496 return isdefined_effects (𝕃, argtypes)
25272497 elseif f === getglobal
2528- return getglobal_effects (argtypes, rt)
2498+ 2 ≤ length (argtypes) ≤ 3 || return EFFECTS_THROWS
2499+ # Modeled more precisely in abstract_eval_getglobal
2500+ return Effects (EFFECTS_TOTAL; consistent= ALWAYS_FALSE, nothrow= false , inaccessiblememonly= ALWAYS_FALSE)
25292501 elseif f === Core. get_binding_type
25302502 length (argtypes) == 2 || return EFFECTS_THROWS
2531- effect_free = get_binding_type_effect_free (argtypes[ 1 ], argtypes[ 2 ]) ? ALWAYS_TRUE : ALWAYS_FALSE
2532- return Effects (EFFECTS_TOTAL; effect_free)
2503+ # Modeled more precisely in abstract_eval_get_binding_type
2504+ return Effects (EFFECTS_TOTAL; effect_free= ALWAYS_FALSE )
25332505 elseif f === compilerbarrier
25342506 length (argtypes) == 2 || return Effects (EFFECTS_THROWS; consistent= ALWAYS_FALSE)
25352507 setting = argtypes[1 ]
@@ -3065,118 +3037,28 @@ function typename_static(@nospecialize(t))
30653037 return isType (t) ? _typename (t. parameters[1 ]) : Core. TypeName
30663038end
30673039
3068- function global_order_nothrow (@nospecialize (o), loading:: Bool , storing:: Bool )
3069- o isa Const || return false
3040+ function global_order_exct (@nospecialize (o), loading:: Bool , storing:: Bool )
3041+ if ! (o isa Const)
3042+ if o === Symbol
3043+ return ConcurrencyViolationError
3044+ elseif ! hasintersect (o, Symbol)
3045+ return TypeError
3046+ else
3047+ return Union{ConcurrencyViolationError, TypeError}
3048+ end
3049+ end
30703050 sym = o. val
30713051 if sym isa Symbol
30723052 order = get_atomic_order (sym, loading, storing)
3073- return order != = MEMORY_ORDER_INVALID && order != = MEMORY_ORDER_NOTATOMIC
3074- end
3075- return false
3076- end
3077- @nospecs function getglobal_nothrow (M, s, o)
3078- global_order_nothrow (o, #= loading=# true , #= storing=# false ) || return false
3079- return getglobal_nothrow (M, s)
3080- end
3081- @nospecs function getglobal_nothrow (M, s)
3082- if M isa Const && s isa Const
3083- M, s = M. val, s. val
3084- if M isa Module && s isa Symbol
3085- return isdefinedconst_globalref (GlobalRef (M, s))
3086- end
3087- end
3088- return false
3089- end
3090- @nospecs function getglobal_tfunc (𝕃:: AbstractLattice , M, s, order= Symbol)
3091- if M isa Const && s isa Const
3092- M, s = M. val, s. val
3093- if M isa Module && s isa Symbol
3094- return abstract_eval_global (M, s)
3095- end
3096- return Bottom
3097- elseif ! (hasintersect (widenconst (M), Module) && hasintersect (widenconst (s), Symbol))
3098- return Bottom
3099- end
3100- T = get_binding_type_tfunc (𝕃, M, s)
3101- T isa Const && return T. val
3102- return Any
3103- end
3104- @nospecs function setglobal!_tfunc (𝕃:: AbstractLattice , M, s, v, order= Symbol)
3105- if ! (hasintersect (widenconst (M), Module) && hasintersect (widenconst (s), Symbol))
3106- return Bottom
3107- end
3108- return v
3109- end
3110- @nospecs function swapglobal!_tfunc (𝕃:: AbstractLattice , M, s, v, order= Symbol)
3111- setglobal!_tfunc (𝕃, M, s, v) === Bottom && return Bottom
3112- return getglobal_tfunc (𝕃, M, s)
3113- end
3114- @nospecs function modifyglobal!_tfunc (𝕃:: AbstractLattice , M, s, op, v, order= Symbol)
3115- T = get_binding_type_tfunc (𝕃, M, s)
3116- T === Bottom && return Bottom
3117- T isa Const || return Pair
3118- T = T. val
3119- return Pair{T, T}
3120- end
3121- @nospecs function replaceglobal!_tfunc (𝕃:: AbstractLattice , M, s, x, v, success_order= Symbol, failure_order= Symbol)
3122- v = setglobal!_tfunc (𝕃, M, s, v)
3123- v === Bottom && return Bottom
3124- T = get_binding_type_tfunc (𝕃, M, s)
3125- T === Bottom && return Bottom
3126- T isa Const || return ccall (:jl_apply_cmpswap_type , Any, (Any,), T) where T
3127- T = T. val
3128- return ccall (:jl_apply_cmpswap_type , Any, (Any,), T)
3129- end
3130- @nospecs function setglobalonce!_tfunc (𝕃:: AbstractLattice , M, s, v, success_order= Symbol, failure_order= Symbol)
3131- setglobal!_tfunc (𝕃, M, s, v) === Bottom && return Bottom
3132- return Bool
3133- end
3134-
3135- add_tfunc (Core. getglobal, 2 , 3 , getglobal_tfunc, 1 )
3136- add_tfunc (Core. setglobal!, 3 , 4 , setglobal!_tfunc, 3 )
3137- add_tfunc (Core. swapglobal!, 3 , 4 , swapglobal!_tfunc, 3 )
3138- add_tfunc (Core. modifyglobal!, 4 , 5 , modifyglobal!_tfunc, 3 )
3139- add_tfunc (Core. replaceglobal!, 4 , 6 , replaceglobal!_tfunc, 3 )
3140- add_tfunc (Core. setglobalonce!, 3 , 5 , setglobalonce!_tfunc, 3 )
3141-
3142- @nospecs function setglobal!_nothrow (M, s, newty, o)
3143- global_order_nothrow (o, #= loading=# false , #= storing=# true ) || return false
3144- return setglobal!_nothrow (M, s, newty)
3145- end
3146- @nospecs function setglobal!_nothrow (M, s, newty)
3147- if M isa Const && s isa Const
3148- M, s = M. val, s. val
3149- if isa (M, Module) && isa (s, Symbol)
3150- return global_assignment_nothrow (M, s, newty)
3151- end
3152- end
3153- return false
3154- end
3155-
3156- function global_assignment_nothrow (M:: Module , s:: Symbol , @nospecialize (newty))
3157- if ! isconst (M, s)
3158- ty = ccall (:jl_get_binding_type , Any, (Any, Any), M, s)
3159- return ty isa Type && widenconst (newty) <: ty
3160- end
3161- return false
3162- end
3163-
3164- @nospecs function get_binding_type_effect_free (M, s)
3165- if M isa Const && s isa Const
3166- M, s = M. val, s. val
3167- if M isa Module && s isa Symbol
3168- return ccall (:jl_get_binding_type , Any, (Any, Any), M, s) != = nothing
3053+ if order != = MEMORY_ORDER_INVALID && order != = MEMORY_ORDER_NOTATOMIC
3054+ return Union{}
3055+ else
3056+ return ConcurrencyViolationError
31693057 end
3058+ else
3059+ return TypeError
31703060 end
3171- return false
3172- end
3173- @nospecs function get_binding_type_tfunc (𝕃:: AbstractLattice , M, s)
3174- if get_binding_type_effect_free (M, s)
3175- return Const (Core. get_binding_type ((M:: Const ). val:: Module , (s:: Const ). val:: Symbol ))
3176- end
3177- return Type
31783061end
3179- add_tfunc (Core. get_binding_type, 2 , 2 , get_binding_type_tfunc, 0 )
31803062
31813063@nospecs function get_binding_type_nothrow (𝕃:: AbstractLattice , M, s)
31823064 ⊑ = partialorder (𝕃)
0 commit comments