@@ -42,19 +42,50 @@ struct DisjunctionInfo {
4242 // / If the score is nullopt it means that the disjunction is not optimizable.
4343 std::optional<double > Score;
4444
45- // / Whether the decisions were based on speculative information
46- // / i.e. literal argument candidates or initializer type inference.
47- bool IsSpeculative = false ;
48-
4945 // / The highest scoring choices that could be favored when disjunction
5046 // / is attempted.
5147 llvm::TinyPtrVector<Constraint *> FavoredChoices;
5248
49+ // / Whether the decisions were based on speculative information
50+ // / i.e. literal argument candidates or initializer type inference.
51+ bool IsSpeculative;
52+
5353 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}; }
5889};
5990
6091static DeclContext *getDisjunctionDC (Constraint *disjunction) {
@@ -624,7 +655,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
624655 isExpr<SubscriptExpr>(argument) ||
625656 isExpr<DynamicSubscriptExpr>(argument) ||
626657 isExpr<LiteralExpr>(argument) || isExpr<BinaryExpr>(argument)))
627- return { /* score= */ 0 } ;
658+ return DisjunctionInfo::none () ;
628659
629660 auto argumentType = cs.getType (argument)->getRValueType ();
630661
@@ -633,7 +664,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
633664 if (isa<BinaryExpr>(argument)) {
634665 auto chainTy = inferTypeOfArithmeticOperatorChain (cs.DC , argument);
635666 if (!chainTy)
636- return { /* score= */ 0 } ;
667+ return DisjunctionInfo::none () ;
637668
638669 argumentType = chainTy;
639670 }
@@ -643,19 +674,19 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
643674 if (auto *LE = dyn_cast<LiteralExpr>(argument)) {
644675 auto *P = TypeChecker::getLiteralProtocol (cs.getASTContext (), LE);
645676 if (!P)
646- return { /* score= */ 0 } ;
677+ return DisjunctionInfo::none () ;
647678
648679 auto defaultTy = TypeChecker::getDefaultType (P, cs.DC );
649680 if (!defaultTy)
650- return { /* score= */ 0 } ;
681+ return DisjunctionInfo::none () ;
651682
652683 argumentType = defaultTy;
653684 }
654685
655686 ASSERT (argumentType);
656687
657688 if (argumentType->hasTypeVariable () || argumentType->hasDependentMember ())
658- return { /* score= */ 0 } ;
689+ return DisjunctionInfo::none () ;
659690
660691 SmallVector<Constraint *, 2 > favoredChoices;
661692 forEachDisjunctionChoice (
@@ -677,8 +708,9 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
677708 favoredChoices.push_back (choice);
678709 });
679710
680- return DisjunctionInfo (/* score=*/ favoredChoices.empty () ? 0 : 1 ,
681- /* speculative=*/ false , favoredChoices);
711+ return DisjunctionInfoBuilder (/* score=*/ favoredChoices.empty () ? 0 : 1 ,
712+ favoredChoices)
713+ .build ();
682714}
683715
684716} // end anonymous namespace
@@ -703,11 +735,12 @@ static void determineBestChoicesInContext(
703735 // initializers for CGFloat<->Double conversions and restrictions with
704736 // multiple choices.
705737 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 ());
711744 continue ;
712745 }
713746
@@ -742,8 +775,9 @@ static void determineBestChoicesInContext(
742775 return decl &&
743776 !decl->getInterfaceType ()->is <AnyFunctionType>();
744777 });
745- recordResult (disjunction, {/* score=*/ 1.0 , /* speculative=*/ false ,
746- favoredChoices});
778+ recordResult (
779+ disjunction,
780+ DisjunctionInfoBuilder (/* score=*/ 1.0 , favoredChoices).build ());
747781 continue ;
748782 }
749783
@@ -783,8 +817,9 @@ static void determineBestChoicesInContext(
783817 });
784818
785819 if (!favoredChoices.empty ()) {
786- recordResult (disjunction,
787- {/* score=*/ 0.01 , /* speculative=*/ false , favoredChoices});
820+ recordResult (
821+ disjunction,
822+ DisjunctionInfoBuilder (/* score=*/ 0.01 , favoredChoices).build ());
788823 continue ;
789824 }
790825 }
@@ -1633,14 +1668,16 @@ static void determineBestChoicesInContext(
16331668 (!canUseContextualResultTypes ||
16341669 !anyNonSpeculativeResultTypes(resultTypes));
16351670
1636- DisjunctionInfo info (/* score=*/ bestScore, isSpeculative);
1671+ DisjunctionInfoBuilder info (/* score=*/ bestScore);
1672+
1673+ info.setSpeculative(isSpeculative);
16371674
16381675 for (const auto &choice : favoredChoices) {
16391676 if (choice.second == bestScore)
1640- info.FavoredChoices . push_back (choice.first );
1677+ info.addFavoredChoice (choice.first );
16411678 }
16421679
1643- recordResult (disjunction, std::move( info));
1680+ recordResult (disjunction, info.build( ));
16441681 }
16451682
16461683 if (cs.isDebugMode () && bestOverallScore > 0 ) {
@@ -1751,9 +1788,9 @@ ConstraintSystem::selectDisjunction() {
17511788 if (auto preference = isPreferable (*this , first, second))
17521789 return preference.value ();
17531790
1754- auto &[firstScore, isFirstSpeculative, firstFavoredChoices ] =
1791+ auto &[firstScore, firstFavoredChoices, isFirstSpeculative ] =
17551792 favorings[first];
1756- auto &[secondScore, isSecondSpeculative, secondFavoredChoices ] =
1793+ auto &[secondScore, secondFavoredChoices, isSecondSpeculative ] =
17571794 favorings[second];
17581795
17591796 bool isFirstOperator = isOperatorDisjunction (first);
0 commit comments