Skip to content

Commit 42135e2

Browse files
authored
Merge pull request #60387 from amritpan/improve-solution-printing
[ConstraintSystem] Improve solution printing in the type inference algorithm debug output
2 parents 4ebae53 + 207f1ee commit 42135e2

File tree

11 files changed

+238
-172
lines changed

11 files changed

+238
-172
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,10 @@ struct AppliedBuilderTransform {
946946
Expr *returnExpr = nullptr;
947947
};
948948

949+
struct Score;
950+
/// Display a score.
951+
llvm::raw_ostream &operator<<(llvm::raw_ostream &out, const Score &score);
952+
949953
/// Describes the fixed score of a solution to the constraint system.
950954
struct Score {
951955
unsigned Data[NumScoreKinds] = {};
@@ -1016,11 +1020,94 @@ struct Score {
10161020
friend bool operator>=(const Score &x, const Score &y) {
10171021
return !(x < y);
10181022
}
1023+
1024+
/// Return ScoreKind descriptions for printing alongside non-zero ScoreKinds
1025+
/// in debug output.
1026+
static std::string getNameFor(ScoreKind kind) {
1027+
switch (kind) {
1028+
case SK_Hole:
1029+
return "hole";
10191030

1020-
};
1031+
case SK_Unavailable:
1032+
return "use of an unavailable declaration";
10211033

1022-
/// Display a score.
1023-
llvm::raw_ostream &operator<<(llvm::raw_ostream &out, const Score &score);
1034+
case SK_AsyncInSyncMismatch:
1035+
return "async-in-synchronous mismatch";
1036+
1037+
case SK_SyncInAsync:
1038+
return "sync-in-asynchronous";
1039+
1040+
case SK_ForwardTrailingClosure:
1041+
return "forward scan when matching a trailing closure";
1042+
1043+
case SK_Fix:
1044+
return "applied fix";
1045+
1046+
case SK_DisfavoredOverload:
1047+
return "disfavored overload";
1048+
1049+
case SK_UnresolvedMemberViaOptional:
1050+
return "unwrapping optional at unresolved member base";
1051+
1052+
case SK_ForceUnchecked:
1053+
return "force of an implicitly unwrapped optional";
1054+
1055+
case SK_UserConversion:
1056+
return "user conversion";
1057+
1058+
case SK_FunctionConversion:
1059+
return "function conversion";
1060+
1061+
case SK_NonDefaultLiteral:
1062+
return "non-default literal";
1063+
1064+
case SK_CollectionUpcastConversion:
1065+
return "collection upcast conversion";
1066+
1067+
case SK_ValueToOptional:
1068+
return "value to optional promotion";
1069+
1070+
case SK_EmptyExistentialConversion:
1071+
return "empty-existential conversion";
1072+
1073+
case SK_KeyPathSubscript:
1074+
return "key path subscript";
1075+
1076+
case SK_ValueToPointerConversion:
1077+
return "value-to-pointer conversion";
1078+
1079+
case SK_FunctionToAutoClosureConversion:
1080+
return "function to autoclosure parameter conversion";
1081+
1082+
case SK_ImplicitValueConversion:
1083+
return "value-to-value conversion";
1084+
1085+
case SK_UnappliedFunction:
1086+
return "use of overloaded unapplied function";
1087+
}
1088+
}
1089+
1090+
/// Print Score list a with brief description of any non-zero ScoreKinds.
1091+
void print(llvm::raw_ostream &out) const {
1092+
bool hasNonDefault = false;
1093+
for (unsigned int i = 0; i < NumScoreKinds; ++i) {
1094+
if (Data[i] != 0) {
1095+
out << " [";
1096+
out << getNameFor(ScoreKind(i));
1097+
out << "(s) = ";
1098+
out << std::to_string(Data[i]);
1099+
out << "]";
1100+
hasNonDefault = true;
1101+
}
1102+
}
1103+
1104+
if (!hasNonDefault) {
1105+
out << " <default ";
1106+
out << *this;
1107+
out << ">";
1108+
}
1109+
}
1110+
};
10241111

