@@ -78,7 +78,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
78
78
push! (fullmatch, thisfullmatch)
79
79
end
80
80
end
81
- info = UnionSplitInfo (splitsigs, infos)
81
+ info = UnionSplitInfo (infos)
82
82
else
83
83
mt = ccall (:jl_method_table_for , Any, (Any,), atype)
84
84
if mt === nothing
@@ -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,34 @@ 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 (CallMeta[ CallMeta (Bottom, info)])
591
593
valtype = statetype = Bottom
592
594
ret = Any[]
595
+ calls = CallMeta[call]
596
+
593
597
# Try to unroll the iteration up to MAX_TUPLE_SPLAT, which covers any finite
594
598
# length iterators, or interesting prefix
595
599
while true
596
600
stateordonet_widened = widenconst (stateordonet)
597
601
if stateordonet_widened === Nothing
598
- return ret
602
+ return ret, AbstractIterationInfo (calls)
599
603
end
600
604
if Nothing <: stateordonet_widened || length (ret) >= InferenceParams (interp). MAX_TUPLE_SPLAT
601
605
break
@@ -607,12 +611,14 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
607
611
# If there's no new information in this statetype, don't bother continuing,
608
612
# the iterator won't be finite.
609
613
if nstatetype ⊑ statetype
610
- return Any[Bottom]
614
+ return Any[Bottom], nothing
611
615
end
612
616
valtype = getfield_tfunc (stateordonet, Const (1 ))
613
617
push! (ret, valtype)
614
618
statetype = nstatetype
615
- stateordonet = abstract_call_known (interp, iteratef, nothing , Any[Const (iteratef), itertype, statetype], vtypes, sv). rt
619
+ call = abstract_call_known (interp, iteratef, nothing , Any[Const (iteratef), itertype, statetype], vtypes, sv)
620
+ stateordonet = call. rt
621
+ push! (calls, call)
616
622
end
617
623
# From here on, we start asking for results on the widened types, rather than
618
624
# the precise (potentially const) state type
@@ -629,15 +635,15 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
629
635
if nounion. parameters[1 ] <: valtype && nounion. parameters[2 ] <: statetype
630
636
if typeintersect (stateordonet, Nothing) === Union{}
631
637
# Reached a fixpoint, but Nothing is not possible => iterator is infinite or failing
632
- return Any[Bottom]
638
+ return Any[Bottom], nothing
633
639
end
634
640
break
635
641
end
636
642
valtype = tmerge (valtype, nounion. parameters[1 ])
637
643
statetype = tmerge (statetype, nounion. parameters[2 ])
638
644
end
639
645
push! (ret, Vararg{valtype})
640
- return ret
646
+ return ret, nothing
641
647
end
642
648
643
649
# do apply(af, fargs...), where af is a function value
@@ -656,13 +662,15 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
656
662
nargs = length (aargtypes)
657
663
splitunions = 1 < countunionsplit (aargtypes) <= InferenceParams (interp). MAX_APPLY_UNION_ENUM
658
664
ctypes = Any[Any[aft]]
665
+ infos = [Union{Nothing, AbstractIterationInfo}[]]
659
666
for i = 1 : nargs
660
667
ctypes´ = []
668
+ infos′ = []
661
669
for ti in (splitunions ? uniontypes (aargtypes[i]) : Any[aargtypes[i]])
662
670
if ! isvarargtype (ti)
663
- cti = precise_container_type (interp, itft, ti, vtypes, sv)
671
+ cti, info = precise_container_type (interp, itft, ti, vtypes, sv)
664
672
else
665
- cti = precise_container_type (interp, itft, unwrapva (ti), vtypes, sv)
673
+ cti, info = precise_container_type (interp, itft, unwrapva (ti), vtypes, sv)
666
674
# We can't represent a repeating sequence of the same types,
667
675
# so tmerge everything together to get one type that represents
668
676
# everything.
@@ -678,19 +686,29 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
678
686
if _any (t -> t === Bottom, cti)
679
687
continue
680
688
end
681
- for ct in ctypes
689
+ for j = 1 : length (ctypes)
690
+ ct = ctypes[j]
682
691
if isvarargtype (ct[end ])
692
+ # This is vararg, we're not gonna be able to do any inling,
693
+ # drop the info
694
+ info = nothing
695
+
683
696
tail = tuple_tail_elem (unwrapva (ct[end ]), cti)
684
697
push! (ctypes´, push! (ct[1 : (end - 1 )], tail))
685
698
else
686
699
push! (ctypes´, append! (ct[:], cti))
687
700
end
701
+ push! (infos′, push! (copy (infos[j]), info))
688
702
end
689
703
end
690
704
ctypes = ctypes´
705
+ infos = infos′
691
706
end
692
- local info = nothing
693
- for ct in ctypes
707
+ retinfos = ApplyCallInfo[]
708
+ retinfo = UnionSplitApplyCallInfo (retinfos)
709
+ for i = 1 : length (ctypes)
710
+ ct = ctypes[i]
711
+ arginfo = infos[i]
694
712
lct = length (ct)
695
713
# truncate argument list at the first Vararg
696
714
for i = 1 : lct- 1
@@ -701,15 +719,17 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
701
719
end
702
720
end
703
721
call = abstract_call (interp, nothing , ct, vtypes, sv, max_methods)
704
- info = call. info
722
+ push! (retinfos, ApplyCallInfo ( call. info, arginfo))
705
723
res = tmerge (res, call. rt)
706
724
if res === Any
725
+ # No point carrying forward the info, we're not gonna inline it anyway
726
+ retinfo = nothing
707
727
break
708
728
end
709
729
end
710
730
# TODO : Add a special info type to capture all the iteration info.
711
731
# For now, only propagate info if we don't also union-split the iteration
712
- return CallMeta (res, length (ctypes) == 1 ? info : false )
732
+ return CallMeta (res, retinfo )
713
733
end
714
734
715
735
function is_method_pure (method:: Method , @nospecialize (sig), sparams:: SimpleVector )
@@ -779,7 +799,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U
779
799
end
780
800
rt = builtin_tfunction (interp, f, argtypes[2 : end ], sv)
781
801
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)
802
+ cti, _ = precise_container_type (interp, nothing , argtypes[2 ], vtypes, sv)
783
803
idx = argtypes[3 ]. val
784
804
if 1 <= idx <= length (cti)
785
805
rt = unwrapva (cti[idx])
0 commit comments