@@ -41,13 +41,20 @@ struct DisjunctionInfo {
41
41
// / The score of the disjunction is the highest score from its choices.
42
42
// / If the score is nullopt it means that the disjunction is not optimizable.
43
43
std::optional<double > Score;
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
+
44
49
// / The highest scoring choices that could be favored when disjunction
45
50
// / is attempted.
46
51
llvm::TinyPtrVector<Constraint *> FavoredChoices;
47
52
48
53
DisjunctionInfo () = default ;
49
- DisjunctionInfo (double score, ArrayRef<Constraint *> favoredChoices = {})
50
- : Score(score), FavoredChoices(favoredChoices) {}
54
+ DisjunctionInfo (double score, bool speculative = false ,
55
+ ArrayRef<Constraint *> favoredChoices = {})
56
+ : Score(score), IsSpeculative(speculative),
57
+ FavoredChoices (favoredChoices) {}
51
58
};
52
59
53
60
static DeclContext *getDisjunctionDC (Constraint *disjunction) {
@@ -656,7 +663,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
656
663
});
657
664
658
665
return DisjunctionInfo (/* score=*/ favoredChoices.empty () ? 0 : 1 ,
659
- favoredChoices);
666
+ /* speculative= */ false , favoredChoices);
660
667
}
661
668
662
669
} // end anonymous namespace
@@ -720,7 +727,8 @@ static void determineBestChoicesInContext(
720
727
return decl &&
721
728
!decl->getInterfaceType ()->is <AnyFunctionType>();
722
729
});
723
- recordResult (disjunction, {/* score=*/ 1.0 , favoredChoices});
730
+ recordResult (disjunction, {/* score=*/ 1.0 , /* speculative=*/ false ,
731
+ favoredChoices});
724
732
continue ;
725
733
}
726
734
@@ -760,7 +768,8 @@ static void determineBestChoicesInContext(
760
768
});
761
769
762
770
if (!favoredChoices.empty ()) {
763
- recordResult (disjunction, {/* score=*/ 0.01 , favoredChoices});
771
+ recordResult (disjunction,
772
+ {/* score=*/ 0.01 , /* speculative=*/ false , favoredChoices});
764
773
continue ;
765
774
}
766
775
}
@@ -1577,41 +1586,24 @@ static void determineBestChoicesInContext(
1577
1586
1578
1587
bestOverallScore = std::max(bestOverallScore, bestScore);
1579
1588
1580
- DisjunctionInfo info (/* score=*/ bestScore);
1589
+ // Determine if the score and favoring decisions here are
1590
+ // based only on "speculative" sources i.e. inference from
1591
+ // literals.
1592
+ //
1593
+ // This information is going to be used by the disjunction
1594
+ // selection algorithm to prevent over-eager selection of
1595
+ // the operators over unsupported non-operator declarations.
1596
+ bool isSpeculative = onlySpeculativeArgumentCandidates &&
1597
+ (!canUseContextualResultTypes ||
1598
+ !anyNonSpeculativeResultTypes(resultTypes));
1599
+
1600
+ DisjunctionInfo info (/* score=*/ bestScore, isSpeculative);
1581
1601
1582
1602
for (const auto &choice : favoredChoices) {
1583
1603
if (choice.second == bestScore)
1584
1604
info.FavoredChoices .push_back (choice.first );
1585
1605
}
1586
1606
1587
- // Reset operator disjunction score but keep favoring
1588
- // choices only available candidates where speculative
1589
- // with no contextual information available, standard
1590
- // comparison operators are a special cases because
1591
- // their return type is fixed to `Bool` unlike that of
1592
- // bitwise, arithmetic, and other operators.
1593
- //
1594
- // This helps to prevent over-eager selection of the
1595
- // operators over unsupported non-operator declarations.
1596
- if (isOperator && onlySpeculativeArgumentCandidates &&
1597
- (!canUseContextualResultTypes ||
1598
- !anyNonSpeculativeResultTypes(resultTypes))) {
1599
- if (cs.isDebugMode ()) {
1600
- PrintOptions PO;
1601
- PO.PrintTypesForDebugging = true ;
1602
-
1603
- llvm::errs ().indent (cs.solverState ->getCurrentIndent ())
1604
- << " <<< Disjunction "
1605
- << disjunction->getNestedConstraints ()[0 ]
1606
- ->getFirstType ()
1607
- ->getString (PO)
1608
- << " score " << bestScore
1609
- << " was reset due to having only speculative candidates\n " ;
1610
- }
1611
-
1612
- info.Score = 0 ;
1613
- }
1614
-
1615
1607
recordResult (disjunction, std::move(info));
1616
1608
}
1617
1609
@@ -1723,8 +1715,25 @@ ConstraintSystem::selectDisjunction() {
1723
1715
if (auto preference = isPreferable (*this , first, second))
1724
1716
return preference.value ();
1725
1717
1726
- auto &[firstScore, firstFavoredChoices] = favorings[first];
1727
- auto &[secondScore, secondFavoredChoices] = favorings[second];
1718
+ auto &[firstScore, isFirstSpeculative, firstFavoredChoices] =
1719
+ favorings[first];
1720
+ auto &[secondScore, isSecondSpeculative, secondFavoredChoices] =
1721
+ favorings[second];
1722
+
1723
+ bool isFirstOperator = isOperatorDisjunction (first);
1724
+ bool isSecondOperator = isOperatorDisjunction (second);
1725
+
1726
+ // Not all of the non-operator disjunctions are supported by the
1727
+ // ranking algorithm, so to prevent eager selection of operators
1728
+ // when anything concrete is known about them, let's reset the score
1729
+ // and compare purely based on number of choices.
1730
+ if (isFirstOperator != isSecondOperator) {
1731
+ if (isFirstOperator && isFirstSpeculative)
1732
+ firstScore = 0 ;
1733
+
1734
+ if (isSecondOperator && isSecondSpeculative)
1735
+ secondScore = 0 ;
1736
+ }
1728
1737
1729
1738
// Rank based on scores only if both disjunctions are supported.
1730
1739
if (firstScore && secondScore) {
0 commit comments