10251112
/// Describes a dependent type that has been opened to a particular type
10261113
/// variable.

include/swift/Sema/OverloadChoice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ class OverloadChoice {
310310
assert(isDecl() && "only makes sense for declaration choices");
311311
return TheFunctionRefKind;
312312
}
313+
314+
/// Print selected overload choice kind found for Solution in debug output.
315+
void dump(Type adjustedOpenedType, SourceManager *sm, raw_ostream &out) const;
313316
};
314317

315318
} // end namespace constraints

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9124,9 +9124,9 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
91249124

91259125
auto &log = llvm::errs();
91269126
if (isPartial) {
9127-
log << "---Partially type-checked expression---\n";
9127+
log << "\n---Partially type-checked expression---\n";
91289128
} else {
9129-
log << "---Type-checked expression---\n";
9129+
log << "\n---Type-checked expression---\n";
91309130
}
91319131
resultExpr->dump(log);
91329132
log << "\n";
@@ -9204,7 +9204,7 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
92049204
auto node = target.getAsASTNode();
92059205
if (node && needsPostProcessing) {
92069206
auto &log = llvm::errs();
9207-
log << "---Fully type-checked target---\n";
9207+
log << "\n---Fully type-checked target---\n";
92089208
node.dump(log);
92099209
log << "\n";
92109210
}

lib/Sema/CSRanking.cpp

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -32,70 +32,6 @@ using namespace constraints;
3232
#define DEBUG_TYPE "Constraint solver overall"
3333
STATISTIC(NumDiscardedSolutions, "Number of solutions discarded");
3434

