@@ -1706,6 +1706,44 @@ void ConstraintSystem::collectDisjunctions(
1706
1706
}
1707
1707
}
1708
1708
1709
+ // / \brief Check if the given disjunction choice should be attempted by solver.
1710
+ static bool shouldSkipDisjunctionChoice (ConstraintSystem &cs,
1711
+ DisjunctionChoice &choice,
1712
+ Optional<Score> &bestNonGenericScore) {
1713
+ if (choice->isDisabled ()) {
1714
+ auto &TC = cs.TC ;
1715
+ if (TC.getLangOpts ().DebugConstraintSolver ) {
1716
+ auto &log = cs.getASTContext ().TypeCheckerDebug ->getStream ();
1717
+ log.indent (cs.solverState ->depth )
1718
+ << " (skipping " ;
1719
+ choice->print (log, &TC.Context .SourceMgr );
1720
+ log << ' \n ' ;
1721
+ }
1722
+
1723
+ return true ;
1724
+ }
1725
+
1726
+ // Don't attempt to solve for generic operators if we already have
1727
+ // a non-generic solution.
1728
+
1729
+ // FIXME: Less-horrible but still horrible hack to attempt to
1730
+ // speed things up. Skip the generic operators if we
1731
+ // already have a solution involving non-generic operators,
1732
+ // but continue looking for a better non-generic operator
1733
+ // solution.
1734
+ if (bestNonGenericScore && choice.isGenericOperatorOrUnavailable ()) {
1735
+ auto &score = bestNonGenericScore->Data ;
1736
+ // Let's skip generic overload choices only in case if
1737
+ // non-generic score indicates that there were no forced
1738
+ // unwrappings of optional(s) and no unavailable overload
1739
+ // choices present in the solution.
1740
+ if (score[SK_ForceUnchecked] == 0 && score[SK_Unavailable] == 0 )
1741
+ return true ;
1742
+ }
1743
+
1744
+ return false ;
1745
+ }
1746
+
1709
1747
bool ConstraintSystem::solveSimplified (
1710
1748
SmallVectorImpl<Solution> &solutions,
1711
1749
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -1789,47 +1827,29 @@ bool ConstraintSystem::solveSimplified(
1789
1827
auto afterDisjunction = InactiveConstraints.erase (disjunction);
1790
1828
CG.removeConstraint (disjunction);
1791
1829
1792
- Score initialScore = CurrentScore;
1793
- Optional<DisjunctionChoice> lastSolvedChoice;
1830
+ Optional<std::pair<DisjunctionChoice, Score>> lastSolvedChoice;
1794
1831
Optional<Score> bestNonGenericScore;
1795
1832
1796
1833
++solverState->NumDisjunctions ;
1797
1834
auto constraints = disjunction->getNestedConstraints ();
1798
1835
// Try each of the constraints within the disjunction.
1799
1836
for (auto index : indices (constraints)) {
1800
1837
auto currentChoice = DisjunctionChoice (this , constraints[index]);
1801
- if (currentChoice.isDisabled ()) {
1802
- if (TC.getLangOpts ().DebugConstraintSolver ) {
1803
- auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
1804
- log.indent (solverState->depth )
1805
- << " (skipping " ;
1806
- currentChoice->print (log, &TC.Context .SourceMgr );
1807
- log << ' \n ' ;
1808
- }
1838
+ if (shouldSkipDisjunctionChoice (*this , currentChoice, bestNonGenericScore))
1809
1839
continue ;
1810
- }
1811
-
1812
- // Don't attempt to solve for generic operators if we already have
1813
- // a non-generic solution.
1814
-
1815
- // FIXME: Less-horrible but still horrible hack to attempt to
1816
- // speed things up. Skip the generic operators if we
1817
- // already have a solution involving non-generic operators,
1818
- // but continue looking for a better non-generic operator
1819
- // solution.
1820
- if (bestNonGenericScore && currentChoice.isGenericOperatorOrUnavailable ()) {
1821
- // If non-generic solution increased the score by applying any
1822
- // fixes or restrictions to the solution, let's not skip generic
1823
- // overloads because they could produce a better solution.
1824
- if (bestNonGenericScore <= initialScore)
1825
- continue ;
1826
- }
1827
1840
1828
1841
// We already have a solution; check whether we should
1829
1842
// short-circuit the disjunction.
1830
1843
if (lastSolvedChoice) {
1831
- auto *lastChoice = lastSolvedChoice->getConstraint ();
1832
- if (shortCircuitDisjunctionAt (¤tChoice, lastChoice,
1844
+ auto *lastChoice = lastSolvedChoice->first .getConstraint ();
1845
+ auto &score = lastSolvedChoice->second ;
1846
+ bool hasUnavailableOverloads = score.Data [SK_Unavailable] > 0 ;
1847
+
1848
+ // Attempt to short-circuit disjunction only if
1849
+ // score indicates that there are no unavailable
1850
+ // overload choices present in the solution.
1851
+ if (!hasUnavailableOverloads &&
1852
+ shortCircuitDisjunctionAt (¤tChoice, lastChoice,
1833
1853
getASTContext ()))
1834
1854
break ;
1835
1855
}
@@ -1864,7 +1884,7 @@ bool ConstraintSystem::solveSimplified(
1864
1884
bestNonGenericScore = score;
1865
1885
}
1866
1886
1867
- lastSolvedChoice = currentChoice;
1887
+ lastSolvedChoice = { currentChoice, *score} ;
1868
1888
1869
1889
// If we see a tuple-to-tuple conversion that succeeded, we're done.
1870
1890
// FIXME: This should be more general.
@@ -1894,8 +1914,24 @@ Optional<Score>
1894
1914
DisjunctionChoice::solve (SmallVectorImpl<Solution> &solutions,
1895
1915
FreeTypeVariableBinding allowFreeTypeVariables) {
1896
1916
CS->simplifyDisjunctionChoice (Choice);
1897
- bool failed = CS->solveRec (solutions, allowFreeTypeVariables);
1898
- return failed ? None : Optional<Score>(CS->CurrentScore );
1917
+
1918
+ if (CS->solveRec (solutions, allowFreeTypeVariables))
1919
+ return None;
1920
+
1921
+ assert (!solutions.empty ());
1922
+
1923
+ Score bestScore = solutions.front ().getFixedScore ();
1924
+
1925
+ if (solutions.size () == 1 )
1926
+ return bestScore;
1927
+
1928
+ for (unsigned i = 1 , n = solutions.size (); i != n; ++i) {
1929
+ auto &score = solutions[i].getFixedScore ();
1930
+ if (score < bestScore)
1931
+ bestScore = score;
1932
+ }
1933
+
1934
+ return bestScore;
1899
1935
}
1900
1936
1901
1937
bool DisjunctionChoice::isGenericOperatorOrUnavailable () const {
0 commit comments