@@ -1650,64 +1650,67 @@ bool ConstraintSystem::haveTypeInformationForAllArguments(
1650
1650
}
1651
1651
1652
1652
Constraint *ConstraintSystem::getUnboundBindOverloadDisjunction (
1653
- TypeVariableType *tyvar) {
1653
+ TypeVariableType *tyvar, unsigned *numOptionalUnwraps) {
1654
+ if (numOptionalUnwraps)
1655
+ *numOptionalUnwraps = 0 ;
1656
+
1654
1657
auto *rep = getRepresentative (tyvar);
1655
1658
assert (!getFixedType (rep));
1656
1659
1657
- llvm::SetVector<Constraint *> disjunctions;
1658
- getConstraintGraph ().gatherConstraints (
1659
- rep, disjunctions, ConstraintGraph::GatheringKind::EquivalenceClass,
1660
- [this , rep](Constraint *match) {
1661
- if (match->getKind () != ConstraintKind::Disjunction ||
1662
- match->getNestedConstraints ().front ()->getKind () !=
1663
- ConstraintKind::BindOverload)
1664
- return false ;
1665
-
1666
- auto lhsTypeVar =
1667
- match->getNestedConstraints ().front ()->getFirstType ()
1668
- ->getAs <TypeVariableType>();
1669
- if (!lhsTypeVar)
1670
- return false ;
1671
-
1672
- return getRepresentative (lhsTypeVar) == rep;
1673
- });
1674
-
1675
- if (disjunctions.empty ())
1676
- return nullptr ;
1660
+ SmallPtrSet<TypeVariableType *, 4 > visitedVars;
1661
+ while (visitedVars.insert (rep).second ) {
1662
+ // Look for a disjunction that binds this type variable to an overload set.
1663
+ TypeVariableType *optionalObjectTypeVar = nullptr ;
1664
+ llvm::SetVector<Constraint *> disjunctions;
1665
+ getConstraintGraph ().gatherConstraints (
1666
+ rep, disjunctions, ConstraintGraph::GatheringKind::EquivalenceClass,
1667
+ [this , rep, &optionalObjectTypeVar](Constraint *match) {
1668
+ // If we have an "optional object of" constraint where the right-hand
1669
+ // side is this type variable, we may need to follow that type
1670
+ // variable to find the disjunction.
1671
+ if (match->getKind () == ConstraintKind::OptionalObject) {
1672
+ auto rhsTypeVar = match->getSecondType ()->getAs <TypeVariableType>();
1673
+ if (rhsTypeVar && getRepresentative (rhsTypeVar) == rep) {
1674
+ optionalObjectTypeVar =
1675
+ match->getFirstType ()->getAs <TypeVariableType>();
1676
+ }
1677
+ return false ;
1678
+ }
1677
1679
1678
- return disjunctions[0 ];
1679
- }
1680
+ // We only care about disjunctions of overload bindings.
1681
+ if (match->getKind () != ConstraintKind::Disjunction ||
1682
+ match->getNestedConstraints ().front ()->getKind () !=
1683
+ ConstraintKind::BindOverload)
1684
+ return false ;
1680
1685
1681
- // / solely resolved by an overload set.
1682
- SmallVector<OverloadChoice, 2 > ConstraintSystem::getUnboundBindOverloads (
1683
- TypeVariableType *tyvar) {
1684
- // Always work on the representation.
1685
- tyvar = getRepresentative (tyvar) ;
1686
+ auto lhsTypeVar =
1687
+ match-> getNestedConstraints (). front ()-> getFirstType ()
1688
+ -> getAs < TypeVariableType>();
1689
+ if (!lhsTypeVar)
1690
+ return false ;
1686
1691
1687
- SmallVector<OverloadChoice, 2 > choices;
1692
+ return getRepresentative (lhsTypeVar) == rep;
1693
+ });
1688
1694
1689
- auto disjunction = getUnboundBindOverloadDisjunction (tyvar);
1690
- if (!disjunction) return choices;
1695
+ // If we found a disjunction, return it.
1696
+ if (!disjunctions.empty ())
1697
+ return disjunctions[0 ];
1691
1698
1692
- for (auto constraint : disjunction->getNestedConstraints ()) {
1693
- // We must have bind-overload constraints.
1694
- if (constraint->getKind () != ConstraintKind::BindOverload) {
1695
- choices.clear ();
1696
- return choices;
1697
- }
1699
+ // If we found an "optional object of" constraint, follow it.
1700
+ if (optionalObjectTypeVar && !getFixedType (optionalObjectTypeVar)) {
1701
+ if (numOptionalUnwraps)
1702
+ ++*numOptionalUnwraps;
1698
1703
1699
- // We must be binding the type variable (or a type variable equivalent to
1700
- // it).
1701
- auto boundTypeVar = constraint->getFirstType ()->getAs <TypeVariableType>();
1702
- if (!boundTypeVar || getRepresentative (boundTypeVar) != tyvar) {
1703
- choices.clear ();
1704
- return choices;
1704
+ tyvar = optionalObjectTypeVar;
1705
+ rep = getRepresentative (tyvar);
1706
+ continue ;
1705
1707
}
1706
1708
1707
- choices.push_back (constraint->getOverloadChoice ());
1709
+ // There is nowhere else to look.
1710
+ return nullptr ;
1708
1711
}
1709
1712
1710
- return choices ;
1713
+ return nullptr ;
1711
1714
}
1712
1715
1713
1716
// Find a disjunction associated with an ApplicableFunction constraint
@@ -1941,7 +1944,7 @@ static Constraint *tryOptimizeGenericDisjunction(
1941
1944
return type->isAny ();
1942
1945
});
1943
1946
1944
- // If function declaration references `Any` or `Any?` type
1947
+ // If function declaration references `Any` or an optional type,
1945
1948
// let's not attempt it, because it's unclear
1946
1949
// without solving which overload is going to be better.
1947
1950
return !hasAnyOrOptional;
0 commit comments