35-
static StringRef getScoreKindName(ScoreKind kind) {
36-
switch (kind) {
37-
case SK_Hole:
38-
return "hole in the constraint system";
39-
40-
case SK_Unavailable:
41-
return "use of an unavailable declaration";
42-
43-
case SK_AsyncInSyncMismatch:
44-
return "async-in-synchronous mismatch";
45-
46-
case SK_SyncInAsync:
47-
return "sync-in-asynchronous";
48-
49-
case SK_ForwardTrailingClosure:
50-
return "forward scan when matching a trailing closure";
51-
52-
case SK_Fix:
53-
return "attempting to fix the source";
54-
55-
case SK_DisfavoredOverload:
56-
return "disfavored overload";
57-
58-
case SK_UnresolvedMemberViaOptional:
59-
return "unwrapping optional at unresolved member base";
60-
61-
case SK_ForceUnchecked:
62-
return "force of an implicitly unwrapped optional";
63-
64-
case SK_UserConversion:
65-
return "user conversion";
66-
67-
case SK_FunctionConversion:
68-
return "function conversion";
69-
70-
case SK_NonDefaultLiteral:
71-
return "non-default literal";
72-
73-
case SK_CollectionUpcastConversion:
74-
return "collection upcast conversion";
75-
76-
case SK_ValueToOptional:
77-
return "value to optional";
78-
79-
case SK_EmptyExistentialConversion:
80-
return "empty-existential conversion";
81-
82-
case SK_KeyPathSubscript:
83-
return "key path subscript";
84-
85-
case SK_ValueToPointerConversion:
86-
return "value-to-pointer conversion";
87-
88-
case SK_FunctionToAutoClosureConversion:
89-
return "function to autoclosure parameter";
90-
91-
case SK_ImplicitValueConversion:
92-
return "value-to-value conversion";
93-
94-
case SK_UnappliedFunction:
95-
return "overloaded unapplied function";
96-
}
97-
}
98-
9935
void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
10036
if (isForCodeCompletion()) {
10137
switch (kind) {
@@ -119,7 +55,8 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
11955
if (isDebugMode() && value > 0) {
12056
if (solverState)
12157
llvm::errs().indent(solverState->depth * 2);
122-
llvm::errs() << "(increasing score due to " << getScoreKindName(kind) << ")\n";
58+
llvm::errs() << "(increasing '" << Score::getNameFor(kind) << "' score by " << value
59+
<< ")\n";
12360
}
12461

12562
unsigned index = static_cast<unsigned>(kind);
@@ -1420,7 +1357,7 @@ ConstraintSystem::findBestSolution(SmallVectorImpl<Solution> &viable,
14201357

14211358
for (unsigned i = 0, n = viable.size(); i != n; ++i) {
14221359
llvm::errs().indent(solverState->depth * 2)
1423-
<< "--- Solution #" << i << " ---\n";
1360+
<< "\n--- Solution #" << i << " ---\n";
14241361
viable[i].dump(llvm::errs().indent(solverState->depth * 2));
14251362
}
14261363
}

lib/Sema/CSSolver.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ bool ConstraintSystem::Candidate::solve(
790790
log << "--- Solutions ---\n";
791791
for (unsigned i = 0, n = solutions.size(); i != n; ++i) {
792792
auto &solution = solutions[i];
793-
log << "--- Solution #" << i << " ---\n";
793+
log << "\n--- Solution #" << i << " ---\n";
794794
solution.dump(log);
795795
}
796796
}
@@ -1275,12 +1275,12 @@ Optional<std::vector<Solution>> ConstraintSystem::solve(
12751275
// Debug-print the set of solutions.
12761276
if (isDebugMode()) {
12771277
if (result.getKind() == SolutionResult::Success) {
1278-
llvm::errs() << "---Solution---\n";
1278+
llvm::errs() << "\n---Solution---\n";
12791279
result.getSolution().dump(llvm::errs());
12801280
} else if (result.getKind() == SolutionResult::Ambiguous) {
12811281
auto solutions = result.getAmbiguousSolutions();
12821282
for (unsigned i : indices(solutions)) {
1283-
llvm::errs() << "--- Solution #" << i << " ---\n";
1283+
llvm::errs() << "\n--- Solution #" << i << " ---\n";
12841284
solutions[i].dump(llvm::errs());
12851285
}
12861286
}
@@ -1418,7 +1418,7 @@ bool ConstraintSystem::solve(SmallVectorImpl<Solution> &solutions,
14181418

14191419
if (isDebugMode()) {
14201420
auto &log = llvm::errs();
1421-
log << "---Solver statistics---\n";
1421+
log << "\n---Solver statistics---\n";
14221422
log << "Total number of scopes explored: " << solverState->NumStatesExplored << "\n";
14231423
log << "Maximum depth reached while exploring solutions: " << solverState->maxDepth << "\n";
14241424
if (Timer) {

lib/Sema/CSStep.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,12 @@ bool SplitterStep::mergePartialSolutions() const {
241241
// Finalize this solution.
242242
auto solution = CS.finalize();
243243
solutionMemory += solution.getTotalMemory();
244-
if (CS.isDebugMode())
245-
getDebugLogger() << "(composed solution " << CS.CurrentScore << ")\n";
244+
if (CS.isDebugMode()) {
245+
auto &log = getDebugLogger();
246+
log << "(composed solution:";
247+
CS.CurrentScore.print(log);
248+
log << ")\n";
249+
}
246250

247251
// Save this solution.
248252
Solutions.push_back(std::move(solution));
@@ -429,8 +433,12 @@ StepResult ComponentStep::take(bool prevFailed) {
429433
}
430434

431435
auto solution = CS.finalize();
432-
if (CS.isDebugMode())
433-
getDebugLogger() << "(found solution " << getCurrentScore() << ")\n";
436+
if (CS.isDebugMode()) {
437+
auto &log = getDebugLogger();
438+
log << "(found solution:";
439+
getCurrentScore().print(log);
440+
log << ")\n";
441+
}
434442

435443
Solutions.push_back(std::move(solution));
436444
return finalize(/*isSuccess=*/true);

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4624,7 +4624,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
46244624
<< " solutions with fixes ---\n";
46254625
int i = 0;
46264626
for (auto &solution : solutions) {
4627-
log << "--- Solution #" << i++ << "---\n";
4627+
log << "\n--- Solution #" << i++ << "---\n";
46284628
solution.dump(log);
46294629
log << "\n";
46304630
}

0 commit comments

Comments
 (0)