@@ -240,7 +240,8 @@ void ConstraintSystem::applySolution(const Solution &solution) {
240
240
for (const auto &contextualType : solution.contextualTypes ) {
241
241
if (!getContextualTypeInfo (contextualType.first )) {
242
242
setContextualType (contextualType.first , contextualType.second .typeLoc ,
243
- contextualType.second .purpose );
243
+ contextualType.second .purpose ,
244
+ contextualType.second .isOpaqueReturnType );
244
245
}
245
246
}
246
247
@@ -591,7 +592,7 @@ bool ConstraintSystem::Candidate::solve(
591
592
cs.Timer .emplace (E, cs);
592
593
593
594
// Generate constraints for the new system.
594
- if (auto generatedExpr = cs.generateConstraints (E)) {
595
+ if (auto generatedExpr = cs.generateConstraints (E, DC )) {
595
596
E = generatedExpr;
596
597
} else {
597
598
// Failure to generate constraint system for sub-expression
@@ -1115,80 +1116,93 @@ bool ConstraintSystem::solve(Expr *&expr,
1115
1116
getASTContext ().TypeCheckerOpts .DebugConstraintSolver ,
1116
1117
debugConstraintSolverForExpr (getASTContext (), expr));
1117
1118
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 ;
1119
+ // / Dump solutions for debugging purposes.
1120
+ auto dumpSolutions = [&] {
1121
+ // Debug-print the set of solutions.
1122
+ if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
1123
+ auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
1124
+ if (solutions.size () == 1 ) {
1125
+ log << " ---Solution---\n " ;
1126
+ solutions[0 ].dump (log );
1127
+ } else {
1128
+ for (unsigned i = 0 , e = solutions.size (); i != e; ++i) {
1129
+ log << " --- Solution #" << i << " ---\n " ;
1130
+ solutions[i].dump (log );
1131
+ }
1132
+ }
1133
+ }
1134
+ };
1137
1135
1138
- // Try to fix the system or provide a decent diagnostic.
1139
- auto salvagedResult = salvage ();
1140
- switch (salvagedResult.getKind ()) {
1141
- case SolutionResult::Kind::Success:
1136
+ // Take up to two attempts at solving the system. The first attempts to
1137
+ // solve a system that is expected to be well-formed, the second kicks in
1138
+ // when there is an error and attempts to salvage an ill-formed expression.
1139
+ for (unsigned stage = 0 ; stage != 2 ; ++stage) {
1140
+ auto solution = (stage == 0 )
1141
+ ? solveImpl (expr, convertType, listener, allowFreeTypeVariables)
1142
+ : salvage ();
1143
+
1144
+ switch (solution.getKind ()) {
1145
+ case SolutionResult::Success:
1146
+ // Return the successful solution.
1142
1147
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 ;
1148
+ solutions.push_back (std::move (solution).takeSolution ());
1149
+ dumpSolutions ();
1150
+ return false ;
1149
1151
1150
- case SolutionResult::Kind::UndiagnosedError:
1151
- diagnoseFailureFor (expr);
1152
- salvagedResult.markAsDiagnosed ();
1152
+ case SolutionResult::Error:
1153
1153
return true ;
1154
1154
1155
- case SolutionResult::Kind:: TooComplex:
1155
+ case SolutionResult::TooComplex:
1156
1156
getASTContext ().Diags .diagnose (expr->getLoc (), diag::expression_too_complex)
1157
- .highlight (expr->getSourceRange ());
1158
- salvagedResult .markAsDiagnosed ();
1157
+ .highlight (expr->getSourceRange ());
1158
+ solution .markAsDiagnosed ();
1159
1159
return true ;
1160
- }
1161
1160
1162
- // The system was salvaged; continue on as if nothing happened.
1163
- }
1161
+ case SolutionResult::Ambiguous:
1162
+ // If salvaging produced an ambiguous result, it has already been
1163
+ // diagnosed.
1164
+ if (stage == 1 ) {
1165
+ solution.markAsDiagnosed ();
1166
+ return true ;
1167
+ }
1164
1168
1165
- if (getExpressionTooComplex (solutions)) {
1166
- getASTContext ().Diags .diagnose (expr->getLoc (), diag::expression_too_complex)
1167
- .highlight (expr->getSourceRange ());
1168
- return true ;
1169
- }
1169
+ if (Options.contains (
1170
+ ConstraintSystemFlags::AllowUnresolvedTypeVariables)) {
1171
+ auto ambiguousSolutions = std::move (solution).takeAmbiguousSolutions ();
1172
+ solutions.assign (std::make_move_iterator (ambiguousSolutions.begin ()),
1173
+ std::make_move_iterator (ambiguousSolutions.end ()));
1174
+ dumpSolutions ();
1175
+ solution.markAsDiagnosed ();
1176
+ return false ;
1177
+ }
1170
1178
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 );
1179
+ LLVM_FALLTHROUGH;
1180
+
1181
+ case SolutionResult::UndiagnosedError:
1182
+ if (shouldSuppressDiagnostics ()) {
1183
+ solution.markAsDiagnosed ();
1184
+ return true ;
1185
+ }
1186
+
1187
+ if (stage == 1 ) {
1188
+ diagnoseFailureFor (expr);
1189
+ solution.markAsDiagnosed ();
1190
+ return true ;
1180
1191
}
1192
+
1193
+ // Loop again to try to salvage.
1194
+ solution.markAsDiagnosed ();
1195
+ continue ;
1181
1196
}
1182
1197
}
1183
1198
1184
- return false ;
1199
+ llvm_unreachable ( " Loop always returns " ) ;
1185
1200
}
1186
1201
1187
- ConstraintSystem::SolutionKind
1202
+ SolutionResult
1188
1203
ConstraintSystem::solveImpl (Expr *&expr,
1189
1204
Type convertType,
1190
1205
ExprTypeCheckListener *listener,
1191
- SmallVectorImpl<Solution> &solutions,
1192
1206
FreeTypeVariableBinding allowFreeTypeVariables) {
1193
1207
if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
1194
1208
auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
@@ -1215,53 +1229,46 @@ ConstraintSystem::solveImpl(Expr *&expr,
1215
1229
shrink (expr);
1216
1230
1217
1231
// Generate constraints for the main system.
1218
- if (auto generatedExpr = generateConstraints (expr))
1232
+ if (auto generatedExpr = generateConstraints (expr, DC ))
1219
1233
expr = generatedExpr;
1220
1234
else {
1221
1235
if (listener)
1222
1236
listener->constraintGenerationFailed (expr);
1223
- return SolutionKind::Error ;
1237
+ return SolutionResult::forError () ;
1224
1238
}
1225
1239
1226
1240
// If there is a type that we're expected to convert to, add the conversion
1227
1241
// constraint.
1228
1242
if (convertType) {
1229
- auto constraintKind = ConstraintKind::Conversion;
1230
-
1231
- auto ctp = getContextualTypePurpose (origExpr);
1232
- if ((ctp == CTP_ReturnStmt ||
1233
- ctp == CTP_ReturnSingleExpr ||
1234
- ctp == CTP_Initialization)
1235
- && Options.contains (ConstraintSystemFlags::UnderlyingTypeForOpaqueReturnType))
1236
- constraintKind = ConstraintKind::OpaqueUnderlyingType;
1237
-
1238
- if (ctp == CTP_CallArgument)
1239
- constraintKind = ConstraintKind::ArgumentConversion;
1240
-
1241
- // In a by-reference yield, we expect the contextual type to be an
1242
- // l-value type, so the result must be bound to that.
1243
- if (ctp == CTP_YieldByReference)
1244
- constraintKind = ConstraintKind::Bind;
1245
-
1246
- bool isForSingleExprFunction = ctp == CTP_ReturnSingleExpr;
1247
- auto *convertTypeLocator = getConstraintLocator (
1248
- expr, LocatorPathElt::ContextualType (isForSingleExprFunction));
1243
+ // Determine whether we know more about the contextual type.
1244
+ ContextualTypePurpose ctp = CTP_Unused;
1245
+ bool isOpaqueReturnType = false ;
1246
+ if (auto contextualInfo = getContextualTypeInfo (origExpr)) {
1247
+ ctp = contextualInfo->purpose ;
1248
+ isOpaqueReturnType = contextualInfo->isOpaqueReturnType ;
1249
+ }
1249
1250
1251
+ // Substitute type variables in for unresolved types.
1250
1252
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
1253
+ bool isForSingleExprFunction = (ctp == CTP_ReturnSingleExpr);
1254
+ auto *convertTypeLocator = getConstraintLocator (
1255
+ expr, LocatorPathElt::ContextualType (isForSingleExprFunction));
1256
+
1251
1257
convertType = convertType.transform ([&](Type type) -> Type {
1252
1258
if (type->is <UnresolvedType>())
1253
1259
return createTypeVariable (convertTypeLocator, TVO_CanBindToNoEscape);
1254
1260
return type;
1255
1261
});
1256
1262
}
1257
1263
1258
- addConstraint (constraintKind, getType (expr), convertType,
1259
- convertTypeLocator, /* isFavored*/ true );
1264
+ ContextualTypeInfo info{
1265
+ TypeLoc::withoutLoc (convertType), ctp, isOpaqueReturnType};
1266
+ addContextualConversionConstraint (expr, info);
1260
1267
}
1261
1268
1262
1269
// Notify the listener that we've built the constraint system.
1263
1270
if (listener && listener->builtConstraints (*this , expr)) {
1264
- return SolutionKind::Error ;
1271
+ return SolutionResult::forError () ;
1265
1272
}
1266
1273
1267
1274
if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
@@ -1273,11 +1280,22 @@ ConstraintSystem::solveImpl(Expr *&expr,
1273
1280
}
1274
1281
1275
1282
// Try to solve the constraint system using computed suggestions.
1283
+ SmallVector<Solution, 4 > solutions;
1276
1284
solve (solutions, allowFreeTypeVariables);
1277
1285
1278
- // If there are no solutions let's mark system as unsolved,
1279
- // and solved otherwise even if there are multiple solutions still present.
1280
- return solutions.empty () ? SolutionKind::Unsolved : SolutionKind::Solved;
1286
+ if (getExpressionTooComplex (solutions))
1287
+ return SolutionResult::forTooComplex ();
1288
+
1289
+ switch (solutions.size ()) {
1290
+ case 0 :
1291
+ return SolutionResult::forUndiagnosedError ();
1292
+
1293
+ case 1 :
1294
+ return SolutionResult::forSolved (std::move (solutions.front ()));
1295
+
1296
+ default :
1297
+ return SolutionResult::forAmbiguous (solutions);
1298
+ }
1281
1299
}
1282
1300
1283
1301
bool ConstraintSystem::solve (SmallVectorImpl<Solution> &solutions,
0 commit comments