@@ -2862,7 +2862,7 @@ function sp_type_rewrap(@nospecialize(T), mi::MethodInstance, isreturn::Bool)
28622862end
28632863
28642864function 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)
28662866 # rt = sp_type_rewrap(e.args[3], sv.linfo, true)
28672867 atv = e. args[4 ]:: SimpleVector
28682868 at = Vector {Any} (undef, length (atv) + 1 )
@@ -2921,30 +2921,32 @@ function abstract_eval_value_expr(interp::AbstractInterpreter, e::Expr, sv::AbsI
29212921 # @assert false "Unexpected EXPR head in value position"
29222922 merge_effects! (interp, sv, EFFECTS_UNKNOWN)
29232923 end
2924- return Any
2924+ return Pair { Any, Any} (Any, Any)
29252925end
29262926
29272927function abstract_eval_value (interp:: AbstractInterpreter , @nospecialize (e), sstate:: StatementState , sv:: AbsIntState )
29282928 if isa (e, Expr)
29292929 return abstract_eval_value_expr (interp, e, sv)
29302930 else
2931- (;rt, effects) = abstract_eval_special_value (interp, e, sstate, sv)
2931+ (;rt, exct, effects) = abstract_eval_special_value (interp, e, sstate, sv)
29322932 merge_effects! (interp, sv, effects)
2933- return collect_limitations! (rt, sv)
2933+ return Pair {Any, Any} ( collect_limitations! (rt, sv), exct )
29342934 end
29352935end
29362936
29372937function collect_argtypes (interp:: AbstractInterpreter , ea:: Vector{Any} , sstate:: StatementState , sv:: AbsIntState )
29382938 n = length (ea)
29392939 argtypes = Vector {Any} (undef, n)
2940+ exct = Union{}
29402941 @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)
29422943 if ai === Bottom
29432944 return nothing
29442945 end
29452946 argtypes[i] = ai
2947+ exct = Union{exct, ei}
29462948 end
2947- return argtypes
2949+ return Pair {Vector{Any}, Any} ( argtypes, exct)
29482950end
29492951
29502952struct RTEffects
@@ -2984,21 +2986,23 @@ function abstract_eval_call(interp::AbstractInterpreter, e::Expr, sstate::Statem
29842986 if argtypes === nothing
29852987 return Future (RTEffects (Bottom, Any, Effects ()))
29862988 end
2989+ (argtypes, aexct) = argtypes
29872990 arginfo = ArgInfo (ea, argtypes)
29882991 call = abstract_call (interp, arginfo, sstate, sv):: Future
29892992 return Future {RTEffects} (call, interp, sv) do call, interp, sv
29902993 (; rt, exct, effects, refinements) = call
2991- return RTEffects (rt, exct, effects, refinements)
2994+ return RTEffects (rt, tmerge ( typeinf_lattice (interp), exct, aexct) , effects, refinements)
29922995 end
29932996end
29942997
2995-
2998+ const generic_new_exct = Union{ErrorException, TypeError}
29962999function abstract_eval_new (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
29973000 sv:: AbsIntState )
29983001 𝕃ᵢ = 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 )
30003004 ut = unwrap_unionall (rt)
3001- exct = Union{ErrorException,TypeError}
3005+ nothrow = false
30023006 if isa (ut, DataType) && ! isabstracttype (ut)
30033007 ismutable = ismutabletype (ut)
30043008 fcount = datatype_fieldcount (ut)
@@ -3018,12 +3022,15 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, sstate::Stateme
30183022 end
30193023 if isconcretedispatch (rt)
30203024 nothrow = true
3025+ exct = Union{}
30213026 @assert fcount != = nothing && fcount ≥ nargs " malformed :new expression" # syntactically enforced by the front-end
30223027 ats = Vector {Any} (undef, nargs)
30233028 local anyrefine = false
30243029 local allconst = true
30253030 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)
30273034 ft = fieldtype (rt, i)
30283035 nothrow && (nothrow = ⊑ (𝕃ᵢ, at, ft))
30293036 at = tmeet (𝕃ᵢ, at, ft)
@@ -3039,6 +3046,7 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, sstate::Stateme
30393046 end
30403047 ats[i] = at
30413048 end
3049+ nothrow || (exct = Union{exct, TypeError})
30423050 if fcount == nargs && consistent === ALWAYS_TRUE && allconst
30433051 argvals = Vector {Any} (undef, nargs)
30443052 for j in 1 : nargs
@@ -3054,24 +3062,26 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, sstate::Stateme
30543062 end
30553063 else
30563064 rt = refine_partial_type (rt)
3057- nothrow = false
3065+ exct = generic_new_exct
30583066 end
30593067 else
30603068 consistent = ALWAYS_FALSE
3061- nothrow = false
3069+ exct = generic_new_exct
30623070 end
3063- nothrow && ( exct = Union{})
3071+ exct = Union{exct, a1exct}
30643072 effects = Effects (EFFECTS_TOTAL; consistent, nothrow)
30653073 return RTEffects (rt, exct, effects)
30663074end
30673075
30683076function abstract_eval_splatnew (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
30693077 sv:: AbsIntState )
30703078 𝕃ᵢ = 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 )
30723081 nothrow = false
30733082 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}
30753085 n = fieldcount (rt)
30763086 if (isa (at, Const) && isa (at. val, Tuple) && n == length (at. val:: Tuple ) &&
30773087 (let t = rt, at = at
@@ -3087,12 +3097,14 @@ function abstract_eval_splatnew(interp::AbstractInterpreter, e::Expr, sstate::St
30873097 nothrow = isexact
30883098 rt = PartialStruct (𝕃ᵢ, rt, at. fields:: Vector{Any} )
30893099 end
3100+ nothrow || (exct = Union{exct, generic_new_exct})
30903101 else
30913102 rt = refine_partial_type (rt)
3103+ exct = Any
30923104 end
30933105 consistent = ! ismutabletype (rt) ? ALWAYS_TRUE : CONSISTENT_IF_NOTRETURNED
30943106 effects = Effects (EFFECTS_TOTAL; consistent, nothrow)
3095- return RTEffects (rt, Any , effects)
3107+ return RTEffects (rt, exct , effects)
30963108end
30973109
30983110function 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,
31073119 rt = Bottom
31083120 effects = EFFECTS_THROWS
31093121 else
3122+ (argtypes, _) = argtypes
31103123 mi = frame_instance (sv)
31113124 rt = opaque_closure_tfunc (𝕃ᵢ, argtypes[1 ], argtypes[2 ], argtypes[3 ],
31123125 argtypes[5 ], argtypes[6 : end ], mi)
@@ -3134,7 +3147,7 @@ end
31343147function abstract_eval_copyast (interp:: AbstractInterpreter , e:: Expr , sstate:: StatementState ,
31353148 sv:: AbsIntState )
31363149 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)
31383151 if rt isa Const && rt. val isa Expr
31393152 # `copyast` makes copies of Exprs
31403153 rt = Expr
@@ -3190,7 +3203,7 @@ function abstract_eval_isdefined(interp::AbstractInterpreter, @nospecialize(sym)
31903203end
31913204
31923205function 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)
31943207 condval = maybe_extract_const_bool (condt)
31953208 rt = Nothing
31963209 exct = UndefVarError
@@ -3205,7 +3218,7 @@ function abstract_eval_throw_undef_if_not(interp::AbstractInterpreter, e::Expr,
32053218 elseif ! hasintersect (widenconst (condt), Bool)
32063219 rt = Union{}
32073220 end
3208- return RTEffects (rt, exct, effects)
3221+ return RTEffects (rt, Union{ exct, argexct} , effects)
32093222end
32103223
32113224function abstract_eval_the_exception (:: AbstractInterpreter , sv:: InferenceState )
@@ -3275,8 +3288,8 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, ssta
32753288 # N.B.: abstract_eval_value_expr can modify the global effects, but
32763289 # we move out any arguments with effects during SSA construction later
32773290 # 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)
32803293end
32813294
32823295# 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:
32963309 mi = frame_instance (sv)
32973310 t = sp_type_rewrap (e. args[2 ], mi, true )
32983311 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
33003314 return RTEffects (Bottom, Any, EFFECTS_THROWS)
33013315 end
33023316 end
33033317 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
33053320 end
33063321 cconv = e. args[5 ]
33073322 if isa (cconv, QuoteNode) && (v = cconv. value; isa (v, Tuple{Symbol, UInt16}))
@@ -3367,6 +3382,10 @@ end
33673382
33683383function abstract_eval_globalref_type (g:: GlobalRef , src:: Union{CodeInfo, IRCode, IncrementalCompact} , retry_after_resolve:: Bool = true )
33693384 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 )
33703389 partition = lookup_binding_partition (min_world (worlds), g)
33713390 partition. max_world < max_world (worlds) && return Any
33723391 while is_some_imported (binding_kind (partition))
@@ -3380,7 +3399,7 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
33803399 # the binding unless necessary - doing so triggers an additional lookup, which though
33813400 # not super expensive is hot enough to show up in benchmarks.
33823401 force_binding_resolution! (g)
3383- return abstract_eval_globalref_type (g, src , false )
3402+ return abstract_eval_globalref_type (g, worlds , false )
33843403 end
33853404 # return Union{}
33863405 return Any
@@ -3391,6 +3410,11 @@ function abstract_eval_globalref_type(g::GlobalRef, src::Union{CodeInfo, IRCode,
33913410 return partition_restriction (partition)
33923411end
33933412
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+
33943418function abstract_eval_binding_partition! (interp:: AbstractInterpreter , g:: GlobalRef , sv:: AbsIntState )
33953419 force_binding_resolution! (g)
33963420 partition = lookup_binding_partition (get_inference_world (interp), g)
@@ -3821,7 +3845,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
38213845 elseif isa (stmt, GotoIfNot)
38223846 condx = stmt. cond
38233847 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
38253850 if condt === Bottom
38263851 ssavaluetypes[currpc] = Bottom
38273852 empty! (frame. pclimitations)
@@ -3908,7 +3933,11 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
39083933 @goto fallthrough
39093934 end
39103935 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
39123941 if update_bestguess! (interp, frame, currstate, rt)
39133942 update_cycle_worklists! (frame) do caller:: InferenceState , caller_pc:: Int
39143943 # 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
39213950 ssavaluetypes[currpc] = Any
39223951 add_curr_ssaflag! (frame, IR_FLAG_NOTHROW)
39233952 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
39253955 handler = gethandler (frame, currpc + 1 ):: TryCatchFrame
39263956 @assert handler. scopet != = nothing
39273957 if ! ⊑ (𝕃ᵢ, scopet, handler. scopet)
@@ -4023,13 +4053,13 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState, nextr
40234053 changes = StateUpdate (lhs:: SlotNumber , VarState (rt, false ))
40244054 end
40254055 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)
40324058 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)
40334063 end
40344064 if rt === Bottom
40354065 ssavaluetypes[currpc] = Bottom
0 commit comments