@@ -1802,15 +1802,89 @@ static bool shouldSkipDisjunctionChoice(ConstraintSystem &cs,
1802
1802
return false ;
1803
1803
}
1804
1804
1805
+ // Attempt to find a disjunction of bind constraints where all options
1806
+ // in the disjunction are binding the same type variable, and where
1807
+ // that type variable appears as the right hand side of a conversion
1808
+ // constraint.
1809
+ //
1810
+ // Trying these bindings early can make it possible to split the
1811
+ // constraint system into multiple ones.
1812
+ static Constraint *selectDisjunctionBindingConversionResultType (
1813
+ ConstraintSystem &cs, SmallVectorImpl<Constraint *> &disjunctions) {
1814
+
1815
+ // Collect any disjunctions that simply attempt bindings for a
1816
+ // type variable.
1817
+ SmallVector<Constraint *, 8 > bindingDisjunctions;
1818
+ for (auto *disjunction : disjunctions) {
1819
+ llvm::Optional<TypeVariableType *> commonTypeVariable;
1820
+ if (llvm::all_of (
1821
+ disjunction->getNestedConstraints (),
1822
+ [&](Constraint *bindingConstraint) {
1823
+ if (bindingConstraint->getKind () != ConstraintKind::Bind)
1824
+ return false ;
1825
+
1826
+ auto *tv =
1827
+ bindingConstraint->getFirstType ()->getAs <TypeVariableType>();
1828
+ // Only do this for simple type variable bindings, not for
1829
+ // bindings like: ($T1) -> $T2 bind String -> Int
1830
+ if (!tv)
1831
+ return false ;
1832
+
1833
+ if (!commonTypeVariable.hasValue ())
1834
+ commonTypeVariable = tv;
1835
+
1836
+ if (commonTypeVariable.getValue () != tv)
1837
+ return false ;
1838
+
1839
+ return true ;
1840
+ })) {
1841
+ bindingDisjunctions.push_back (disjunction);
1842
+ }
1843
+ }
1844
+
1845
+ for (auto *disjunction : bindingDisjunctions) {
1846
+ auto nested = disjunction->getNestedConstraints ();
1847
+ assert (!nested.empty ());
1848
+ auto *tv = cs.simplifyType (nested[0 ]->getFirstType ())
1849
+ ->getRValueType ()
1850
+ ->getAs <TypeVariableType>();
1851
+ assert (tv);
1852
+
1853
+ SmallVector<Constraint *, 8 > constraints;
1854
+ cs.getConstraintGraph ().gatherConstraints (
1855
+ tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);
1856
+
1857
+ for (auto *constraint : constraints) {
1858
+ if (constraint->getKind () != ConstraintKind::Conversion)
1859
+ continue ;
1860
+
1861
+ auto toType =
1862
+ cs.simplifyType (constraint->getSecondType ())->getRValueType ();
1863
+ auto *toTV = toType->getAs <TypeVariableType>();
1864
+ if (tv != toTV)
1865
+ continue ;
1866
+
1867
+ return disjunction;
1868
+ }
1869
+ }
1870
+
1871
+ return nullptr ;
1872
+ }
1873
+
1805
1874
Constraint *ConstraintSystem::selectDisjunction (
1806
1875
SmallVectorImpl<Constraint *> &disjunctions) {
1807
1876
if (disjunctions.empty ())
1808
1877
return nullptr ;
1809
1878
1879
+ auto *disjunction =
1880
+ selectDisjunctionBindingConversionResultType (*this , disjunctions);
1881
+ if (disjunction)
1882
+ return disjunction;
1883
+
1810
1884
// Pick the smallest disjunction.
1811
1885
// FIXME: This heuristic isn't great, but it helped somewhat for
1812
1886
// overload sets.
1813
- auto disjunction = disjunctions[0 ];
1887
+ disjunction = disjunctions[0 ];
1814
1888
auto bestSize = disjunction->countActiveNestedConstraints ();
1815
1889
if (bestSize > 2 ) {
1816
1890
for (auto contender : llvm::makeArrayRef (disjunctions).slice (1 )) {
0 commit comments