Skip to content

Commit 88e090b

Browse files
authored
Merge pull request swiftlang#38770 from xedin/rdar-56167233
[ConstraintSystem] Relax the left-over information check in `ComponentStep`
2 parents 962f221 + 6a85650 commit 88e090b

File tree

5 files changed

+79
-11
lines changed

5 files changed

+79
-11
lines changed

Diff for: include/swift/Sema/ConstraintSystem.h

+10
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,11 @@ class ConstraintSystem {
21472147
/// explored.
21482148
size_t MaxMemory = 0;
21492149

2150+
/// Flag to indicate to the solver that the system is in invalid
2151+
/// state and it shouldn't proceed but instead produce a fallback
2152+
/// diagnostic.
2153+
bool InvalidState = false;
2154+
21502155
/// Cached member lookups.
21512156
llvm::DenseMap<std::pair<Type, DeclNameRef>, Optional<LookupResult>>
21522157
MemberLookups;
@@ -2646,6 +2651,11 @@ class ConstraintSystem {
26462651
Phase = newPhase;
26472652
}
26482653

2654+
/// Check whether constraint system is in valid state e.g.
2655+
/// has left-over active/inactive constraints which should
2656+
/// have been simplified.
2657+
bool inInvalidState() const { return InvalidState; }
2658+
26492659
/// Cache the types of the given expression and all subexpressions.
26502660
void cacheExprTypes(Expr *expr) {
26512661
bool excludeRoot = false;

Diff for: lib/Sema/CSSolver.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,11 @@ ConstraintSystem::SolverState::~SolverState() {
422422
"Expected constraint system to have this solver state!");
423423
CS.solverState = nullptr;
424424

425+
// If constraint system ended up being in an invalid state
426+
// let's just drop the state without attempting to rollback.
427+
if (CS.inInvalidState())
428+
return;
429+
425430
// Make sure that all of the retired constraints have been returned
426431
// to constraint system.
427432
assert(!hasRetiredConstraints());
@@ -513,6 +518,10 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
513518
}
514519

515520
ConstraintSystem::SolverScope::~SolverScope() {
521+
// Don't attempt to rollback from an incorrect state.
522+
if (cs.inInvalidState())
523+
return;
524+
516525
// Erase the end of various lists.
517526
while (cs.TypeVariables.size() > numTypeVariables)
518527
cs.TypeVariables.pop_back();
@@ -1384,6 +1393,13 @@ void ConstraintSystem::solveImpl(SmallVectorImpl<Solution> &solutions) {
13841393
if (failedConstraint)
13851394
return;
13861395

1396+
// Attempt to solve a constraint system already in an invalid
1397+
// state should be immediately aborted.
1398+
if (inInvalidState()) {
1399+
solutions.clear();
1400+
return;
1401+
}
1402+
13871403
// Allocate new solver scope, so constraint system
13881404
// could be restored to its original state afterwards.
13891405
// Otherwise there is a risk that some of the constraints
@@ -1426,6 +1442,14 @@ void ConstraintSystem::solveImpl(SmallVectorImpl<Solution> &solutions) {
14261442
// or error, which means that current path is inconsistent.
14271443
{
14281444
auto result = advance(step.get(), prevFailed);
1445+
1446+
// If execution of this step let constraint system in an
1447+
// invalid state, let's drop all of the solutions and abort.
1448+
if (inInvalidState()) {
1449+
solutions.clear();
1450+
return;
1451+
}
1452+
14291453
switch (result.getKind()) {
14301454
// It was impossible to solve this step, let's note that
14311455
// for followup steps, to propogate the error.

Diff for: lib/Sema/CSStep.cpp

+24-10
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

Diff for: lib/Sema/ConstraintGraph.cpp

+13-1
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();
@@ -412,6 +419,11 @@ ConstraintGraphScope::ConstraintGraphScope(ConstraintGraph &CG)
412419
}
413420

414421
ConstraintGraphScope::~ConstraintGraphScope() {
422+
// Don't attempt to rollback if constraint system ended up
423+
// in an invalid state.
424+
if (CG.CS.inInvalidState())
425+
return;
426+
415427
// Pop changes off the stack until we hit the change could we had prior to
416428
// introducing this scope.
417429
assert(CG.Changes.size() >= NumChanges && "Scope stack corrupted");

Diff for: lib/Sema/ConstraintSystem.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -5515,6 +5515,14 @@ void ConstraintSystem::diagnoseFailureFor(SolutionApplicationTarget target) {
55155515
SWIFT_DEFER { setPhase(ConstraintSystemPhase::Finalization); };
55165516

55175517
auto &DE = getASTContext().Diags;
5518+
5519+
// If constraint system is in invalid state always produce
5520+
// a fallback diagnostic that asks to file a bug.
5521+
if (inInvalidState()) {
5522+
DE.diagnose(target.getLoc(), diag::failed_to_produce_diagnostic);
5523+
return;
5524+
}
5525+
55185526
if (auto expr = target.getAsExpr()) {
55195527
if (auto *assignment = dyn_cast<AssignExpr>(expr)) {
55205528
if (isa<DiscardAssignmentExpr>(assignment->getDest()))

0 commit comments

Comments
 (0)