@@ -406,6 +406,10 @@ ConstraintSystem::SolverState::SolverState(
406
406
++NumSolutionAttempts;
407
407
SolutionAttempt = NumSolutionAttempts;
408
408
409
+ // Record active constraints for re-activation at the end of lifetime.
410
+ for (auto &constraint : cs.ActiveConstraints )
411
+ activeConstraints.push_back (&constraint);
412
+
409
413
// If we're supposed to debug a specific constraint solver attempt,
410
414
// turn on debugging now.
411
415
ASTContext &ctx = CS.getTypeChecker ().Context ;
@@ -425,6 +429,34 @@ ConstraintSystem::SolverState::~SolverState() {
425
429
" Expected constraint system to have this solver state!" );
426
430
CS.solverState = nullptr ;
427
431
432
+ // Make sure that all of the retired constraints have been returned
433
+ // to constraint system.
434
+ assert (!hasRetiredConstraints ());
435
+
436
+ // Make sure that all of the generated constraints have been handled.
437
+ assert (generatedConstraints.empty ());
438
+
439
+ // Re-activate constraints which were initially marked as "active"
440
+ // to restore original state of the constraint system.
441
+ for (auto *constraint : activeConstraints) {
442
+ // If the constraint is already active we can just move on.
443
+ if (constraint->isActive ())
444
+ continue ;
445
+
446
+ // Make sure that constraint is present in the "inactive" set
447
+ // before transferring it to "active".
448
+ auto existing = llvm::find_if (CS.InactiveConstraints ,
449
+ [&constraint](const Constraint &inactive) {
450
+ return &inactive == constraint;
451
+ });
452
+ assert (existing != CS.InactiveConstraints .end ());
453
+
454
+ // Transfer the constraint to "active" set.
455
+ CS.InactiveConstraints .erase (existing);
456
+ CS.ActiveConstraints .push_back (constraint);
457
+ constraint->setActive (true );
458
+ }
459
+
428
460
// Restore debugging state.
429
461
LangOptions &langOpts = CS.getTypeChecker ().Context .LangOpts ;
430
462
langOpts.DebugConstraintSolver = OldDebugConstraintSolver;
@@ -1230,6 +1262,17 @@ bool ConstraintSystem::solve(Expr *const expr,
1230
1262
void ConstraintSystem::solve (SmallVectorImpl<Solution> &solutions) {
1231
1263
assert (solverState);
1232
1264
1265
+ // If constraint system failed while trying to
1266
+ // genenerate constraints, let's stop right here.
1267
+ if (failedConstraint)
1268
+ return ;
1269
+
1270
+ // Allocate new solver scope, so constraint system
1271
+ // could be restored to its original state afterwards.
1272
+ // Otherwise there is a risk that some of the constraints
1273
+ // are not going to be re-introduced to the system.
1274
+ SolverScope scope (*this );
1275
+
1233
1276
SmallVector<std::unique_ptr<SolverStep>, 16 > workList;
1234
1277
// First step is always wraps whole constraint system.
1235
1278
workList.push_back (llvm::make_unique<SplitterStep>(*this , solutions));
0 commit comments