@@ -1228,8 +1228,7 @@ struct TypeReprCycleCheckWalker : ASTWalker {
12281228 bool checkForPotentialCycle (ValueDecl *witness) {
12291229 // Don't do this for protocol extension members, because we have a
12301230 // mini "solver" that avoids similar issues instead.
1231- if (witness->getDeclContext ()->getSelfProtocolDecl () != nullptr )
1232- return false ;
1231+ assert (!witness->getDeclContext ()->getExtendedProtocolDecl ());
12331232
12341233 // If we already have an interface type, don't bother trying to
12351234 // avoid a cycle.
@@ -1383,12 +1382,9 @@ enum class InferenceCandidateKind {
13831382static InferenceCandidateKind checkInferenceCandidate (
13841383 std::pair<AssociatedTypeDecl *, Type> *result,
13851384 NormalProtocolConformance *conformance,
1386- ValueDecl *witness) {
1387- auto witnessContext = witness->getDeclContext ();
1388- auto &ctx = witnessContext->getASTContext ();
1389-
1390- assert (witnessContext->getExtendedProtocolDecl ());
1391- auto selfTy = witnessContext->getSelfInterfaceType ();
1385+ DeclContext *witnessDC,
1386+ Type selfTy) {
1387+ auto &ctx = selfTy->getASTContext ();
13921388
13931389 auto isTautological = [&](Type t) -> bool {
13941390 auto dmt = t->getAs <DependentMemberType>();
@@ -1416,17 +1412,16 @@ static InferenceCandidateKind checkInferenceCandidate(
14161412 return true ;
14171413 };
14181414
1415+ // Self.X == Self.X doesn't give us any new information, nor does it
1416+ // immediately fail.
14191417 if (isTautological (result->second )) {
14201418 auto *dmt = result->second ->castTo <DependentMemberType>();
14211419
1422- // If this associated type is same-typed to another associated type
1423- // on `Self`, then it may still be an interesting candidate if we find
1424- // an answer for that other type.
1425- auto selfTy = witnessContext->getSelfInterfaceType ();
1426- auto selfAssocTy = DependentMemberType::get (selfTy,
1427- dmt->getAssocType ());
1428- for (auto &reqt : witnessContext->getGenericSignatureOfContext ()
1429- .getRequirements ()) {
1420+ auto selfAssocTy = DependentMemberType::get (selfTy, dmt->getAssocType ());
1421+
1422+ // If we have a same-type requirement `Self.X == Self.Y`,
1423+ // introduce a binding `Self.X := Self.Y`.
1424+ for (auto &reqt : witnessDC->getGenericSignatureOfContext ().getRequirements ()) {
14301425 switch (reqt.getKind ()) {
14311426 case RequirementKind::SameShape:
14321427 llvm_unreachable (" Same-shape requirement not supported here" );
@@ -1460,8 +1455,6 @@ static InferenceCandidateKind checkInferenceCandidate(
14601455
14611456 }
14621457
1463- // We may be able to infer one associated type from the
1464- // other.
14651458 result->second = result->second .transform ([&](Type t) -> Type{
14661459 if (t->isEqual (dmt))
14671460 return otherDMT;
@@ -1479,6 +1472,8 @@ static InferenceCandidateKind checkInferenceCandidate(
14791472 return InferenceCandidateKind::Tautological;
14801473 }
14811474
1475+ // If we have something like `Self.X := G<Self.X>` on the other hand,
1476+ // the binding can never be satisfied.
14821477 if (result->second .findIf (isTautological))
14831478 return InferenceCandidateKind::Infinite;
14841479
@@ -1537,6 +1532,10 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15371532 LLVM_DEBUG (llvm::dbgs () << " Inferring associated types from decl:\n " ;
15381533 witness->dump (llvm::dbgs ()));
15391534
1535+ // This is the protocol `Self` type if the witness is declared in a protocol
1536+ // extension, or nullptr.
1537+ Type selfTy;
1538+
15401539 // If the potential witness came from an extension, and our `Self`
15411540 // type can't use it regardless of what associated types we end up
15421541 // inferring, skip the witness.
@@ -1545,18 +1544,28 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15451544 LLVM_DEBUG (llvm::dbgs () << " Extension not usable for inference\n " );
15461545 continue ;
15471546 }
1547+
1548+ if (auto *proto = dyn_cast<ProtocolDecl>(extension->getExtendedNominal ()))
1549+ selfTy = proto->getSelfInterfaceType ();
15481550 }
15491551
1550- if (cycleCheck.checkForPotentialCycle (witness)) {
1551- LLVM_DEBUG (llvm::dbgs () << " Skipping witness to avoid request cycle\n " );
1552+ if (!selfTy) {
1553+ if (cycleCheck.checkForPotentialCycle (witness)) {
1554+ LLVM_DEBUG (llvm::dbgs () << " Skipping witness to avoid request cycle\n " );
15521555
1553- // We must consider the possibility that none of the witnesses for this
1554- // requirement can be chosen.
1555- hadTautologicalWitness = true ;
1556- continue ;
1556+ // We must consider the possibility that none of the witnesses for this
1557+ // requirement can be chosen.
1558+ hadTautologicalWitness = true ;
1559+ continue ;
1560+ }
15571561 }
15581562
1559- // Try to resolve the type witness via this value witness.
1563+ // Match the type of the requirement against the type of the witness to
1564+ // produce a list of bindings. The left-hand side of each binding is an
1565+ // associated type of our protocol, and the right-hand side is either
1566+ // a concrete type (possibly containing archetypes of the conforming type)
1567+ // or a type parameter rooted in the protocol 'Self' type, representing
1568+ // an unresolved type witness.
15601569 auto witnessResult = getPotentialTypeWitnessesByMatchingTypes (req, witness);
15611570
15621571 // Filter out duplicated inferred types as well as inferred types
@@ -1574,9 +1583,10 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15741583 << " can infer to:\n " ;
15751584 result.second ->dump (llvm::dbgs ()));
15761585
1577- bool fromProtocolExtension =
1578- witness->getDeclContext ()->getExtendedProtocolDecl ();
1579- assert (!result.second ->hasTypeParameter () || fromProtocolExtension);
1586+ assert (!result.second ->hasTypeParameter () || selfTy &&
1587+ " We should only see unresolved type witnesses on the "
1588+ " right-hand side of a binding when the value witness came from a "
1589+ " protocol extension" );
15801590
15811591 // Filter out errors.
15821592 if (result.second ->hasError ()) {
@@ -1595,42 +1605,48 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15951605 REJECT;
15961606 }
15971607
1598- if (fromProtocolExtension) {
1599- // Filter out circular possibilities, e.g. that
1600- // AssocType == Self.AssocType or
1601- // AssocType == Foo<Self.AssocType>.
1602- switch (checkInferenceCandidate (&result, conformance, witness)) {
1608+ // The type of a potential value witness in a protocol extensions may
1609+ // itself involve unresolved type witnesses.
1610+ if (selfTy) {
1611+ // Handle Self.X := Self.X and Self.X := G<Self.X>.
1612+ switch (checkInferenceCandidate (&result, conformance,
1613+ witness->getDeclContext (), selfTy)) {
16031614 case InferenceCandidateKind::Good:
1604- // Continued below .
1615+ // The "good" case is something like `Self.X := Self.Y` .
16051616 break ;
16061617
16071618 case InferenceCandidateKind::Tautological: {
16081619 LLVM_DEBUG (llvm::dbgs () << " -- tautological\n " );
1620+ // A tautology is the `Self.X := Self.X` case.
1621+ //
16091622 // Skip this binding because it is immediately satisfied.
16101623 REJECT;
16111624 }
16121625
16131626 case InferenceCandidateKind::Infinite: {
16141627 LLVM_DEBUG (llvm::dbgs () << " -- infinite\n " );
1628+ // The infinite case is `Self.X := G<Self.X>`.
1629+ //
16151630 // Discard this witness altogether, because it has an unsatisfiable
16161631 // binding.
16171632 goto next_witness;
16181633 }
16191634 }
16201635 }
16211636
1622- // Check that the binding doesn't contradict an explicitly-given type
1623- // witness. If it does contradict, throw out the witness completely.
1637+ // Check that the binding doesn't contradict a type witness previously
1638+ // resolved via name lookup.
1639+ //
1640+ // If it does contradict, throw out the witness entirely.
16241641 if (!allUnresolved.count (result.first )) {
16251642 auto existingWitness =
16261643 conformance->getTypeWitness (result.first );
16271644 existingWitness = dc->mapTypeIntoContext (existingWitness);
16281645
1629- // If the deduced type contains an irreducible
1630- // DependentMemberType, that indicates a dependency
1631- // on another associated type we haven't deduced,
1632- // so we can't tell whether there's a contradiction
1633- // yet.
1646+ // For now, only a fully-concrete binding can contradict an existing
1647+ // type witness.
1648+ //
1649+ // FIXME: Generate new constraints by matching the two types.
16341650 auto newWitness = result.second ->getCanonicalType ();
16351651 if (!newWitness->hasTypeParameter () &&
16361652 !newWitness->hasDependentMember () &&
@@ -1641,8 +1657,8 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
16411657 }
16421658 }
16431659
1644- // Check that the type witness meets the requirements on the
1645- // associated type.
1660+ // Check that the potential type witness satisfies the local requirements
1661+ // imposed upon the associated type.
16461662 if (auto failed =
16471663 checkTypeWitness (result.second , result.first , conformance)) {
16481664 witnessResult.NonViable .push_back (
@@ -1661,15 +1677,15 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
16611677#undef REJECT
16621678
16631679 // If no viable or non-viable bindings remain, the witness does not
1664- // inter anything new, nor contradict any existing bindings. We collapse
1665- // all tautological witnesses into a single element of the disjunction.
1680+ // give us anything new or contradict any existing bindings. We collapse
1681+ // all tautological witnesses into a single disjunction term .
16661682 if (witnessResult.Inferred .empty () && witnessResult.NonViable .empty ()) {
16671683 hadTautologicalWitness = true ;
16681684 continue ;
16691685 }
16701686
1671- // If there were any non-viable inferred associated types, don't
1672- // infer anything from this witness.
1687+ // If we had at least one non-viable binding, drop the viable bindings;
1688+ // we cannot infer anything from this witness.
16731689 if (!witnessResult.NonViable .empty ())
16741690 witnessResult.Inferred .clear ();
16751691
@@ -3627,6 +3643,8 @@ void AssociatedTypeInference::findSolutionsRec(
36273643
36283644 // If one has a type parameter remaining but the other does not,
36293645 // drop the one with the type parameter.
3646+ //
3647+ // FIXME: This is too ad-hoc. Generate new constraints instead.
36303648 if ((known->first ->hasTypeParameter () ||
36313649 known->first ->hasDependentMember ())
36323650 != (typeWitness.second ->hasTypeParameter () ||
0 commit comments