@@ -434,7 +434,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp
434434 # Under direct self-recursion, permit much greater use of reducers.
435435 # here we assume that complexity(specTypes) :>= complexity(sig)
436436 comparison = sv. linfo. specTypes
437- l_comparison = length (unwrap_unionall (comparison). parameters)
437+ l_comparison = length (unwrap_unionall (comparison). parameters):: Int
438438 spec_len = max (spec_len, l_comparison)
439439 else
440440 comparison = method. sig
589589
590590# simulate iteration protocol on container type up to fixpoint
591591function abstract_iteration (interp:: AbstractInterpreter , @nospecialize (itft), @nospecialize (itertype), sv:: InferenceState )
592- if ! isdefined (Main, :Base ) || ! isdefined (Main. Base, :iterate ) || ! isconst (Main. Base, :iterate )
593- return Any[Vararg{Any}], nothing
594- end
595- if itft === nothing
596- iteratef = getfield (Main. Base, :iterate )
597- itft = Const (iteratef)
598- elseif isa (itft, Const)
592+ if isa (itft, Const)
599593 iteratef = itft. val
600594 else
601595 return Any[Vararg{Any}], nothing
@@ -607,6 +601,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
607601 # Return Bottom if this is not an iterator.
608602 # WARNING: Changes to the iteration protocol must be reflected here,
609603 # this is not just an optimization.
604+ # TODO : this doesn't realize that Array, SimpleVector, Tuple, and NamedTuple do not use the iterate protocol
610605 stateordonet === Bottom && return Any[Bottom], AbstractIterationInfo (CallMeta[CallMeta (Bottom, info)])
611606 valtype = statetype = Bottom
612607 ret = Any[]
@@ -670,7 +665,7 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
670665 aftw = widenconst (aft)
671666 if ! isa (aft, Const) && (! isType (aftw) || has_free_typevars (aftw))
672667 if ! isconcretetype (aftw) || (aftw <: Builtin )
673- add_remark! (interp, sv, " Core._apply called on a function of a non-concrete type" )
668+ add_remark! (interp, sv, " Core._apply_iterate called on a function of a non-concrete type" )
674669 # bail now, since it seems unlikely that abstract_call will be able to do any better after splitting
675670 # this also ensures we don't call abstract_call_gf_by_type below on an IntrinsicFunction or Builtin
676671 return CallMeta (Any, false )
@@ -679,16 +674,20 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
679674 res = Union{}
680675 nargs = length (aargtypes)
681676 splitunions = 1 < unionsplitcost (aargtypes) <= InferenceParams (interp). MAX_APPLY_UNION_ENUM
682- ctypes = Any [Any[aft]]
677+ ctypes = [Any[aft]]
683678 infos = [Union{Nothing, AbstractIterationInfo}[]]
684679 for i = 1 : nargs
685- ctypes´ = []
686- infos′ = []
680+ ctypes´ = Vector{Any} []
681+ infos′ = Vector{Union{Nothing, AbstractIterationInfo}} []
687682 for ti in (splitunions ? uniontypes (aargtypes[i]) : Any[aargtypes[i]])
688683 if ! isvarargtype (ti)
689- cti, info = precise_container_type (interp, itft, ti, sv)
684+ cti_info = precise_container_type (interp, itft, ti, sv)
685+ cti = cti_info[1 ]:: Vector{Any}
686+ info = cti_info[2 ]:: Union{Nothing,AbstractIterationInfo}
690687 else
691- cti, info = precise_container_type (interp, itft, unwrapva (ti), sv)
688+ cti_info = precise_container_type (interp, itft, unwrapva (ti), sv)
689+ cti = cti_info[1 ]:: Vector{Any}
690+ info = cti_info[2 ]:: Union{Nothing,AbstractIterationInfo}
692691 # We can't represent a repeating sequence of the same types,
693692 # so tmerge everything together to get one type that represents
694693 # everything.
@@ -705,7 +704,7 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
705704 continue
706705 end
707706 for j = 1 : length (ctypes)
708- ct = ctypes[j]
707+ ct = ctypes[j]:: Vector{Any}
709708 if isvarargtype (ct[end ])
710709 # This is vararg, we're not gonna be able to do any inling,
711710 # drop the info
@@ -826,7 +825,8 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U
826825 end
827826 rt = builtin_tfunction (interp, f, argtypes[2 : end ], sv)
828827 if f === getfield && isa (fargs, Vector{Any}) && la == 3 && isa (argtypes[3 ], Const) && isa (argtypes[3 ]. val, Int) && argtypes[2 ] ⊑ Tuple
829- cti, _ = precise_container_type (interp, nothing , argtypes[2 ], sv)
828+ # TODO : why doesn't this use the getfield_tfunc?
829+ cti, _ = precise_container_type (interp, iterate, argtypes[2 ], sv)
830830 idx = argtypes[3 ]. val:: Int
831831 if 1 <= idx <= length (cti)
832832 rt = unwrapva (cti[idx])
@@ -945,11 +945,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
945945 la = length (argtypes)
946946
947947 if isa (f, Builtin)
948- if f === _apply
949- ft = argtype_by_index (argtypes, 2 )
950- ft === Bottom && return CallMeta (Bottom, false )
951- return abstract_apply (interp, nothing , ft, argtype_tail (argtypes, 3 ), sv, max_methods)
952- elseif f === _apply_iterate
948+ if f === _apply_iterate
953949 itft = argtype_by_index (argtypes, 2 )
954950 ft = argtype_by_index (argtypes, 3 )
955951 (itft === Bottom || ft === Bottom) && return CallMeta (Bottom, false )
@@ -1304,6 +1300,28 @@ function abstract_eval_ssavalue(s::SSAValue, src::CodeInfo)
13041300 return typ
13051301end
13061302
1303+ function widenreturn (@nospecialize rt)
1304+ # only propagate information we know we can store
1305+ # and is valid and good inter-procedurally
1306+ rt = widenconditional (rt)
1307+ isa (rt, Const) && return rt
1308+ isa (rt, Type) && return rt
1309+ if isa (rt, PartialStruct)
1310+ fields = copy (rt. fields)
1311+ haveconst = false
1312+ for i in 1 : length (fields)
1313+ a = widenreturn (fields[i])
1314+ if ! haveconst && has_const_info (a)
1315+ # TODO : consider adding && const_prop_profitable(a) here?
1316+ haveconst = true
1317+ end
1318+ fields[i] = a
1319+ end
1320+ haveconst && return PartialStruct (rt. typ, fields)
1321+ end
1322+ return widenconst (rt)
1323+ end
1324+
13071325# make as much progress on `frame` as possible (without handling cycles)
13081326function typeinf_local (interp:: AbstractInterpreter , frame:: InferenceState )
13091327 @assert ! frame. inferred
@@ -1326,6 +1344,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
13261344 frame. currpc = pc
13271345 frame. cur_hand = frame. handler_at[pc]
13281346 frame. stmt_edges[pc] === nothing || empty! (frame. stmt_edges[pc])
1347+ frame. stmt_info[pc] = nothing
13291348 stmt = frame. src. code[pc]
13301349 changes = s[pc]:: VarTable
13311350 t = nothing
@@ -1338,7 +1357,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
13381357 elseif isa (stmt, GotoNode)
13391358 pc´ = (stmt:: GotoNode ). label
13401359 elseif isa (stmt, GotoIfNot)
1341- condt = abstract_eval_value (interp, stmt. cond, s[pc] , frame)
1360+ condt = abstract_eval_value (interp, stmt. cond, changes , frame)
13421361 if condt === Bottom
13431362 empty! (frame. pclimitations)
13441363 break
@@ -1369,7 +1388,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
13691388 end
13701389 end
13711390 newstate_else = stupdate! (s[l], changes_else)
1372- if newstate_else != = false
1391+ if newstate_else != = nothing
13731392 # add else branch to active IP list
13741393 if l < frame. pc´´
13751394 frame. pc´´ = l
@@ -1380,12 +1399,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
13801399 end
13811400 elseif isa (stmt, ReturnNode)
13821401 pc´ = n + 1
1383- rt = widenconditional (abstract_eval_value (interp, stmt. val, s[pc], frame))
1384- if ! isa (rt, Const) && ! isa (rt, Type) && ! isa (rt, PartialStruct)
1385- # only propagate information we know we can store
1386- # and is valid inter-procedurally
1387- rt = widenconst (rt)
1388- end
1402+ rt = widenreturn (abstract_eval_value (interp, stmt. val, changes, frame))
13891403 # copy limitations to return value
13901404 if ! isempty (frame. pclimitations)
13911405 union! (frame. limitations, frame. pclimitations)
@@ -1414,9 +1428,8 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
14141428 frame. cur_hand = Pair {Any,Any} (l, frame. cur_hand)
14151429 # propagate type info to exception handler
14161430 old = s[l]
1417- new = s[pc]:: Array{Any,1}
1418- newstate_catch = stupdate! (old, new)
1419- if newstate_catch != = false
1431+ newstate_catch = stupdate! (old, changes)
1432+ if newstate_catch != = nothing
14201433 if l < frame. pc´´
14211434 frame. pc´´ = l
14221435 end
@@ -1483,12 +1496,12 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
14831496 # (such as a terminator for a loop, if-else, or try block),
14841497 # consider whether we should jump to an older backedge first,
14851498 # to try to traverse the statements in approximate dominator order
1486- if newstate != = false
1499+ if newstate != = nothing
14871500 s[pc´] = newstate
14881501 end
14891502 push! (W, pc´)
14901503 pc = frame. pc´´
1491- elseif newstate != = false
1504+ elseif newstate != = nothing
14921505 s[pc´] = newstate
14931506 pc = pc´
14941507 elseif pc´ in W
0 commit comments