@@ -1650,64 +1650,67 @@ bool ConstraintSystem::haveTypeInformationForAllArguments(
16501650}
16511651
16521652Constraint *ConstraintSystem::getUnboundBindOverloadDisjunction (
1653- TypeVariableType *tyvar) {
1653+ TypeVariableType *tyvar, unsigned *numOptionalUnwraps) {
1654+ if (numOptionalUnwraps)
1655+ *numOptionalUnwraps = 0 ;
1656+
16541657 auto *rep = getRepresentative (tyvar);
16551658 assert (!getFixedType (rep));
16561659
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+ }
16771679
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 ;
16801685
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 ;
16861691
1687- SmallVector<OverloadChoice, 2 > choices;
1692+ return getRepresentative (lhsTypeVar) == rep;
1693+ });
16881694
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 ];
16911698
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;
16981703
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 ;
17051707 }
17061708
1707- choices.push_back (constraint->getOverloadChoice ());
1709+ // There is nowhere else to look.
1710+ return nullptr ;
17081711 }
17091712
1710- return choices ;
1713+ return nullptr ;
17111714}
17121715
17131716// Find a disjunction associated with an ApplicableFunction constraint
@@ -1941,7 +1944,7 @@ static Constraint *tryOptimizeGenericDisjunction(
19411944 return type->isAny ();
19421945 });
19431946
1944- // If function declaration references `Any` or `Any?` type
1947+ // If function declaration references `Any` or an optional type,
19451948 // let's not attempt it, because it's unclear
19461949 // without solving which overload is going to be better.
19471950 return !hasAnyOrOptional;
0 commit comments