@@ -1321,6 +1321,108 @@ static bool isExtensionUsableForInference(const ExtensionDecl *extension,
1321
1321
return true ;
1322
1322
}
1323
1323
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
+
1324
1426
InferredAssociatedTypesByWitnesses
1325
1427
AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses (
1326
1428
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
@@ -1397,82 +1499,25 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1397
1499
// AssocType == S.AssocType or
1398
1500
// AssocType == Foo<S.AssocType>.
1399
1501
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
- }
1467
1502
1468
- return true ;
1469
- });
1503
+ switch (checkInferenceCandidate (&result,
1504
+ &canInferFromOtherAssociatedType,
1505
+ conformance, witness)) {
1506
+ case InferenceCandidateKind::Good:
1507
+ // Continued below.
1508
+ break ;
1470
1509
1471
- if (containsTautologicalType) {
1510
+ case InferenceCandidateKind::Tautological: {
1472
1511
LLVM_DEBUG (llvm::dbgs () << " -- tautological\n " );
1473
1512
REJECT;
1474
1513
}
1475
1514
1515
+ case InferenceCandidateKind::Infinite: {
1516
+ LLVM_DEBUG (llvm::dbgs () << " -- infinite\n " );
1517
+ goto next_witness;
1518
+ }
1519
+ }
1520
+
1476
1521
// Check that the type witness doesn't contradict an
1477
1522
// explicitly-given type witness. If it does contradict, throw out the
1478
1523
// witness completely.
@@ -1868,13 +1913,17 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitness(ValueDecl *req,
1868
1913
if (!inferredType->isMaterializable ())
1869
1914
return true ;
1870
1915
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> ())
1876
1921
return true ;
1877
1922
1923
+ // A type containing a type parameter cannot match.
1924
+ if (inferredType->hasTypeParameter ())
1925
+ return false ;
1926
+
1878
1927
auto proto = Conformance->getProtocol ();
1879
1928
if (auto assocType = getReferencedAssocTypeOfProtocol (firstDepMember,
1880
1929
proto)) {
0 commit comments