@@ -42,19 +42,50 @@ struct DisjunctionInfo {
42
42
// / If the score is nullopt it means that the disjunction is not optimizable.
43
43
std::optional<double > Score;
44
44
45
- // / Whether the decisions were based on speculative information
46
- // / i.e. literal argument candidates or initializer type inference.
47
- bool IsSpeculative = false ;
48
-
49
45
// / The highest scoring choices that could be favored when disjunction
50
46
// / is attempted.
51
47
llvm::TinyPtrVector<Constraint *> FavoredChoices;
52
48
49
+ // / Whether the decisions were based on speculative information
50
+ // / i.e. literal argument candidates or initializer type inference.
51
+ bool IsSpeculative;
52
+
53
53
DisjunctionInfo () = default ;
54
- DisjunctionInfo (double score, bool speculative = false ,
55
- ArrayRef<Constraint *> favoredChoices = {})
56
- : Score(score), IsSpeculative(speculative),
57
- FavoredChoices (favoredChoices) {}
54
+ DisjunctionInfo (std::optional<double > score,
55
+ ArrayRef<Constraint *> favoredChoices, bool speculative)
56
+ : Score(score), FavoredChoices(favoredChoices),
57
+ IsSpeculative (speculative) {}
58
+
59
+ static DisjunctionInfo none () { return {std::nullopt, {}, false }; }
60
+ };
61
+
62
+ class DisjunctionInfoBuilder {
63
+ std::optional<double > Score;
64
+ SmallVector<Constraint *, 2 > FavoredChoices;
65
+ bool IsSpeculative;
66
+
67
+ public:
68
+ DisjunctionInfoBuilder (std::optional<double > score)
69
+ : DisjunctionInfoBuilder(score, {}) {}
70
+
71
+ DisjunctionInfoBuilder (std::optional<double > score,
72
+ ArrayRef<Constraint *> favoredChoices)
73
+ : Score(score),
74
+ FavoredChoices (favoredChoices.begin(), favoredChoices.end()),
75
+ IsSpeculative(false ) {}
76
+
77
+ void setFavoredChoices (ArrayRef<Constraint *> choices) {
78
+ FavoredChoices.clear ();
79
+ FavoredChoices.append (choices.begin (), choices.end ());
80
+ }
81
+
82
+ void addFavoredChoice (Constraint *constraint) {
83
+ FavoredChoices.push_back (constraint);
84
+ }
85
+
86
+ void setSpeculative (bool value = true ) { IsSpeculative = value; }
87
+
88
+ DisjunctionInfo build () { return {Score, FavoredChoices, IsSpeculative}; }
58
89
};
59
90
60
91
static DeclContext *getDisjunctionDC (Constraint *disjunction) {
@@ -624,7 +655,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
624
655
isExpr<SubscriptExpr>(argument) ||
625
656
isExpr<DynamicSubscriptExpr>(argument) ||
626
657
isExpr<LiteralExpr>(argument) || isExpr<BinaryExpr>(argument)))
627
- return { /* score= */ 0 } ;
658
+ return DisjunctionInfo::none () ;
628
659
629
660
auto argumentType = cs.getType (argument)->getRValueType ();
630
661
@@ -633,7 +664,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
633
664
if (isa<BinaryExpr>(argument)) {
634
665
auto chainTy = inferTypeOfArithmeticOperatorChain (cs.DC , argument);
635
666
if (!chainTy)
636
- return { /* score= */ 0 } ;
667
+ return DisjunctionInfo::none () ;
637
668
638
669
argumentType = chainTy;
639
670
}
@@ -643,19 +674,19 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
643
674
if (auto *LE = dyn_cast<LiteralExpr>(argument)) {
644
675
auto *P = TypeChecker::getLiteralProtocol (cs.getASTContext (), LE);
645
676
if (!P)
646
- return { /* score= */ 0 } ;
677
+ return DisjunctionInfo::none () ;
647
678
648
679
auto defaultTy = TypeChecker::getDefaultType (P, cs.DC );
649
680
if (!defaultTy)
650
- return { /* score= */ 0 } ;
681
+ return DisjunctionInfo::none () ;
651
682
652
683
argumentType = defaultTy;
653
684
}
654
685
655
686
ASSERT (argumentType);
656
687
657
688
if (argumentType->hasTypeVariable () || argumentType->hasDependentMember ())
658
- return { /* score= */ 0 } ;
689
+ return DisjunctionInfo::none () ;
659
690
660
691
SmallVector<Constraint *, 2 > favoredChoices;
661
692
forEachDisjunctionChoice (
@@ -677,8 +708,9 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
677
708
favoredChoices.push_back (choice);
678
709
});
679
710
680
- return DisjunctionInfo (/* score=*/ favoredChoices.empty () ? 0 : 1 ,
681
- /* speculative=*/ false , favoredChoices);
711
+ return DisjunctionInfoBuilder (/* score=*/ favoredChoices.empty () ? 0 : 1 ,
712
+ favoredChoices)
713
+ .build ();
682
714
}
683
715
684
716
} // end anonymous namespace
@@ -703,11 +735,12 @@ static void determineBestChoicesInContext(
703
735
// initializers for CGFloat<->Double conversions and restrictions with
704
736
// multiple choices.
705
737
if (disjunction->countFavoredNestedConstraints () > 0 ) {
706
- DisjunctionInfo info (/* score=*/ 2.0 );
707
- llvm::copy_if (disjunction->getNestedConstraints (),
708
- std::back_inserter (info.FavoredChoices ),
709
- [](Constraint *choice) { return choice->isFavored (); });
710
- recordResult (disjunction, std::move (info));
738
+ DisjunctionInfoBuilder info (/* score=*/ 2.0 );
739
+ for (auto *choice : disjunction->getNestedConstraints ()) {
740
+ if (choice->isFavored ())
741
+ info.addFavoredChoice (choice);
742
+ }
743
+ recordResult (disjunction, info.build ());
711
744
continue ;
712
745
}
713
746
@@ -742,8 +775,9 @@ static void determineBestChoicesInContext(
742
775
return decl &&
743
776
!decl->getInterfaceType ()->is <AnyFunctionType>();
744
777
});
745
- recordResult (disjunction, {/* score=*/ 1.0 , /* speculative=*/ false ,
746
- favoredChoices});
778
+ recordResult (
779
+ disjunction,
780
+ DisjunctionInfoBuilder (/* score=*/ 1.0 , favoredChoices).build ());
747
781
continue ;
748
782
}
749
783
@@ -783,8 +817,9 @@ static void determineBestChoicesInContext(
783
817
});
784
818
785
819
if (!favoredChoices.empty ()) {
786
- recordResult (disjunction,
787
- {/* score=*/ 0.01 , /* speculative=*/ false , favoredChoices});
820
+ recordResult (
821
+ disjunction,
822
+ DisjunctionInfoBuilder (/* score=*/ 0.01 , favoredChoices).build ());
788
823
continue ;
789
824
}
790
825
}
@@ -1633,14 +1668,16 @@ static void determineBestChoicesInContext(
1633
1668
(!canUseContextualResultTypes ||
1634
1669
!anyNonSpeculativeResultTypes(resultTypes));
1635
1670
1636
- DisjunctionInfo info (/* score=*/ bestScore, isSpeculative);
1671
+ DisjunctionInfoBuilder info (/* score=*/ bestScore);
1672
+
1673
+ info.setSpeculative(isSpeculative);
1637
1674
1638
1675
for (const auto &choice : favoredChoices) {
1639
1676
if (choice.second == bestScore)
1640
- info.FavoredChoices . push_back (choice.first );
1677
+ info.addFavoredChoice (choice.first );
1641
1678
}
1642
1679
1643
- recordResult (disjunction, std::move( info));
1680
+ recordResult (disjunction, info.build( ));
1644
1681
}
1645
1682
1646
1683
if (cs.isDebugMode () && bestOverallScore > 0 ) {
@@ -1751,9 +1788,9 @@ ConstraintSystem::selectDisjunction() {
1751
1788
if (auto preference = isPreferable (*this , first, second))
1752
1789
return preference.value ();
1753
1790
1754
- auto &[firstScore, isFirstSpeculative, firstFavoredChoices ] =
1791
+ auto &[firstScore, firstFavoredChoices, isFirstSpeculative ] =
1755
1792
favorings[first];
1756
- auto &[secondScore, isSecondSpeculative, secondFavoredChoices ] =
1793
+ auto &[secondScore, secondFavoredChoices, isSecondSpeculative ] =
1757
1794
favorings[second];
1758
1795
1759
1796
bool isFirstOperator = isOperatorDisjunction (first);
0 commit comments