20
20
#include " swift/AST/Decl.h"
21
21
#include " swift/AST/GenericSignature.h"
22
22
#include " swift/AST/NameLookupRequests.h"
23
+ #include " swift/AST/PrettyStackTrace.h"
23
24
#include " swift/AST/ProtocolConformance.h"
24
25
#include " swift/AST/SubstitutionMap.h"
25
26
#include " swift/AST/TypeMatcher.h"
@@ -1161,6 +1162,8 @@ bool AssociatedTypeInference::checkCurrentTypeWitnesses(
1161
1162
QuerySubstitutionMap{substitutions}, options)) {
1162
1163
case CheckGenericArgumentsResult::RequirementFailure:
1163
1164
++NumSolutionStatesFailedCheck;
1165
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1166
+ << " + Requirement failure\n " ;);
1164
1167
return true ;
1165
1168
1166
1169
case CheckGenericArgumentsResult::Success:
@@ -1186,6 +1189,9 @@ bool AssociatedTypeInference::checkCurrentTypeWitnesses(
1186
1189
1187
1190
++NumConstrainedExtensionChecks;
1188
1191
if (checkConstrainedExtension (ext)) {
1192
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1193
+ << " + Constrained extension failed: " <<
1194
+ ext->getExtendedType () << " \n " ;);
1189
1195
++NumConstrainedExtensionChecksFailed;
1190
1196
return true ;
1191
1197
}
@@ -1432,6 +1438,22 @@ void AssociatedTypeInference::findSolutions(
1432
1438
SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4 > valueWitnesses;
1433
1439
findSolutionsRec (unresolvedAssocTypes, solutions, nonViableSolutions,
1434
1440
valueWitnesses, 0 , 0 , 0 );
1441
+
1442
+ for (auto solution : solutions) {
1443
+ LLVM_DEBUG (llvm::dbgs () << " === Valid solution:\n " ;);
1444
+ for (auto pair : solution.TypeWitnesses ) {
1445
+ LLVM_DEBUG (llvm::dbgs () << pair.first ->getName () << " := "
1446
+ << pair.second .first << " \n " ;);
1447
+ }
1448
+ }
1449
+
1450
+ for (auto solution : nonViableSolutions) {
1451
+ LLVM_DEBUG (llvm::dbgs () << " === Invalid solution:\n " ;);
1452
+ for (auto pair : solution.TypeWitnesses ) {
1453
+ LLVM_DEBUG (llvm::dbgs () << pair.first ->getName () << " := "
1454
+ << pair.second .first << " \n " ;);
1455
+ }
1456
+ }
1435
1457
}
1436
1458
1437
1459
void AssociatedTypeInference::findSolutionsRec (
@@ -1462,6 +1484,8 @@ void AssociatedTypeInference::findSolutionsRec(
1462
1484
if (!missingTypeWitness)
1463
1485
missingTypeWitness = assocType;
1464
1486
1487
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1488
+ << " + Recorded an erroneous type witness\n " ;);
1465
1489
return ;
1466
1490
}
1467
1491
}
@@ -1476,6 +1500,8 @@ void AssociatedTypeInference::findSolutionsRec(
1476
1500
if (!missingTypeWitness)
1477
1501
missingTypeWitness = assocType;
1478
1502
1503
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1504
+ << " + Failed to infer abstract witnesses\n " ;);
1479
1505
return ;
1480
1506
}
1481
1507
@@ -1496,8 +1522,11 @@ void AssociatedTypeInference::findSolutionsRec(
1496
1522
continue ;
1497
1523
1498
1524
Type replaced = substCurrentTypeWitnesses (known->first );
1499
- if (replaced.isNull ())
1525
+ if (replaced.isNull ()) {
1526
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1527
+ << " + Failed substitution of " << known->first << " \n " ;);
1500
1528
return ;
1529
+ }
1501
1530
1502
1531
known->first = replaced;
1503
1532
}
@@ -1516,15 +1545,30 @@ void AssociatedTypeInference::findSolutionsRec(
1516
1545
1517
1546
// If we've seen this solution already, bail out; there's no point in
1518
1547
// checking further.
1519
- if (llvm::any_of (solutions, matchesSolution) ||
1520
- llvm::any_of (nonViableSolutions, matchesSolution)) {
1548
+ if (llvm::any_of (solutions, matchesSolution)) {
1549
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1550
+ << " + Duplicate valid solution found\n " ;);
1551
+ ++NumDuplicateSolutionStates;
1552
+ return ;
1553
+ }
1554
+ if (llvm::any_of (nonViableSolutions, matchesSolution)) {
1555
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1556
+ << " + Duplicate invalid solution found\n " ;);
1521
1557
++NumDuplicateSolutionStates;
1522
1558
return ;
1523
1559
}
1524
1560
1525
1561
// / Check the current set of type witnesses.
1526
1562
bool invalid = checkCurrentTypeWitnesses (valueWitnesses);
1527
1563
1564
+ if (invalid) {
1565
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1566
+ << " + Invalid solution found\n " ;);
1567
+ } else {
1568
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1569
+ << " + Valid solution found\n " ;);
1570
+ }
1571
+
1528
1572
auto &solutionList = invalid ? nonViableSolutions : solutions;
1529
1573
solutionList.push_back (InferredTypeWitnessesSolution ());
1530
1574
auto &solution = solutionList.back ();
@@ -1583,6 +1627,12 @@ void AssociatedTypeInference::findSolutionsRec(
1583
1627
TypeWitnessesScope typeWitnessesScope (typeWitnesses);
1584
1628
1585
1629
// Record this value witness, popping it when we exit the current scope.
1630
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1631
+ << " + Pushing " ;
1632
+ inferredReq.first ->dumpRef (llvm::dbgs ());
1633
+ llvm::dbgs () << " := " ;
1634
+ witnessReq.Witness ->dumpRef (llvm::dbgs ());
1635
+ llvm::dbgs () << " \n " ;);
1586
1636
valueWitnesses.push_back ({inferredReq.first , witnessReq.Witness });
1587
1637
if (!isa<TypeDecl>(inferredReq.first ) &&
1588
1638
witnessReq.Witness ->getDeclContext ()->getExtendedProtocolDecl ())
@@ -1593,6 +1643,13 @@ void AssociatedTypeInference::findSolutionsRec(
1593
1643
--numValueWitnessesInProtocolExtensions;
1594
1644
1595
1645
valueWitnesses.pop_back ();
1646
+
1647
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1648
+ << " + Popping " ;
1649
+ inferredReq.first ->dumpRef (llvm::dbgs ());
1650
+ llvm::dbgs () << " := " ;
1651
+ witnessReq.Witness ->dumpRef (llvm::dbgs ());
1652
+ llvm::dbgs () << " \n " ;);
1596
1653
};
1597
1654
1598
1655
// Introduce each of the type witnesses into the hash table.
@@ -1637,10 +1694,20 @@ void AssociatedTypeInference::findSolutionsRec(
1637
1694
numTypeWitnessesBeforeConflict = numTypeWitnesses;
1638
1695
}
1639
1696
1697
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1698
+ << " + Failed " << typeWitness.first ->getName ()
1699
+ << " := " << typeWitness.second ->getCanonicalType ()
1700
+ << " \n " ;);
1701
+
1640
1702
failed = true ;
1641
1703
break ;
1642
1704
}
1643
1705
1706
+ LLVM_DEBUG (llvm::dbgs () << std::string (valueWitnesses.size (), ' +' )
1707
+ << " + Recording " << typeWitness.first ->getName ()
1708
+ << " := " << typeWitness.second ->getCanonicalType ()
1709
+ << " \n " ;);
1710
+
1644
1711
// Record the type witness.
1645
1712
++numTypeWitnesses;
1646
1713
typeWitnesses.insert (typeWitness.first , {typeWitness.second , reqDepth});
@@ -2224,10 +2291,20 @@ bool AssociatedTypeInference::canAttemptEagerTypeWitnessDerivation(
2224
2291
2225
2292
auto AssociatedTypeInference::solve (ConformanceChecker &checker)
2226
2293
-> llvm::Optional<InferredTypeWitnesses> {
2294
+ LLVM_DEBUG (llvm::dbgs () << " ============ Start " << conformance->getType ()
2295
+ << " : " << conformance->getProtocol ()->getName ()
2296
+ << " ============\n " ;);
2297
+
2227
2298
// Track when we are checking type witnesses.
2228
2299
ProtocolConformanceState initialState = conformance->getState ();
2229
2300
conformance->setState (ProtocolConformanceState::CheckingTypeWitnesses);
2230
- SWIFT_DEFER { conformance->setState (initialState); };
2301
+ SWIFT_DEFER {
2302
+ conformance->setState (initialState);
2303
+
2304
+ LLVM_DEBUG (llvm::dbgs () << " ============ Finish " << conformance->getType ()
2305
+ << " : " << conformance->getProtocol ()->getName ()
2306
+ << " ============\n " ;);
2307
+ };
2231
2308
2232
2309
// Try to resolve type witnesses via name lookup.
2233
2310
llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes;
@@ -2251,9 +2328,13 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
2251
2328
switch (checker.resolveTypeWitnessViaLookup (assocType)) {
2252
2329
case ResolveWitnessResult::Success:
2253
2330
// Success. Move on to the next.
2331
+ LLVM_DEBUG (llvm::dbgs () << " Associated type " << assocType->getName ()
2332
+ << " has a valid witness\n " ;);
2254
2333
continue ;
2255
2334
2256
2335
case ResolveWitnessResult::ExplicitFailed:
2336
+ LLVM_DEBUG (llvm::dbgs () << " Associated type " << assocType->getName ()
2337
+ << " has an invalid witness\n " ;);
2257
2338
continue ;
2258
2339
2259
2340
case ResolveWitnessResult::Missing:
@@ -2307,6 +2388,8 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
2307
2388
// A declaration that can become a witness has shown up. Go
2308
2389
// perform the resolution again now that we have more
2309
2390
// information.
2391
+ LLVM_DEBUG (llvm::dbgs () << " Associated type " << assocType->getName ()
2392
+ << " now has a valid witness\n " ;);
2310
2393
return solve (checker);
2311
2394
2312
2395
case ResolveWitnessResult::Missing:
@@ -2332,6 +2415,9 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
2332
2415
replacement = replacement->mapTypeOutOfContext ();
2333
2416
}
2334
2417
2418
+ LLVM_DEBUG (llvm::dbgs () << " Best witness for " << assocType->getName ()
2419
+ << " is " << replacement->getCanonicalType ()
2420
+ << " \n " ;);
2335
2421
result->push_back ({assocType, replacement});
2336
2422
}
2337
2423
@@ -2643,6 +2729,9 @@ TypeWitnessSystem::compareResolvedTypes(Type ty1, Type ty2) {
2643
2729
}
2644
2730
2645
2731
void ConformanceChecker::resolveTypeWitnesses () {
2732
+ PrettyStackTraceConformance trace (" performing associated type inference on" ,
2733
+ Conformance);
2734
+
2646
2735
// Attempt to infer associated type witnesses.
2647
2736
AssociatedTypeInference inference (getASTContext (), Conformance);
2648
2737
if (auto inferred = inference.solve (*this )) {
0 commit comments