Skip to content

Commit 0ecc8ef

Browse files
committed
Sema: Better debug output for associated type inference
1 parent 73c18fb commit 0ecc8ef

File tree

2 files changed

+98
-8
lines changed

2 files changed

+98
-8
lines changed

lib/AST/PrettyStackTrace.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,11 @@ void swift::printConformanceDescription(llvm::raw_ostream &out,
273273
return;
274274
}
275275

276-
out << "protocol conformance to ";
277-
printDeclDescription(out, conformance->getProtocol(), /*newline*/false);
278-
out << " for ";
279-
printTypeDescription(out, conformance->getType(), ctxt, addNewline);
276+
out << "protocol conformance "
277+
<< conformance->getType() << ": "
278+
<< conformance->getProtocol()->getName() << " at ";
279+
auto *decl = conformance->getDeclContext()->getInnermostDeclarationDeclContext();
280+
printDeclDescription(out, decl, addNewline);
280281
}
281282

282283
void swift::printSourceLocDescription(llvm::raw_ostream &out,

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/Decl.h"
2121
#include "swift/AST/GenericSignature.h"
2222
#include "swift/AST/NameLookupRequests.h"
23+
#include "swift/AST/PrettyStackTrace.h"
2324
#include "swift/AST/ProtocolConformance.h"
2425
#include "swift/AST/SubstitutionMap.h"
2526
#include "swift/AST/TypeMatcher.h"
@@ -1161,6 +1162,8 @@ bool AssociatedTypeInference::checkCurrentTypeWitnesses(
11611162
QuerySubstitutionMap{substitutions}, options)) {
11621163
case CheckGenericArgumentsResult::RequirementFailure:
11631164
++NumSolutionStatesFailedCheck;
1165+
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
1166+
<< "+ Requirement failure\n";);
11641167
return true;
11651168

11661169
case CheckGenericArgumentsResult::Success:
@@ -1186,6 +1189,9 @@ bool AssociatedTypeInference::checkCurrentTypeWitnesses(
11861189

11871190
++NumConstrainedExtensionChecks;
11881191
if (checkConstrainedExtension(ext)) {
1192+
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
1193+
<< "+ Constrained extension failed: " <<
1194+
ext->getExtendedType() << "\n";);
11891195
++NumConstrainedExtensionChecksFailed;
11901196
return true;
11911197
}
@@ -1432,6 +1438,22 @@ void AssociatedTypeInference::findSolutions(
14321438
SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> valueWitnesses;
14331439
findSolutionsRec(unresolvedAssocTypes, solutions, nonViableSolutions,
14341440
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+
}
14351457
}
14361458

14371459
void AssociatedTypeInference::findSolutionsRec(
@@ -1462,6 +1484,8 @@ void AssociatedTypeInference::findSolutionsRec(
14621484
if (!missingTypeWitness)
14631485
missingTypeWitness = assocType;
14641486

1487+
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
1488+
<< "+ Recorded an erroneous type witness\n";);
14651489
return;
14661490
}
14671491
}
@@ -1476,6 +1500,8 @@ void AssociatedTypeInference::findSolutionsRec(
14761500
if (!missingTypeWitness)
14771501
missingTypeWitness = assocType;
14781502

1503+
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
1504+
<< "+ Failed to infer abstract witnesses\n";);
14791505
return;
14801506
}
14811507

@@ -1496,8 +1522,11 @@ void AssociatedTypeInference::findSolutionsRec(
14961522
continue;
14971523

14981524
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";);
15001528
return;
1529+
}
15011530

15021531
known->first = replaced;
15031532
}
@@ -1516,15 +1545,30 @@ void AssociatedTypeInference::findSolutionsRec(
15161545

15171546
// If we've seen this solution already, bail out; there's no point in
15181547
// 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";);
15211557
++NumDuplicateSolutionStates;
15221558
return;
15231559
}
15241560

