@@ -1115,80 +1115,93 @@ bool ConstraintSystem::solve(Expr *&expr,
1115
1115
getASTContext ().TypeCheckerOpts .DebugConstraintSolver ,
1116
1116
debugConstraintSolverForExpr (getASTContext (), expr));
1117
1117
1118
- // Attempt to solve the constraint system.
1119
- auto solution = solveImpl (expr,
1120
- convertType,
1121
- listener,
1122
- solutions,
1123
- allowFreeTypeVariables);
1124
-
1125
- // The constraint system has failed
1126
- if (solution == SolutionKind::Error)
1127
- return true ;
1128
-
1129
- // If the system is unsolved or there are multiple solutions present but
1130
- // type checker options do not allow unresolved types, let's try to salvage
1131
- if (solution == SolutionKind::Unsolved ||
1132
- (solutions.size () != 1 &&
1133
- !Options.contains (
1134
- ConstraintSystemFlags::AllowUnresolvedTypeVariables))) {
1135
- if (shouldSuppressDiagnostics ())
1136
- return true ;
1118
+ // / Dump solutions for debugging purposes.
1119
+ auto dumpSolutions = [&] {
1120
+ // Debug-print the set of solutions.
1121
+ if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
1122
+ auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
1123
+ if (solutions.size () == 1 ) {
1124
+ log << " ---Solution---\n " ;
1125
+ solutions[0 ].dump (log);
1126
+ } else {
1127
+ for (unsigned i = 0 , e = solutions.size (); i != e; ++i) {
1128
+ log << " --- Solution #" << i << " ---\n " ;
1129
+ solutions[i].dump (log);
1130
+ }
1131
+ }
1132
+ }
1133
+ };
1137
1134
1138
- // Try to fix the system or provide a decent diagnostic.
1139
- auto salvagedResult = salvage ();
1140
- switch (salvagedResult.getKind ()) {
1141
- case SolutionResult::Kind::Success:
1135
+ // Take up to two attempts at solving the system. The first attempts to
1136
+ // solve a system that is expected to be well-formed, the second kicks in
1137
+ // when there is an error and attempts to salvage an ill-formed expression.
1138
+ for (unsigned stage = 0 ; stage != 2 ; ++stage) {
1139
+ auto solution = (stage == 0 )
1140
+ ? solveImpl (expr, convertType, listener, allowFreeTypeVariables)
1141
+ : salvage ();
1142
+
1143
+ switch (solution.getKind ()) {
1144
+ case SolutionResult::Success:
1145
+ // Return the successful solution.
1142
1146
solutions.clear ();
1143
- solutions.push_back (std::move (salvagedResult).takeSolution ());
1144
- break ;
1145
-
1146
- case SolutionResult::Kind::Error:
1147
- case SolutionResult::Kind::Ambiguous:
1148
- return true ;
1147
+ solutions.push_back (std::move (solution).takeSolution ());
1148
+ dumpSolutions ();
1149
+ return false ;
1149
1150
1150
- case SolutionResult::Kind::UndiagnosedError:
1151
- diagnoseFailureFor (expr);
1152
- salvagedResult.markAsDiagnosed ();
1151
+ case SolutionResult::Error:
1153
1152
return true ;
1154
1153
1155
- case SolutionResult::Kind:: TooComplex:
1154
+ case SolutionResult::TooComplex:
1156
1155
getASTContext ().Diags .diagnose (expr->getLoc (), diag::expression_too_complex)
1157
- .highlight (expr->getSourceRange ());
1158
- salvagedResult .markAsDiagnosed ();
1156
+ .highlight (expr->getSourceRange ());
1157
+ solution .markAsDiagnosed ();
1159
1158
return true ;
1160
- }
1161
1159
1162
- // The system was salvaged; continue on as if nothing happened.
1163
- }
1160
+ case SolutionResult::Ambiguous:
1161
+ // If salvaging produced an ambiguous result, it has already been
1162
+ // diagnosed.
1163
+ if (stage == 1 ) {
1164
+ solution.markAsDiagnosed ();
1165
+ return true ;
1166
+ }
1164
1167
1165
- if (getExpressionTooComplex (solutions)) {
1166
- getASTContext ().Diags .diagnose (expr->getLoc (), diag::expression_too_complex)
1167
- .highlight (expr->getSourceRange ());
1168
- return true ;
1169
- }
1168
+ if (Options.contains (
1169
+ ConstraintSystemFlags::AllowUnresolvedTypeVariables)) {
1170
+ auto ambiguousSolutions = std::move (solution).takeAmbiguousSolutions ();
1171
+ solutions.assign (std::make_move_iterator (ambiguousSolutions.begin ()),
1172
+ std::make_move_iterator (ambiguousSolutions.end ()));
1173
+ dumpSolutions ();
1174
+ solution.markAsDiagnosed ();
1175
+ return false ;
1176
+ }
1170
1177
1171
- if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
1172
- auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
1173
- if (solutions.size () == 1 ) {
1174
- log << " ---Solution---\n " ;
1175
- solutions[0 ].dump (log);
1176
- } else {
1177
- for (unsigned i = 0 , e = solutions.size (); i != e; ++i) {
1178
- log << " --- Solution #" << i << " ---\n " ;
1179
- solutions[i].dump (log);
1178
+ LLVM_FALLTHROUGH;
1179
+
1180
+ case SolutionResult::UndiagnosedError:
1181
+ if (shouldSuppressDiagnostics ()) {
1182
+ solution.markAsDiagnosed ();
1183
+ return true ;
1184
+ }
1185
+
1186
+ if (stage == 1 ) {
1187
+ diagnoseFailureFor (expr);
1188
+ solution.markAsDiagnosed ();
1189
+ return true ;
1180
1190
}
1191
+
1192
+ // Loop again to try to salvage.
1193
+ solution.markAsDiagnosed ();
1194
+ continue ;
1181
1195
}
1182
1196
}
1183
1197
1184
- return false ;
1198
+ llvm_unreachable ( " Loop always returns " ) ;
1185
1199
}
1186
1200
1187
- ConstraintSystem::SolutionKind
1201
+ SolutionResult
1188
1202
ConstraintSystem::solveImpl (Expr *&expr,
1189
1203
Type convertType,
1190
1204
ExprTypeCheckListener *listener,
1191
- SmallVectorImpl<Solution> &solutions,
1192
1205
FreeTypeVariableBinding allowFreeTypeVariables) {
1193
1206
if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
1194
1207
auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
@@ -1220,7 +1233,7 @@ ConstraintSystem::solveImpl(Expr *&expr,
1220
1233
else {
1221
1234
if (listener)
1222
1235
listener->constraintGenerationFailed (expr);
1223
- return SolutionKind::Error ;
1236
+ return SolutionResult::forError () ;
1224
1237
}
1225
1238
1226
1239
// If there is a type that we're expected to convert to, add the conversion
@@ -1247,7 +1260,7 @@ ConstraintSystem::solveImpl(Expr *&expr,
1247
1260
1248
1261
// Notify the listener that we've built the constraint system.
1249
1262
if (listener && listener->builtConstraints (*this , expr)) {
1250
- return SolutionKind::Error ;
1263
+ return SolutionResult::forError () ;
1251
1264
}
1252
1265
1253
1266
if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
@@ -1259,11 +1272,22 @@ ConstraintSystem::solveImpl(Expr *&expr,
1259
1272
}
1260
1273
1261
1274
// Try to solve the constraint system using computed suggestions.
1275
+ SmallVector<Solution, 4 > solutions;
1262
1276
solve (solutions, allowFreeTypeVariables);
1263
1277
1264
- // If there are no solutions let's mark system as unsolved,
1265
- // and solved otherwise even if there are multiple solutions still present.
1266
- return solutions.empty () ? SolutionKind::Unsolved : SolutionKind::Solved;
1278
+ if (getExpressionTooComplex (solutions))
1279
+ return SolutionResult::forTooComplex ();
1280
+
1281
+ switch (solutions.size ()) {
1282
+ case 0 :
1283
+ return SolutionResult::forUndiagnosedError ();
1284
+
1285
+ case 1 :
1286
+ return SolutionResult::forSolved (std::move (solutions.front ()));
1287
+
1288
+ default :
1289
+ return SolutionResult::forAmbiguous (solutions);
1290
+ }
1267
1291
}
1268
1292
1269
1293
bool ConstraintSystem::solve (SmallVectorImpl<Solution> &solutions,
0 commit comments