@@ -505,13 +505,13 @@ end
505
505
# returns an array of types
506
506
function precise_container_type (interp:: AbstractInterpreter , @nospecialize (itft), @nospecialize (typ), vtypes:: VarTable , sv:: InferenceState )
507
507
if isa (typ, PartialStruct) && typ. typ. name === Tuple. name
508
- return typ. fields
508
+ return typ. fields, nothing
509
509
end
510
510
511
511
if isa (typ, Const)
512
512
val = typ. val
513
513
if isa (val, SimpleVector) || isa (val, Tuple)
514
- return Any[ Const (val[i]) for i in 1 : length (val) ] # avoid making a tuple Generator here!
514
+ return Any[ Const (val[i]) for i in 1 : length (val) ], nothing # avoid making a tuple Generator here!
515
515
end
516
516
end
517
517
@@ -529,27 +529,27 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
529
529
if isa (tti, Union)
530
530
utis = uniontypes (tti)
531
531
if _any (t -> ! isa (t, DataType) || ! (t <: Tuple ) || ! isknownlength (t), utis)
532
- return Any[Vararg{Any}]
532
+ return Any[Vararg{Any}], nothing
533
533
end
534
534
result = Any[rewrap_unionall (p, tti0) for p in utis[1 ]. parameters]
535
535
for t in utis[2 : end ]
536
536
if length (t. parameters) != length (result)
537
- return Any[Vararg{Any}]
537
+ return Any[Vararg{Any}], nothing
538
538
end
539
539
for j in 1 : length (t. parameters)
540
540
result[j] = tmerge (result[j], rewrap_unionall (t. parameters[j], tti0))
541
541
end
542
542
end
543
- return result
543
+ return result, nothing
544
544
elseif tti0 <: Tuple
545
545
if isa (tti0, DataType)
546
546
if isvatuple (tti0) && length (tti0. parameters) == 1
547
- return Any[Vararg{unwrapva (tti0. parameters[1 ])}]
547
+ return Any[Vararg{unwrapva (tti0. parameters[1 ])}], nothing
548
548
else
549
- return Any[ p for p in tti0. parameters ]
549
+ return Any[ p for p in tti0. parameters ], nothing
550
550
end
551
551
elseif ! isa (tti, DataType)
552
- return Any[Vararg{Any}]
552
+ return Any[Vararg{Any}], nothing
553
553
else
554
554
len = length (tti. parameters)
555
555
last = tti. parameters[len]
@@ -558,12 +558,12 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
558
558
if va
559
559
elts[len] = Vararg{elts[len]}
560
560
end
561
- return elts
561
+ return elts, nothing
562
562
end
563
563
elseif tti0 === SimpleVector || tti0 === Any
564
- return Any[Vararg{Any}]
564
+ return Any[Vararg{Any}], nothing
565
565
elseif tti0 <: Array
566
- return Any[Vararg{eltype (tti0)}]
566
+ return Any[Vararg{eltype (tti0)}], nothing
567
567
else
568
568
return abstract_iteration (interp, itft, typ, vtypes, sv)
569
569
end
@@ -572,30 +572,35 @@ end
572
572
# simulate iteration protocol on container type up to fixpoint
573
573
function abstract_iteration (interp:: AbstractInterpreter , @nospecialize (itft), @nospecialize (itertype), vtypes:: VarTable , sv:: InferenceState )
574
574
if ! isdefined (Main, :Base ) || ! isdefined (Main. Base, :iterate ) || ! isconst (Main. Base, :iterate )
575
- return Any[Vararg{Any}]
575
+ return Any[Vararg{Any}], nothing
576
576
end
577
577
if itft === nothing
578
578
iteratef = getfield (Main. Base, :iterate )
579
579
itft = Const (iteratef)
580
580
elseif isa (itft, Const)
581
581
iteratef = itft. val
582
582
else
583
- return Any[Vararg{Any}]
583
+ return Any[Vararg{Any}], nothing
584
584
end
585
585
@assert ! isvarargtype (itertype)
586
- stateordonet = abstract_call_known (interp, iteratef, nothing , Any[itft, itertype], vtypes, sv). rt
586
+ call = abstract_call_known (interp, iteratef, nothing , Any[itft, itertype], vtypes, sv)
587
+ stateordonet = call. rt
588
+ info = call. info
587
589
# Return Bottom if this is not an iterator.
588
590
# WARNING: Changes to the iteration protocol must be reflected here,
589
591
# this is not just an optimization.
590
- stateordonet === Bottom && return Any[Bottom]
592
+ stateordonet === Bottom && return Any[Bottom], AbstractIterationInfo (Any[Bottom], Any[info])
591
593
valtype = statetype = Bottom
592
594
ret = Any[]
595
+ states = Any[stateordonet]
596
+ infos = Any[info]
597
+
593
598
# Try to unroll the iteration up to MAX_TUPLE_SPLAT, which covers any finite
594
599
# length iterators, or interesting prefix
595
600
while true
596
601
stateordonet_widened = widenconst (stateordonet)
597
602
if stateordonet_widened === Nothing
598
- return ret
603
+ return ret, AbstractIterationInfo (states, infos)
599
604
end
600
605
if Nothing <: stateordonet_widened || length (ret) >= InferenceParams (interp). MAX_TUPLE_SPLAT
601
606
break
@@ -607,12 +612,15 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
607
612
# If there's no new information in this statetype, don't bother continuing,
608
613
# the iterator won't be finite.
609
614
if nstatetype ⊑ statetype
610
- return Any[Bottom]
615
+ return Any[Bottom], nothing
611
616
end
612
617
valtype = getfield_tfunc (stateordonet, Const (1 ))
613
618
push! (ret, valtype)
614
619
statetype = nstatetype
615
- stateordonet = abstract_call_known (interp, iteratef, nothing , Any[Const (iteratef), itertype, statetype], vtypes, sv). rt
620
+ call = abstract_call_known (interp, iteratef, nothing , Any[Const (iteratef), itertype, statetype], vtypes, sv)
621
+ stateordonet = call. rt
622
+ push! (states, stateordonet)
623
+ push! (infos, call. info)
616
624
end
617
625
# From here on, we start asking for results on the widened types, rather than
618
626
# the precise (potentially const) state type
@@ -629,15 +637,15 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
629
637
if nounion. parameters[1 ] <: valtype && nounion. parameters[2 ] <: statetype
630
638
if typeintersect (stateordonet, Nothing) === Union{}
631
639
# Reached a fixpoint, but Nothing is not possible => iterator is infinite or failing
632
- return Any[Bottom]
640
+ return Any[Bottom], nothing
633
641
end
634
642
break
635
643
end
636
644
valtype = tmerge (valtype, nounion. parameters[1 ])
637
645
statetype = tmerge (statetype, nounion. parameters[2 ])
638
646
end
639
647
push! (ret, Vararg{valtype})
640
- return ret
648
+ return ret, nothing
641
649
end
642
650
643
651
# do apply(af, fargs...), where af is a function value
@@ -656,13 +664,15 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
656
664
nargs = length (aargtypes)
657
665
splitunions = 1 < countunionsplit (aargtypes) <= InferenceParams (interp). MAX_APPLY_UNION_ENUM
658
666
ctypes = Any[Any[aft]]
667
+ infos = [Union{Nothing, AbstractIterationInfo}[]]
659
668
for i = 1 : nargs
660
669
ctypes´ = []
670
+ infos′ = []
661
671
for ti in (splitunions ? uniontypes (aargtypes[i]) : Any[aargtypes[i]])
662
672
if ! isvarargtype (ti)
663
- cti = precise_container_type (interp, itft, ti, vtypes, sv)
673
+ cti, info = precise_container_type (interp, itft, ti, vtypes, sv)
664
674
else
665
- cti = precise_container_type (interp, itft, unwrapva (ti), vtypes, sv)
675
+ cti, info = precise_container_type (interp, itft, unwrapva (ti), vtypes, sv)
666
676
# We can't represent a repeating sequence of the same types,
667
677
# so tmerge everything together to get one type that represents
668
678
# everything.
@@ -678,19 +688,29 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
678
688
if _any (t -> t === Bottom, cti)
679
689
continue
680
690
end
681
- for ct in ctypes
691
+ for j = 1 : length (ctypes)
692
+ ct = ctypes[j]
682
693
if isvarargtype (ct[end ])
694
+ # This is vararg, we're not gonna be able to do any inling,
695
+ # drop the info
696
+ info = nothing
697
+
683
698
tail = tuple_tail_elem (unwrapva (ct[end ]), cti)
684
699
push! (ctypes´, push! (ct[1 : (end - 1 )], tail))
685
700
else
686
701
push! (ctypes´, append! (ct[:], cti))
687
702
end
703
+ push! (infos′, push! (copy (infos[j]), info))
688
704
end
689
705
end
690
706
ctypes = ctypes´
707
+ infos = infos′
691
708
end
692
- local info = nothing
693
- for ct in ctypes
709
+ retinfos = ApplyCallInfo[]
710
+ retinfo = UnionSplitApplyCallInfo (retinfos)
711
+ for i = 1 : length (ctypes)
712
+ ct = ctypes[i]
713
+ arginfo = infos[i]
694
714
lct = length (ct)
695
715
# truncate argument list at the first Vararg
696
716
for i = 1 : lct- 1
@@ -701,15 +721,17 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
701
721
end
702
722
end
703
723
call = abstract_call (interp, nothing , ct, vtypes, sv, max_methods)
704
- info = call. info
724
+ push! (retinfos, ApplyCallInfo ( call. info, arginfo))
705
725
res = tmerge (res, call. rt)
706
726
if res === Any
727
+ # No point carrying forward the info, we're not gonna inline it anyway
728
+ retinfo = nothing
707
729
break
708
730
end
709
731
end
710
732
# TODO : Add a special info type to capture all the iteration info.
711
733
# For now, only propagate info if we don't also union-split the iteration
712
- return CallMeta (res, length (ctypes) == 1 ? info : false )
734
+ return CallMeta (res, retinfo )
713
735
end
714
736
715
737
function is_method_pure (method:: Method , @nospecialize (sig), sparams:: SimpleVector )
@@ -779,7 +801,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U
779
801
end
780
802
rt = builtin_tfunction (interp, f, argtypes[2 : end ], sv)
781
803
if f === getfield && isa (fargs, Vector{Any}) && la == 3 && isa (argtypes[3 ], Const) && isa (argtypes[3 ]. val, Int) && argtypes[2 ] ⊑ Tuple
782
- cti = precise_container_type (interp, nothing , argtypes[2 ], vtypes, sv)
804
+ cti, _ = precise_container_type (interp, nothing , argtypes[2 ], vtypes, sv)
783
805
idx = argtypes[3 ]. val
784
806
if 1 <= idx <= length (cti)
785
807
rt = unwrapva (cti[idx])
0 commit comments