15251561
/// Check the current set of type witnesses.
15261562
bool invalid = checkCurrentTypeWitnesses(valueWitnesses);
15271563

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+
15281572
auto &solutionList = invalid ? nonViableSolutions : solutions;
15291573
solutionList.push_back(InferredTypeWitnessesSolution());
15301574
auto &solution = solutionList.back();
@@ -1583,6 +1627,12 @@ void AssociatedTypeInference::findSolutionsRec(
15831627
TypeWitnessesScope typeWitnessesScope(typeWitnesses);
15841628

15851629
// 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";);
15861636
valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
15871637
if (!isa<TypeDecl>(inferredReq.first) &&
15881638
witnessReq.Witness->getDeclContext()->getExtendedProtocolDecl())
@@ -1593,6 +1643,13 @@ void AssociatedTypeInference::findSolutionsRec(
15931643
--numValueWitnessesInProtocolExtensions;
15941644

15951645
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";);
15961653
};
15971654

15981655
// Introduce each of the type witnesses into the hash table.
@@ -1637,10 +1694,20 @@ void AssociatedTypeInference::findSolutionsRec(
16371694
numTypeWitnessesBeforeConflict = numTypeWitnesses;
16381695
}
16391696

1697+
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
1698+
<< "+ Failed " << typeWitness.first->getName()
1699+
<< " := " << typeWitness.second->getCanonicalType()
1700+
<< "\n";);
1701+
16401702
failed = true;
16411703
break;
16421704
}
16431705

1706+
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
1707+
<< "+ Recording " << typeWitness.first->getName()
1708+
<< " := " << typeWitness.second->getCanonicalType()
1709+
<< "\n";);
1710+
16441711
// Record the type witness.
16451712
++numTypeWitnesses;
16461713
typeWitnesses.insert(typeWitness.first, {typeWitness.second, reqDepth});
@@ -2224,10 +2291,20 @@ bool AssociatedTypeInference::canAttemptEagerTypeWitnessDerivation(
22242291

22252292
auto AssociatedTypeInference::solve(ConformanceChecker &checker)
22262293
-> llvm::Optional<InferredTypeWitnesses> {
2294+
LLVM_DEBUG(llvm::dbgs() << "============ Start " << conformance->getType()
2295+
<< ": " << conformance->getProtocol()->getName()
2296+
<< " ============\n";);
2297+
22272298
// Track when we are checking type witnesses.
22282299
ProtocolConformanceState initialState = conformance->getState();
22292300
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+
};
22312308

22322309
// Try to resolve type witnesses via name lookup.
22332310
llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes;
@@ -2251,9 +2328,13 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
22512328
switch (checker.resolveTypeWitnessViaLookup(assocType)) {
22522329
case ResolveWitnessResult::Success:
22532330
// Success. Move on to the next.
2331+
LLVM_DEBUG(llvm::dbgs() << "Associated type " << assocType->getName()
2332+
<< " has a valid witness\n";);
22542333
continue;
22552334

22562335
case ResolveWitnessResult::ExplicitFailed:
2336+
LLVM_DEBUG(llvm::dbgs() << "Associated type " << assocType->getName()
2337+
<< " has an invalid witness\n";);
22572338
continue;
22582339

22592340
case ResolveWitnessResult::Missing:
@@ -2307,6 +2388,8 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
23072388
// A declaration that can become a witness has shown up. Go
23082389
// perform the resolution again now that we have more
23092390
// information.
2391+
LLVM_DEBUG(llvm::dbgs() << "Associated type " << assocType->getName()
2392+
<< " now has a valid witness\n";);
23102393
return solve(checker);
23112394

23122395
case ResolveWitnessResult::Missing:
@@ -2332,6 +2415,9 @@ auto AssociatedTypeInference::solve(ConformanceChecker &checker)
23322415
replacement = replacement->mapTypeOutOfContext();
23332416
}
23342417

2418+
LLVM_DEBUG(llvm::dbgs() << "Best witness for " << assocType->getName()
2419+
<< " is " << replacement->getCanonicalType()
2420+
<< "\n";);
23352421
result->push_back({assocType, replacement});
23362422
}
23372423

@@ -2643,6 +2729,9 @@ TypeWitnessSystem::compareResolvedTypes(Type ty1, Type ty2) {
26432729
}
26442730

26452731
void ConformanceChecker::resolveTypeWitnesses() {
2732+
PrettyStackTraceConformance trace("performing associated type inference on",
2733+
Conformance);
2734+
26462735
// Attempt to infer associated type witnesses.
26472736
AssociatedTypeInference inference(getASTContext(), Conformance);
26482737
if (auto inferred = inference.solve(*this)) {

0 commit comments

Comments
 (0)