Skip to content

Commit 5c1a527

Browse files
authored
Merge pull request #38790 from xedin/rdar-56167233-5.5
[5.5][ConstraintSystem] Relax the left-over information check in ComponentStep
2 parents ba16448 + 04711c4 commit 5c1a527

File tree

5 files changed

+79
-11
lines changed

5 files changed

+79
-11
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,11 @@ class ConstraintSystem {
21302130
/// explored.
21312131
size_t MaxMemory = 0;
21322132

2133+
/// Flag to indicate to the solver that the system is in invalid
2134+
/// state and it shouldn't proceed but instead produce a fallback
2135+
/// diagnostic.
2136+
bool InvalidState = false;
2137+
21332138
/// Cached member lookups.
21342139
llvm::DenseMap<std::pair<Type, DeclNameRef>, Optional<LookupResult>>
21352140
MemberLookups;
@@ -2619,6 +2624,11 @@ class ConstraintSystem {
26192624
Phase = newPhase;
26202625
}
26212626

2627+
/// Check whether constraint system is in valid state e.g.
2628+
/// has left-over active/inactive constraints which should
2629+
/// have been simplified.
2630+
bool inInvalidState() const { return InvalidState; }
2631+
26222632
/// Cache the types of the given expression and all subexpressions.
26232633
void cacheExprTypes(Expr *expr) {
26242634
bool excludeRoot = false;

lib/Sema/CSSolver.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ ConstraintSystem::SolverState::~SolverState() {
414414
"Expected constraint system to have this solver state!");
415415
CS.solverState = nullptr;
416416

417+
// If constraint system ended up being in an invalid state
418+
// let's just drop the state without attempting to rollback.
419+
if (CS.inInvalidState())
420+
return;
421+
417422
// Make sure that all of the retired constraints have been returned
418423
// to constraint system.
419424
assert(!hasRetiredConstraints());
@@ -504,6 +509,10 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
504509
}
505510

506511
ConstraintSystem::SolverScope::~SolverScope() {
512+
// Don't attempt to rollback from an incorrect state.
513+
if (cs.inInvalidState())
514+
return;
515+
507516
// Erase the end of various lists.
508517
while (cs.TypeVariables.size() > numTypeVariables)
509518
cs.TypeVariables.pop_back();
@@ -1362,6 +1371,13 @@ void ConstraintSystem::solveImpl(SmallVectorImpl<Solution> &solutions) {
13621371
if (failedConstraint)
13631372
return;
13641373

1374+
// Attempt to solve a constraint system already in an invalid
1375+
// state should be immediately aborted.
1376+
if (inInvalidState()) {
1377+
solutions.clear();
1378+
return;
1379+
}
1380+
13651381
// Allocate new solver scope, so constraint system
13661382
// could be restored to its original state afterwards.
13671383
// Otherwise there is a risk that some of the constraints
@@ -1404,6 +1420,14 @@ void ConstraintSystem::solveImpl(SmallVectorImpl<Solution> &solutions) {
14041420
// or error, which means that current path is inconsistent.
14051421
{
14061422
auto result = advance(step.get(), prevFailed);
1423+
1424+
// If execution of this step let constraint system in an
1425+
// invalid state, let's drop all of the solutions and abort.
1426+
if (inInvalidState()) {
1427+
solutions.clear();
1428+
return;
1429+
}
1430+
14071431
switch (result.getKind()) {
14081432
// It was impossible to solve this step, let's note that
14091433
// for followup steps, to propogate the error.

lib/Sema/CSStep.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -362,22 +362,36 @@ StepResult ComponentStep::take(bool prevFailed) {
362362
return finalize(/*isSuccess=*/false);
363363
}
364364

365+
auto printConstraints = [&](const ConstraintList &constraints) {
366+
for (auto &constraint : constraints)
367+
constraint.print(getDebugLogger(), &CS.getASTContext().SourceMgr);
368+
};
369+
365370
// If we don't have any disjunction or type variable choices left, we're done
366371
// solving. Make sure we don't have any unsolved constraints left over, using
367-
// report_fatal_error to make sure we trap in release builds instead of
368-
// potentially miscompiling.
372+
// report_fatal_error to make sure we trap in debug builds and fail the step
373+
// in release builds.
369374
if (!CS.ActiveConstraints.empty()) {
370-
CS.print(llvm::errs());
371-
llvm::report_fatal_error("Active constraints left over?");
375+
if (CS.isDebugMode()) {
376+
getDebugLogger() << "(failed due to remaining active constraints:\n";
377+
printConstraints(CS.ActiveConstraints);
378+
getDebugLogger() << ")\n";
379+
}
380+
381+
CS.InvalidState = true;
382+
return finalize(/*isSuccess=*/false);
372383
}
384+
373385
if (!CS.solverState->allowsFreeTypeVariables()) {
374386
if (!CS.InactiveConstraints.empty()) {
375-
CS.print(llvm::errs());
376-
llvm::report_fatal_error("Inactive constraints left over?");
377-
}
378-
if (CS.hasFreeTypeVariables()) {
379-
CS.print(llvm::errs());
380-
llvm::report_fatal_error("Free type variables left over?");
387+
if (CS.isDebugMode()) {
388+
getDebugLogger() << "(failed due to remaining inactive constraints:\n";
389+
printConstraints(CS.InactiveConstraints);
390+
getDebugLogger() << ")\n";
391+
}
392+
393+
CS.InvalidState = true;
394+
return finalize(/*isSuccess=*/false);
381395
}
382396
}
383397

lib/Sema/ConstraintGraph.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@ using namespace constraints;
3737
ConstraintGraph::ConstraintGraph(ConstraintSystem &cs) : CS(cs) { }
3838

3939
ConstraintGraph::~ConstraintGraph() {
40-
assert(Changes.empty() && "Scope stack corrupted");
40+
#ifndef NDEBUG
41+
// If constraint system is in an invalid state, it's
42+
// possible that constraint graph is corrupted as well
43+
// so let's not attempt to check change log.
44+
if (!CS.inInvalidState())
45+
assert(Changes.empty() && "Scope stack corrupted");
46+
#endif
47+
4148
for (unsigned i = 0, n = TypeVariables.size(); i != n; ++i) {
4249
auto &impl = TypeVariables[i]->getImpl();
4350
delete impl.getGraphNode();
@@ -402,6 +409,11 @@ ConstraintGraphScope::ConstraintGraphScope(ConstraintGraph &CG)
402409
}
403410

404411
ConstraintGraphScope::~ConstraintGraphScope() {
412+
// Don't attempt to rollback if constraint system ended up
413+
// in an invalid state.
414+
if (CG.CS.inInvalidState())
415+
return;
416+
405417
// Pop changes off the stack until we hit the change could we had prior to
406418
// introducing this scope.
407419
assert(CG.Changes.size() >= NumChanges && "Scope stack corrupted");

lib/Sema/ConstraintSystem.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5318,6 +5318,14 @@ void ConstraintSystem::diagnoseFailureFor(SolutionApplicationTarget target) {
53185318
SWIFT_DEFER { setPhase(ConstraintSystemPhase::Finalization); };
53195319

53205320
auto &DE = getASTContext().Diags;
5321+
5322+
// If constraint system is in invalid state always produce
5323+
// a fallback diagnostic that asks to file a bug.
5324+
if (inInvalidState()) {
5325+
DE.diagnose(target.getLoc(), diag::failed_to_produce_diagnostic);
5326+
return;
5327+
}
5328+
53215329
if (auto expr = target.getAsExpr()) {
53225330
if (auto *assignment = dyn_cast<AssignExpr>(expr)) {
53235331
if (isa<DiscardAssignmentExpr>(assignment->getDest()))

0 commit comments

Comments
 (0)