@@ -599,6 +599,8 @@ void InferredAssociatedTypesByWitness::dump(llvm::raw_ostream &out,
599
599
out.indent (indent) << " (" ;
600
600
if (Witness) {
601
601
Witness->dumpRef (out);
602
+ } else {
603
+ out << " Tautological" ;
602
604
}
603
605
604
606
for (const auto &inferred : Inferred) {
@@ -948,12 +950,12 @@ class AssociatedTypeInference {
948
950
949
951
// / Infer associated type witnesses for the given tentative
950
952
// / requirement/witness match.
951
- InferredAssociatedTypesByWitness inferTypeWitnessesViaValueWitness (
953
+ InferredAssociatedTypesByWitness getPotentialTypeWitnessesByMatchingTypes (
952
954
ValueDecl *req,
953
955
ValueDecl *witness);
954
956
955
957
// / Infer associated type witnesses for the given value requirement.
956
- InferredAssociatedTypesByWitnesses inferTypeWitnessesViaValueWitnesses (
958
+ InferredAssociatedTypesByWitnesses getPotentialTypeWitnessesFromRequirement (
957
959
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
958
960
ValueDecl *req);
959
961
@@ -1309,20 +1311,25 @@ static bool isExtensionUsableForInference(const ExtensionDecl *extension,
1309
1311
if (!checkConformance (proto))
1310
1312
return false ;
1311
1313
1312
- // Source file and module file have different ways to get self bounds.
1313
- // Source file extension will have trailing where clause which can avoid
1314
- // computing a generic signature. Module file will not have
1315
- // trailing where clause, so it will compute generic signature to get
1316
- // self bounds which might result in slow performance.
1314
+ // In a source file, we perform a syntactic check which avoids computing a
1315
+ // generic signature. In a binary module, we have a generic signature so we
1316
+ // can query it directly.
1317
1317
SelfBounds bounds;
1318
1318
if (extension->getParentSourceFile () != nullptr )
1319
1319
bounds = getSelfBoundsFromWhereClause (extension);
1320
- else
1320
+ else {
1321
+ LLVM_DEBUG (llvm::dbgs () << " -- extension generic signature: "
1322
+ << extension->getGenericSignature () << " \n " );
1321
1323
bounds = getSelfBoundsFromGenericSignature (extension);
1324
+ }
1322
1325
for (auto *decl : bounds.decls ) {
1323
1326
if (auto *proto = dyn_cast<ProtocolDecl>(decl)) {
1324
- if (!checkConformance (proto))
1327
+ if (!checkConformance (proto)) {
1328
+ LLVM_DEBUG (llvm::dbgs () << " -- " << conformance->getType ()
1329
+ << " does not conform to " << proto->getName ()
1330
+ << " \n " );
1325
1331
return false ;
1332
+ }
1326
1333
}
1327
1334
}
1328
1335
@@ -1431,8 +1438,31 @@ static InferenceCandidateKind checkInferenceCandidate(
1431
1438
return InferenceCandidateKind::Good;
1432
1439
}
1433
1440
1441
+ // / Create an initial constraint system for the associated type inference solver.
1442
+ // /
1443
+ // / Each protocol requirement defines a disjunction, where each disjunction
1444
+ // / element is a potential value witness for the requirement.
1445
+ // /
1446
+ // / Each value witness binds some set of type witness candidates, which we
1447
+ // / compute by matching the witness type against the requirement.
1448
+ // /
1449
+ // / The solver must pick exactly one value witness for each requirement while
1450
+ // / ensuring that the potential type bindings from each value witness are
1451
+ // / compatible with each other.
1452
+ // /
1453
+ // / A value witness may be tautological, meaning it does not introduce any
1454
+ // / potential type witness bindings, for example, a protocol extension default
1455
+ // / `func f(_: Self.A) {}` for a protocol requirement `func f(_: Self.A)` with
1456
+ // / associated type A.
1457
+ // /
1458
+ // / We collapse all tautological witnesses into one, since the solver only needs
1459
+ // / to explore that part of the solution space at most once. It is also true
1460
+ // / that it needs to explore it *at least* once, and we must take care when
1461
+ // / skipping potential bindings to distinguish between scenarios where a single
1462
+ // / binding is skipped, or the entire value witness must be thrown out because
1463
+ // / a binding is unsatisfiable.
1434
1464
InferredAssociatedTypesByWitnesses
1435
- AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses (
1465
+ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement (
1436
1466
const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
1437
1467
ValueDecl *req) {
1438
1468
// Conformances constructed by the ClangImporter should have explicit type
@@ -1449,6 +1479,9 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1449
1479
1450
1480
InferredAssociatedTypesByWitnesses result;
1451
1481
1482
+ // Was there at least one witness that does not introduce new bindings?
1483
+ bool hadTautologicalWitness = false ;
1484
+
1452
1485
LLVM_DEBUG (llvm::dbgs () << " Considering requirement:\n " ;
1453
1486
req->dump (llvm::dbgs ()));
1454
1487
@@ -1473,7 +1506,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1473
1506
}
1474
1507
1475
1508
// Try to resolve the type witness via this value witness.
1476
- auto witnessResult = inferTypeWitnessesViaValueWitness (req, witness);
1509
+ auto witnessResult = getPotentialTypeWitnessesByMatchingTypes (req, witness);
1477
1510
1478
1511
// Filter out duplicated inferred types as well as inferred types
1479
1512
// that don't meet the requirements placed on the associated type.
@@ -1493,12 +1526,16 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1493
1526
// Filter out errors.
1494
1527
if (result.second ->hasError ()) {
1495
1528
LLVM_DEBUG (llvm::dbgs () << " -- has error type\n " );
1529
+ // Skip this binding, but consider others from the same witness.
1530
+ // This might not be strictly correct, but once we have error types
1531
+ // we're diagnosing something anyway.
1496
1532
REJECT;
1497
1533
}
1498
1534
1499
1535
// Filter out duplicates.
1500
1536
if (!known.insert ({result.first , result.second ->getCanonicalType ()})
1501
1537
.second ) {
1538
+ // Skip this binding, but consider others from the same witness.
1502
1539
LLVM_DEBUG (llvm::dbgs () << " -- duplicate\n " );
1503
1540
REJECT;
1504
1541
}
@@ -1517,18 +1554,20 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1517
1554
1518
1555
case InferenceCandidateKind::Tautological: {
1519
1556
LLVM_DEBUG (llvm::dbgs () << " -- tautological\n " );
1557
+ // Skip this binding because it is immediately satisfied.
1520
1558
REJECT;
1521
1559
}
1522
1560
1523
1561
case InferenceCandidateKind::Infinite: {
1524
1562
LLVM_DEBUG (llvm::dbgs () << " -- infinite\n " );
1563
+ // Discard this witness altogether, because it has an unsatisfiable
1564
+ // binding.
1525
1565
goto next_witness;
1526
1566
}
1527
1567
}
1528
1568
1529
- // Check that the type witness doesn't contradict an
1530
- // explicitly-given type witness. If it does contradict, throw out the
1531
- // witness completely.
1569
+ // Check that the binding doesn't contradict an explicitly-given type
1570
+ // witness. If it does contradict, throw out the witness completely.
1532
1571
if (!allUnresolved.count (result.first )) {
1533
1572
auto existingWitness =
1534
1573
conformance->getTypeWitness (result.first );
@@ -1560,6 +1599,10 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1560
1599
witnessResult.NonViable .push_back (
1561
1600
std::make_tuple (result.first ,result.second ,failed));
1562
1601
LLVM_DEBUG (llvm::dbgs () << " -- doesn't fulfill requirements\n " );
1602
+
1603
+ // By adding an element to NonViable we ensure the witness is rejected
1604
+ // below, so we continue to consider other bindings to generate better
1605
+ // diagnostics later.
1563
1606
REJECT;
1564
1607
}
1565
1608
}
@@ -1569,9 +1612,13 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1569
1612
}
1570
1613
#undef REJECT
1571
1614
1572
- // If no inferred types remain, skip this witness.
1573
- if (witnessResult.Inferred .empty () && witnessResult.NonViable .empty ())
1615
+ // If no viable or non-viable bindings remain, the witness does not
1616
+ // inter anything new, nor contradict any existing bindings. We collapse
1617
+ // all tautological witnesses into a single element of the disjunction.
1618
+ if (witnessResult.Inferred .empty () && witnessResult.NonViable .empty ()) {
1619
+ hadTautologicalWitness = true ;
1574
1620
continue ;
1621
+ }
1575
1622
1576
1623
// If there were any non-viable inferred associated types, don't
1577
1624
// infer anything from this witness.
@@ -1582,6 +1629,13 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1582
1629
next_witness:;
1583
1630
}
1584
1631
1632
+ if (hadTautologicalWitness && !result.empty ()) {
1633
+ // Create a dummy entry, but only if there was at least one other witness;
1634
+ // otherwise, we return an empty disjunction. See the remark in
1635
+ // inferTypeWitnessesViaValueWitnesses() for explanation.
1636
+ result.push_back (InferredAssociatedTypesByWitness ());
1637
+ }
1638
+
1585
1639
return result;
1586
1640
}
1587
1641
@@ -1654,10 +1708,16 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
1654
1708
continue ;
1655
1709
}
1656
1710
1657
- // Infer associated types from the potential value witnesses for
1658
- // this requirement .
1711
+ // Collect this requirement's value witnesses and their potential
1712
+ // type witness bindings .
1659
1713
auto reqInferred =
1660
- inferTypeWitnessesViaValueWitnesses (assocTypes, req);
1714
+ getPotentialTypeWitnessesFromRequirement (assocTypes, req);
1715
+
1716
+ // An empty disjunction is silently discarded, instead of immediately
1717
+ // refuting the entirely system as it would in a real solver.
1718
+ //
1719
+ // If we find a solution and it so happens that this requirement cannot be
1720
+ // witnessed, we'll diagnose the failure later in value witness checking.
1661
1721
if (reqInferred.empty ())
1662
1722
continue ;
1663
1723
@@ -1820,6 +1880,12 @@ AssociatedTypeInference::inferTypeWitnessesViaAssociatedType(
1820
1880
result.push_back (std::move (inferred));
1821
1881
}
1822
1882
1883
+ if (!result.empty ()) {
1884
+ // If we found at least one default candidate, we must allow for the
1885
+ // possibility that no default is chosen by adding a tautological witness
1886
+ // to our disjunction.
1887
+ result.push_back (InferredAssociatedTypesByWitness ());
1888
+ }
1823
1889
return result;
1824
1890
}
1825
1891
@@ -1878,10 +1944,11 @@ getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) {
1878
1944
return nullptr ;
1879
1945
}
1880
1946
1881
- // / Attempt to resolve a type witness via a specific value witness.
1947
+ // / Find a set of potential type witness bindings by matching the interface type
1948
+ // / of the requirement against the interface type of a witness.
1882
1949
InferredAssociatedTypesByWitness
1883
- AssociatedTypeInference::inferTypeWitnessesViaValueWitness (ValueDecl *req,
1884
- ValueDecl *witness) {
1950
+ AssociatedTypeInference::getPotentialTypeWitnessesByMatchingTypes (ValueDecl *req,
1951
+ ValueDecl *witness) {
1885
1952
InferredAssociatedTypesByWitness inferred;
1886
1953
inferred.Witness = witness;
1887
1954
@@ -3032,16 +3099,28 @@ void AssociatedTypeInference::findSolutionsRec(
3032
3099
for (const auto &witnessReq : inferredReq.second ) {
3033
3100
llvm::SaveAndRestore<unsigned > savedNumTypeWitnesses (numTypeWitnesses);
3034
3101
3035
- // If we inferred a type witness via a default, try both with and without
3036
- // the default.
3037
- if (isa<TypeDecl>(inferredReq.first )) {
3038
- // Recurse without considering this type.
3102
+ // If we had at least one tautological witness, we must consider the
3103
+ // possibility that none of the remaining witnesses are chosen.
3104
+ if (witnessReq.Witness == nullptr ) {
3105
+ // Count tautological witnesses as if they come from protocol extensions,
3106
+ // which ranks the solution lower than a more constrained one.
3107
+ if (!isa<TypeDecl>(inferredReq.first ))
3108
+ ++numValueWitnessesInProtocolExtensions;
3039
3109
valueWitnesses.push_back ({inferredReq.first , nullptr });
3040
3110
findSolutionsRec (unresolvedAssocTypes, solutions, nonViableSolutions,
3041
3111
valueWitnesses, numTypeWitnesses,
3042
3112
numValueWitnessesInProtocolExtensions, reqDepth + 1 );
3043
3113
valueWitnesses.pop_back ();
3114
+ if (!isa<TypeDecl>(inferredReq.first ))
3115
+ --numValueWitnessesInProtocolExtensions;
3116
+ continue ;
3117
+ }
3044
3118
3119
+ // If we inferred a type witness via a default, we do a slightly simpler
3120
+ // thing.
3121
+ //
3122
+ // FIXME: Why can't we just fold this with the below?
3123
+ if (isa<TypeDecl>(inferredReq.first )) {
3045
3124
++numTypeWitnesses;
3046
3125
for (const auto &typeWitness : witnessReq.Inferred ) {
3047
3126
auto known = typeWitnesses.begin (typeWitness.first );
@@ -3075,6 +3154,7 @@ void AssociatedTypeInference::findSolutionsRec(
3075
3154
llvm::dbgs () << " := " ;
3076
3155
witnessReq.Witness ->dumpRef (llvm::dbgs ());
3077
3156
llvm::dbgs () << " \n " ;);
3157
+
3078
3158
valueWitnesses.push_back ({inferredReq.first , witnessReq.Witness });
3079
3159
if (!isa<TypeDecl>(inferredReq.first ) &&
3080
3160
witnessReq.Witness ->getDeclContext ()->getExtendedProtocolDecl ())
0 commit comments