@@ -240,7 +240,8 @@ void ConstraintSystem::applySolution(const Solution &solution) {
240240 for (const auto &contextualType : solution.contextualTypes ) {
241241 if (!getContextualTypeInfo (contextualType.first )) {
242242 setContextualType (contextualType.first , contextualType.second .typeLoc ,
243- contextualType.second .purpose );
243+ contextualType.second .purpose ,
244+ contextualType.second .isOpaqueReturnType );
244245 }
245246 }
246247
@@ -591,7 +592,7 @@ bool ConstraintSystem::Candidate::solve(
591592 cs.Timer .emplace (E, cs);
592593
593594 // Generate constraints for the new system.
594- if (auto generatedExpr = cs.generateConstraints (E)) {
595+ if (auto generatedExpr = cs.generateConstraints (E, DC )) {
595596 E = generatedExpr;
596597 } else {
597598 // Failure to generate constraint system for sub-expression
@@ -1115,80 +1116,93 @@ bool ConstraintSystem::solve(Expr *&expr,
11151116 getASTContext ().TypeCheckerOpts .DebugConstraintSolver ,
11161117 debugConstraintSolverForExpr (getASTContext (), expr));
11171118
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+ };
11371135
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.
11421147 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 ;
11491151
1150- case SolutionResult::Kind::UndiagnosedError:
1151- diagnoseFailureFor (expr);
1152- salvagedResult.markAsDiagnosed ();
1152+ case SolutionResult::Error:
11531153 return true ;
11541154
1155- case SolutionResult::Kind:: TooComplex:
1155+ case SolutionResult::TooComplex:
11561156 getASTContext ().Diags .diagnose (expr->getLoc (), diag::expression_too_complex)
1157- .highlight (expr->getSourceRange ());
1158- salvagedResult .markAsDiagnosed ();
1157+ .highlight (expr->getSourceRange ());
1158+ solution .markAsDiagnosed ();
11591159 return true ;
1160- }
11611160
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+ }
11641168
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+ }
11701178
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 ;
11801191 }
1192+
1193+ // Loop again to try to salvage.
1194+ solution.markAsDiagnosed ();
1195+ continue ;
11811196 }
11821197 }
11831198
1184- return false ;
1199+ llvm_unreachable ( " Loop always returns " ) ;
11851200}
11861201
1187- ConstraintSystem::SolutionKind
1202+ SolutionResult
11881203ConstraintSystem::solveImpl (Expr *&expr,
11891204 Type convertType,
11901205 ExprTypeCheckListener *listener,
1191- SmallVectorImpl<Solution> &solutions,
11921206 FreeTypeVariableBinding allowFreeTypeVariables) {
11931207 if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
11941208 auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
@@ -1215,53 +1229,46 @@ ConstraintSystem::solveImpl(Expr *&expr,
12151229 shrink (expr);
12161230
12171231 // Generate constraints for the main system.
1218- if (auto generatedExpr = generateConstraints (expr))
1232+ if (auto generatedExpr = generateConstraints (expr, DC ))
12191233 expr = generatedExpr;
12201234 else {
12211235 if (listener)
12221236 listener->constraintGenerationFailed (expr);
1223- return SolutionKind::Error ;
1237+ return SolutionResult::forError () ;
12241238 }
12251239
12261240 // If there is a type that we're expected to convert to, add the conversion
12271241 // constraint.
12281242 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+ }
12491250
1251+ // Substitute type variables in for unresolved types.
12501252 if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
1253+ bool isForSingleExprFunction = (ctp == CTP_ReturnSingleExpr);
1254+ auto *convertTypeLocator = getConstraintLocator (
1255+ expr, LocatorPathElt::ContextualType (isForSingleExprFunction));
1256+
12511257 convertType = convertType.transform ([&](Type type) -> Type {
12521258 if (type->is <UnresolvedType>())
12531259 return createTypeVariable (convertTypeLocator, TVO_CanBindToNoEscape);
12541260 return type;
12551261 });
12561262 }
12571263
1258- addConstraint (constraintKind, getType (expr), convertType,
1259- convertTypeLocator, /* isFavored*/ true );
1264+ ContextualTypeInfo info{
1265+ TypeLoc::withoutLoc (convertType), ctp, isOpaqueReturnType};
1266+ addContextualConversionConstraint (expr, info);
12601267 }
12611268
12621269 // Notify the listener that we've built the constraint system.
12631270 if (listener && listener->builtConstraints (*this , expr)) {
1264- return SolutionKind::Error ;
1271+ return SolutionResult::forError () ;
12651272 }
12661273
12671274 if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
@@ -1273,11 +1280,22 @@ ConstraintSystem::solveImpl(Expr *&expr,
12731280 }
12741281
12751282 // Try to solve the constraint system using computed suggestions.
1283+ SmallVector<Solution, 4 > solutions;
12761284 solve (solutions, allowFreeTypeVariables);
12771285
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+ }
12811299}
12821300
12831301bool ConstraintSystem::solve (SmallVectorImpl<Solution> &solutions,
0 commit comments