@@ -2862,7 +2862,7 @@ function sp_type_rewrap(@nospecialize(T), mi::MethodInstance, isreturn::Bool)
2862
2862
end
2863
2863
2864
2864
function abstract_eval_cfunction (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState , sv:: AbsIntState )
2865
- f = abstract_eval_value (interp, e. args[2 ], sstate, sv)
2865
+ (f, exct) = abstract_eval_value (interp, e. args[2 ], sstate, sv)
2866
2866
# rt = sp_type_rewrap(e.args[3], sv.linfo, true)
2867
2867
atv = e. args[4 ]:: SimpleVector
2868
2868
at = Vector {Any} (undef, length (atv) + 1 )
@@ -2921,30 +2921,32 @@ function abstract_eval_value_expr(interp::AbstractInterpreter, e::Expr, sv::AbsI
2921
2921
# @assert false "Unexpected EXPR head in value position"
2922
2922
merge_effects! (interp, sv, EFFECTS_UNKNOWN)
2923
2923
end
2924
- return Any
2924
+ return Pair { Any, Any} (Any, Any)
2925
2925
end
2926
2926
2927
2927
function abstract_eval_value (interp:: AbstractInterpreter , @nospecialize (e), sstate:: StatementState , sv:: AbsIntState )
2928
2928
if isa (e, Expr)
2929
2929
return abstract_eval_value_expr (interp, e, sv)
2930
2930
else
2931
- (;rt, effects) = abstract_eval_special_value (interp, e, sstate, sv)
2931
+ (;rt, exct, effects) = abstract_eval_special_value (interp, e, sstate, sv)
2932
2932
merge_effects! (interp, sv, effects)
2933
- return collect_limitations! (rt, sv)
2933
+ return Pair {Any, Any} ( collect_limitations! (rt, sv), exct )
2934
2934
end
2935
2935
end
2936
2936
2937
2937
function collect_argtypes (interp:: AbstractInterpreter , ea:: Vector{Any} , sstate:: StatementState , sv:: AbsIntState )
2938
2938
n = length (ea)
2939
2939
argtypes = Vector {Any} (undef, n)
2940
+ exct = Union{}
2940
2941
@inbounds for i = 1 : n
2941
- ai = abstract_eval_value (interp, ea[i], sstate, sv)
2942
+ (ai, ei) = abstract_eval_value (interp, ea[i], sstate, sv)
2942
2943
if ai === Bottom
2943
2944
return nothing
2944
2945
end
2945
2946
argtypes[i] = ai
2947
+ exct = Union{exct, ei}
2946
2948
end
2947
- return argtypes
2949
+ return Pair {Vector{Any}, Any} ( argtypes, exct)
2948
2950
end
2949
2951
2950
2952
struct RTEffects
@@ -2984,21 +2986,23 @@ function abstract_eval_call(interp::AbstractInterpreter, e::Expr, sstate::Statem
2984
2986
if argtypes === nothing
2985
2987
return Future (RTEffects (Bottom, Any, Effects ()))
2986
2988
end
2989
+ (argtypes, aexct) = argtypes
2987
2990
arginfo = ArgInfo (ea, argtypes)
2988
2991
call = abstract_call (interp, arginfo, sstate, sv):: Future
2989
2992
return Future {RTEffects} (call, interp, sv) do call, interp, sv
2990
2993
(; rt, exct, effects, refinements) = call
2991
- return RTEffects (rt, exct, effects, refinements)
2994
+ return RTEffects (rt, tmerge ( typeinf_lattice (interp), exct, aexct) , effects, refinements)
2992
2995
end
2993
2996
end
2994
2997
2995
-
2998
+ const generic_new_exct = Union{ErrorException, TypeError}
2996
2999
function abstract_eval_new (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
2997
3000
sv:: AbsIntState )
2998
3001
𝕃ᵢ = typeinf_lattice (interp)
2999
- rt, isexact = instanceof_tfunc (abstract_eval_value (interp, e. args[1 ], sstate, sv), true )
3002
+ (ea1, a1exct) = abstract_eval_value (interp, e. args[1 ], sstate, sv)
3003
+ rt, isexact = instanceof_tfunc (ea1, true )
3000
3004
ut = unwrap_unionall (rt)
3001
- exct = Union{ErrorException,TypeError}
3005
+ nothrow = false
3002
3006
if isa (ut, DataType) && ! isabstracttype (ut)
3003
3007
ismutable = ismutabletype (ut)
3004
3008
fcount = datatype_fieldcount (ut)
@@ -3018,12 +3022,15 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, sstate::Stateme
3018
3022
end
3019
3023
if isconcretedispatch (rt)
3020
3024
nothrow = true
3025
+ exct = Union{}
3021
3026
@assert fcount != = nothing && fcount ≥ nargs " malformed :new expression" # syntactically enforced by the front-end
3022
3027
ats = Vector {Any} (undef, nargs)
3023
3028
local anyrefine = false
3024
3029
local allconst = true
3025
3030
for i = 1 : nargs
3026
- at = widenslotwrapper (abstract_eval_value (interp, e. args[i+ 1 ], sstate, sv))
3031
+ (atn, aexct) = abstract_eval_value (interp, e. args[i+ 1 ], sstate, sv)
3032
+ exct = Union{exct, aexct}
3033
+ at = widenslotwrapper (atn)
3027
3034
ft = fieldtype (rt, i)
3028
3035
nothrow && (nothrow = ⊑ (𝕃ᵢ, at, ft))
3029
3036
at = tmeet (𝕃ᵢ, at, ft)
@@ -3039,6 +3046,7 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, sstate::Stateme
3039
3046
end
3040
3047
ats[i] = at
3041
3048
end
3049
+ nothrow || (exct = Union{exct, TypeError})
3042
3050
if fcount == nargs && consistent === ALWAYS_TRUE && allconst
3043
3051
argvals = Vector {Any} (undef, nargs)
3044
3052
for j in 1 : nargs
@@ -3054,24 +3062,26 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, sstate::Stateme
3054
3062
end
3055
3063
else
3056
3064
rt = refine_partial_type (rt)
3057
- nothrow = false
3065
+ exct = generic_new_exct
3058
3066
end
3059
3067
else
3060
3068
consistent = ALWAYS_FALSE
3061
- nothrow = false
3069
+ exct = generic_new_exct
3062
3070
end
3063
- nothrow && ( exct = Union{})
3071
+ exct = Union{exct, a1exct}
3064
3072
effects = Effects (EFFECTS_TOTAL; consistent, nothrow)
3065
3073
return RTEffects (rt, exct, effects)
3066
3074
end
3067
3075
3068
3076
function abstract_eval_splatnew (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
3069
3077
sv:: AbsIntState )
3070
3078
𝕃ᵢ = typeinf_lattice (interp)
3071
- rt, isexact = instanceof_tfunc (abstract_eval_value (interp, e. args[1 ], sstate, sv), true )
3079
+ (a1, a1exct) = abstract_eval_value (interp, e. args[1 ], sstate, sv)
3080
+ rt, isexact = instanceof_tfunc (a1, true )
3072
3081
nothrow = false
3073
3082
if length (e. args) == 2 && isconcretedispatch (rt) && ! ismutabletype (rt)
3074
- at = abstract_eval_value (interp, e. args[2 ], sstate, sv)
3083
+ (at, a2exct) = abstract_eval_value (interp, e. args[2 ], sstate, sv)
3084
+ exct = Union{a1exct, a2exct}
3075
3085
n = fieldcount (rt)
3076
3086
if (isa (at, Const) && isa (at. val, Tuple) && n == length (at. val:: Tuple ) &&
3077
3087
(let t = rt, at = at
@@ -3087,12 +3097,14 @@ function abstract_eval_splatnew(interp::AbstractInterpreter, e::Expr, sstate::St
3087
3097
nothrow = isexact
3088
3098
rt = PartialStruct (𝕃ᵢ, rt, at. fields:: Vector{Any} )
3089
3099
end
3100
+ nothrow || (exct = Union{exct, generic_new_exct})
3090
3101
else
3091
3102
rt = refine_partial_type (rt)
3103
+ exct = Any
3092
3104
end
3093
3105
consistent = ! ismutabletype (rt) ? ALWAYS_TRUE : CONSISTENT_IF_NOTRETURNED
3094
3106
effects = Effects (EFFECTS_TOTAL; consistent, nothrow)
3095
- return RTEffects (rt, Any , effects)
3107
+ return RTEffects (rt, exct , effects)
3096
3108
end
3097
3109
3098
3110
function abstract_eval_new_opaque_closure (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
@@ -3107,6 +3119,7 @@ function abstract_eval_new_opaque_closure(interp::AbstractInterpreter, e::Expr,
3107
3119
rt = Bottom
3108
3120
effects = EFFECTS_THROWS
3109
3121
else
3122
+ (argtypes, _) = argtypes
3110
3123
mi = frame_instance (sv)
3111
3124
rt = opaque_closure_tfunc (𝕃ᵢ, argtypes[1 ], argtypes[2 ], argtypes[3 ],
3112
3125
argtypes[5 ], argtypes[6 : end ], mi)
@@ -3134,7 +3147,7 @@ end
3134
3147
function abstract_eval_copyast (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
3135
3148
sv:: AbsIntState )
3136
3149
effects = EFFECTS_UNKNOWN
3137
- rt = abstract_eval_value (interp, e. args[1 ], sstate, sv)
3150
+ (rt, _) = abstract_eval_value (interp, e. args[1 ], sstate, sv)
3138
3151
if rt isa Const && rt. val isa Expr
3139
3152
# `copyast` makes copies of Exprs
3140
3153
rt = Expr
@@ -3190,7 +3203,7 @@ function abstract_eval_isdefined(interp::AbstractInterpreter, @nospecialize(sym)
3190
3203
end
3191
3204
3192
3205
function abstract_eval_throw_undef_if_not (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState , sv:: AbsIntState )
3193
- condt = abstract_eval_value (interp, e. args[2 ], sstate, sv)
3206
+ ( condt, argexct) = abstract_eval_value (interp, e. args[2 ], sstate, sv)
3194
3207
condval = maybe_extract_const_bool (condt)
3195
3208
rt = Nothing
3196
3209
exct = UndefVarError
@@ -3205,7 +3218,7 @@ function abstract_eval_throw_undef_if_not(interp::AbstractInterpreter, e::Expr,
3205
3218
elseif ! hasintersect (widenconst (condt), Bool)
3206
3219
rt = Union{}
3207
3220
end
3208
- return RTEffects (rt, exct, effects)
3221
+ return RTEffects (rt, Union{ exct, argexct} , effects)
3209
3222
end
3210
3223
3211
3224
function abstract_eval_the_exception (:: AbstractInterpreter , sv:: InferenceState )
@@ -3275,8 +3288,8 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, ssta
3275
3288
# N.B.: abstract_eval_value_expr can modify the global effects, but
3276
3289
# we move out any arguments with effects during SSA construction later
3277
3290
# and recompute the effects.
3278
- rt = abstract_eval_value_expr (interp, e, sv)
3279
- return RTEffects (rt, Any , EFFECTS_TOTAL)
3291
+ (rt, exct) = abstract_eval_value_expr (interp, e, sv)
3292
+ return RTEffects (rt, exct , EFFECTS_TOTAL)
3280
3293
end
3281
3294
3282
3295
# refine the result of instantiation of partially-known type `t` if some invariant can be assumed
@@ -3296,12 +3309,14 @@ function abstract_eval_foreigncall(interp::AbstractInterpreter, e::Expr, sstate:
3296
3309
mi = frame_instance (sv)
3297
3310
t = sp_type_rewrap (e. args[2 ], mi, true )
3298
3311
for i = 3 : length (e. args)
3299
- if abstract_eval_value (interp, e. args[i], sstate, sv) === Bottom
3312
+ (at, aexct) = abstract_eval_value (interp, e. args[i], sstate, sv)
3313
+ if at === Bottom
3300
3314
return RTEffects (Bottom, Any, EFFECTS_THROWS)
3301
3315
end
3302
3316
end
3303
3317
effects = foreigncall_effects (e) do @nospecialize x
3304
- abstract_eval_value (interp, x, sstate, sv)
3318
+ (at, aexct) = abstract_eval_value (interp, x, sstate, sv)
3319
+ at
3305
3320
end
3306
3321
cconv = e. args[5 ]
3307
3322
if isa (cconv, QuoteNode) && (v = cconv. value; isa (v, Tuple{Symbol, UInt16}))
@@ -3367,6 +3382,10 @@ end
3367
3382
3368
3383
function abstract_eval_globalref_type (g:: GlobalRef , src:: Union{CodeInfo, IRCode, IncrementalCompact} , retry_after_resolve:: Bool = true )
3369
3384
worlds = world_range (src)
3385
+ abstract_eval_globalref_type (g, worlds, retry_after_resolve)
3386
+ end
3387
+
3388
+ function abstract_eval_globalref_type (g:: GlobalRef , worlds:: WorldRange , retry_after_resolve:: Bool = true )
3370
3389
partition = lookup_binding_partition (min_world (worlds), g)
3371
3390
partition. max_world < max_world (worlds) && return Any
3372
3391
while is_some_imported (binding_kind (partition))
@@ -3380,7 +3399,7 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
3380
3399
# the binding unless necessary - doing so triggers an additional lookup, which though
3381
3400
# not super expensive is hot enough to show up in benchmarks.
3382
3401
force_binding_resolution! (g)
3383
- return abstract_eval_globalref_type (g, src , false )
3402
+ return abstract_eval_globalref_type (g, worlds , false )
3384
3403
end
3385
3404
# return Union{}
3386
3405
return Any
@@ -3391,6 +3410,11 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
3391
3410
return partition_restriction (partition)
3392
3411
end
3393
3412
3413
+ function is_global_nothrow_const_in_all_worlds (g:: GlobalRef , worlds:: WorldRange , retry_after_resolve:: Bool = true )
3414
+ # TODO : We may be fine if there's two different partitions with different constants
3415
+ return isa (abstract_eval_globalref_type (g, worlds, retry_after_resolve), Const)
3416
+ end
3417
+
3394
3418
function abstract_eval_binding_partition! (interp:: AbstractInterpreter , g:: GlobalRef , sv:: AbsIntState )
3395
3419
force_binding_resolution! (g)
3396
3420
partition = lookup_binding_partition (get_inference_world (interp), g)
@@ -3821,7 +3845,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
3821
3845
elseif isa (stmt, GotoIfNot)
3822
3846
condx = stmt. cond
3823
3847
condslot = ssa_def_slot (condx, frame)
3824
- condt = abstract_eval_value (interp, condx, StatementState (currstate, currsaw_latestworld), frame)
3848
+ condt, aexct = abstract_eval_value (interp, condx, StatementState (currstate, currsaw_latestworld), frame)
3849
+ @assert aexct === Bottom # Guaranteed in lowering
3825
3850
if condt === Bottom
3826
3851
ssavaluetypes[currpc] = Bottom
3827
3852
empty! (frame. pclimitations)
@@ -3908,7 +3933,11 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
3908
3933
@goto fallthrough
3909
3934
end
3910
3935
elseif isa (stmt, ReturnNode)
3911
- rt = abstract_eval_value (interp, stmt. val, StatementState (currstate, currsaw_latestworld), frame)
3936
+ rt, rexct = abstract_eval_value (interp, stmt. val, StatementState (currstate, currsaw_latestworld), frame)
3937
+ if rexct != = Union{}
3938
+ update_exc_bestguess! (interp, rexct, frame)
3939
+ propagate_to_error_handler! (currstate, currsaw_latestworld, frame, 𝕃ᵢ)
3940
+ end
3912
3941
if update_bestguess! (interp, frame, currstate, rt)
3913
3942
update_cycle_worklists! (frame) do caller:: InferenceState , caller_pc:: Int
3914
3943
# no reason to revisit if that call-site doesn't affect the final result
@@ -3921,7 +3950,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
3921
3950
ssavaluetypes[currpc] = Any
3922
3951
add_curr_ssaflag! (frame, IR_FLAG_NOTHROW)
3923
3952
if isdefined (stmt, :scope )
3924
- scopet = abstract_eval_value (interp, stmt. scope, StatementState (currstate, currsaw_latestworld), frame)
3953
+ scopet, sexct = abstract_eval_value (interp, stmt. scope, StatementState (currstate, currsaw_latestworld), frame)
3954
+ @assert sexct === Bottom # Guaranteed in lowering
3925
3955
handler = gethandler (frame, currpc + 1 ):: TryCatchFrame
3926
3956
@assert handler. scopet != = nothing
3927
3957
if ! ⊑ (𝕃ᵢ, scopet, handler. scopet)
@@ -4023,13 +4053,13 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
4023
4053
changes = StateUpdate (lhs:: SlotNumber , VarState (rt, false ))
4024
4054
end
4025
4055
end
4026
- if ! has_curr_ssaflag (frame, IR_FLAG_NOTHROW)
4027
- if exct != = Union{}
4028
- update_exc_bestguess! (interp, exct, frame)
4029
- # TODO : assert that these conditions match. For now, we assume the `nothrow` flag
4030
- # to be correct, but allow the exct to be an over-approximation.
4031
- end
4056
+ if exct != = Union{}
4057
+ update_exc_bestguess! (interp, exct, frame)
4032
4058
propagate_to_error_handler! (currstate, currsaw_latestworld, frame, 𝕃ᵢ)
4059
+ # TODO : assert that these conditions match. For now, we assume the `nothrow` flag
4060
+ # to be correct, but allow the exct to be an over-approximation.
4061
+ else
4062
+ has_curr_ssaflag (frame, IR_FLAG_NOTHROW)
4033
4063
end
4034
4064
if rt === Bottom
4035
4065
ssavaluetypes[currpc] = Bottom
0 commit comments