@@ -1321,6 +1321,108 @@ static bool isExtensionUsableForInference(const ExtensionDecl *extension,
13211321 return true ;
13221322}
13231323
1324+ namespace {
1325+
1326+ enum class InferenceCandidateKind {
1327+ // / Nothing weird going on.
1328+ Good,
1329+
1330+ // / T := T. Always satisfied.
1331+ Tautological,
1332+
1333+ // / T := G<T>. Cannot be satisfied.
1334+ Infinite
1335+ };
1336+
1337+ }
1338+
1339+ static InferenceCandidateKind checkInferenceCandidate (
1340+ std::pair<AssociatedTypeDecl *, Type> *result,
1341+ bool *canInferFromOtherAssociatedType,
1342+ NormalProtocolConformance *conformance,
1343+ ValueDecl *witness) {
1344+ auto isTautological = [&](Type t) -> bool {
1345+ auto dmt = t->getAs <DependentMemberType>();
1346+ if (!dmt)
1347+ return false ;
1348+ if (!associatedTypesAreSameEquivalenceClass (dmt->getAssocType (),
1349+ result->first ))
1350+ return false ;
1351+
1352+ auto typeInContext =
1353+ conformance->getDeclContext ()->mapTypeIntoContext (conformance->getType ());
1354+
1355+ if (!dmt->getBase ()->isEqual (typeInContext))
1356+ return false ;
1357+
1358+ return true ;
1359+ };
1360+
1361+ if (isTautological (result->second )) {
1362+ auto *dmt = result->second ->castTo <DependentMemberType>();
1363+
1364+ // If this associated type is same-typed to another associated type
1365+ // on `Self`, then it may still be an interesting candidate if we find
1366+ // an answer for that other type.
1367+ auto witnessContext = witness->getDeclContext ();
1368+ if (witnessContext->getExtendedProtocolDecl ()
1369+ && witnessContext->getGenericSignatureOfContext ()) {
1370+ auto selfTy = witnessContext->getSelfInterfaceType ();
1371+ auto selfAssocTy = DependentMemberType::get (selfTy,
1372+ dmt->getAssocType ());
1373+ for (auto &reqt : witnessContext->getGenericSignatureOfContext ()
1374+ .getRequirements ()) {
1375+ switch (reqt.getKind ()) {
1376+ case RequirementKind::SameShape:
1377+ llvm_unreachable (" Same-shape requirement not supported here" );
1378+
1379+ case RequirementKind::Conformance:
1380+ case RequirementKind::Superclass:
1381+ case RequirementKind::Layout:
1382+ break ;
1383+
1384+ case RequirementKind::SameType:
1385+ Type other;
1386+ if (reqt.getFirstType ()->isEqual (selfAssocTy)) {
1387+ other = reqt.getSecondType ();
1388+ } else if (reqt.getSecondType ()->isEqual (selfAssocTy)) {
1389+ other = reqt.getFirstType ();
1390+ } else {
1391+ break ;
1392+ }
1393+
1394+ if (auto otherAssoc = other->getAs <DependentMemberType>()) {
1395+ if (otherAssoc->getBase ()->isEqual (selfTy)) {
1396+ auto otherDMT = DependentMemberType::get (dmt->getBase (),
1397+ otherAssoc->getAssocType ());
1398+
1399+ // We may be able to infer one associated type from the
1400+ // other.
1401+ result->second = result->second .transform ([&](Type t) -> Type{
1402+ if (t->isEqual (dmt))
1403+ return otherDMT;
1404+ return t;
1405+ });
1406+ *canInferFromOtherAssociatedType = true ;
1407+ LLVM_DEBUG (llvm::dbgs () << " ++ we can same-type to:\n " ;
1408+ result->second ->dump (llvm::dbgs ()));
1409+ return InferenceCandidateKind::Good;
1410+ }
1411+ }
1412+ break ;
1413+ }
1414+ }
1415+ }
1416+
1417+ return InferenceCandidateKind::Tautological;
1418+ }
1419+
1420+ if (result->second .findIf (isTautological))
1421+ return InferenceCandidateKind::Infinite;
1422+
1423+ return InferenceCandidateKind::Good;
1424+ }
1425+
13241426InferredAssociatedTypesByWitnesses
13251427AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses (
13261428 const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
@@ -1397,82 +1499,25 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
13971499 // AssocType == S.AssocType or
13981500 // AssocType == Foo<S.AssocType>.
13991501 bool canInferFromOtherAssociatedType = false ;
1400- bool containsTautologicalType =
1401- result.second .findIf ([&](Type t) -> bool {
1402- auto dmt = t->getAs <DependentMemberType>();
1403- if (!dmt)
1404- return false ;
1405- if (!associatedTypesAreSameEquivalenceClass (dmt->getAssocType (),
1406- result.first ))
1407- return false ;
1408-
1409- auto typeInContext =
1410- conformance->getDeclContext ()->mapTypeIntoContext (conformance->getType ());
1411-
1412- if (!dmt->getBase ()->isEqual (typeInContext))
1413- return false ;
1414-
1415- // If this associated type is same-typed to another associated type
1416- // on `Self`, then it may still be an interesting candidate if we find
1417- // an answer for that other type.
1418- auto witnessContext = witness->getDeclContext ();
1419- if (witnessContext->getExtendedProtocolDecl ()
1420- && witnessContext->getGenericSignatureOfContext ()) {
1421- auto selfTy = witnessContext->getSelfInterfaceType ();
1422- auto selfAssocTy = DependentMemberType::get (selfTy,
1423- dmt->getAssocType ());
1424- for (auto &reqt : witnessContext->getGenericSignatureOfContext ()
1425- .getRequirements ()) {
1426- switch (reqt.getKind ()) {
1427- case RequirementKind::SameShape:
1428- llvm_unreachable (" Same-shape requirement not supported here" );
1429-
1430- case RequirementKind::Conformance:
1431- case RequirementKind::Superclass:
1432- case RequirementKind::Layout:
1433- break ;
1434-
1435- case RequirementKind::SameType:
1436- Type other;
1437- if (reqt.getFirstType ()->isEqual (selfAssocTy)) {
1438- other = reqt.getSecondType ();
1439- } else if (reqt.getSecondType ()->isEqual (selfAssocTy)) {
1440- other = reqt.getFirstType ();
1441- } else {
1442- break ;
1443- }
1444-
1445- if (auto otherAssoc = other->getAs <DependentMemberType>()) {
1446- if (otherAssoc->getBase ()->isEqual (selfTy)) {
1447- auto otherDMT = DependentMemberType::get (dmt->getBase (),
1448- otherAssoc->getAssocType ());
1449-
1450- // We may be able to infer one associated type from the
1451- // other.
1452- result.second = result.second .transform ([&](Type t) -> Type{
1453- if (t->isEqual (dmt))
1454- return otherDMT;
1455- return t;
1456- });
1457- canInferFromOtherAssociatedType = true ;
1458- LLVM_DEBUG (llvm::dbgs () << " ++ we can same-type to:\n " ;
1459- result.second ->dump (llvm::dbgs ()));
1460- return false ;
1461- }
1462- }
1463- break ;
1464- }
1465- }
1466- }
14671502
1468- return true ;
1469- });
1503+ switch (checkInferenceCandidate (&result,
1504+ &canInferFromOtherAssociatedType,
1505+ conformance, witness)) {
1506+ case InferenceCandidateKind::Good:
1507+ // Continued below.
1508+ break ;
14701509
1471- if (containsTautologicalType) {
1510+ case InferenceCandidateKind::Tautological: {
14721511 LLVM_DEBUG (llvm::dbgs () << " -- tautological\n " );
14731512 REJECT;
14741513 }
14751514
1515+ case InferenceCandidateKind::Infinite: {
1516+ LLVM_DEBUG (llvm::dbgs () << " -- infinite\n " );
1517+ goto next_witness;
1518+ }
1519+ }
1520+
14761521 // Check that the type witness doesn't contradict an
14771522 // explicitly-given type witness. If it does contradict, throw out the
14781523 // witness completely.
@@ -1868,13 +1913,17 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitness(ValueDecl *req,
18681913 if (!inferredType->isMaterializable ())
18691914 return true ;
18701915
1871- // If the type contains a type parameter, there is nothing we can infer
1872- // from it.
1873- // FIXME: This is a weird state introduced by associated type inference
1874- // that should not exist .
1875- if (inferredType->hasTypeParameter ())
1916+ // Type parameters of the conforming type become archetypes here, so
1917+ // any remaining type parameters correspond to the innermost generic
1918+ // parameter list of the witness. A generic parameter gives us a
1919+ // tautological match .
1920+ if (inferredType->is <GenericTypeParamType> ())
18761921 return true ;
18771922
1923+ // A type containing a type parameter cannot match.
1924+ if (inferredType->hasTypeParameter ())
1925+ return false ;
1926+
18781927 auto proto = Conformance->getProtocol ();
18791928 if (auto assocType = getReferencedAssocTypeOfProtocol (firstDepMember,
18801929 proto)) {
0 commit comments