Skip to content

Commit ef94156

Browse files
authored
Merge pull request #6160 from xedin/crasher-28565
[TypeChecker] Add retired constraints to the front of the list in SolverScope
2 parents 2d5c4de + 8208c94 commit ef94156

File tree

5 files changed

+139
-60
lines changed

5 files changed

+139
-60
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ bool ConstraintSystem::simplify(bool ContinueAfterFailures) {
359359
}
360360

361361
if (solverState)
362-
solverState->retiredConstraints.push_front(constraint);
362+
solverState->retireConstraint(constraint);
363363

364364
CG.removeConstraint(constraint);
365365
break;
@@ -369,7 +369,7 @@ bool ConstraintSystem::simplify(bool ContinueAfterFailures) {
369369
++solverState->NumSimplifiedConstraints;
370370

371371
// This constraint has already been solved; retire it.
372-
solverState->retiredConstraints.push_front(constraint);
372+
solverState->retireConstraint(constraint);
373373
}
374374

375375
// Remove the constraint from the constraint graph.
@@ -470,16 +470,15 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
470470
resolvedOverloadSets = cs.resolvedOverloadSets;
471471
numTypeVariables = cs.TypeVariables.size();
472472
numSavedBindings = cs.solverState->savedBindings.size();
473-
firstRetired = cs.solverState->retiredConstraints.begin();
474473
numConstraintRestrictions = cs.ConstraintRestrictions.size();
475474
numFixes = cs.Fixes.size();
476475
numDisjunctionChoices = cs.DisjunctionChoices.size();
477476
numOpenedTypes = cs.OpenedTypes.size();
478477
numOpenedExistentialTypes = cs.OpenedExistentialTypes.size();
479478
numDefaultedConstraints = cs.DefaultedConstraints.size();
480-
numGeneratedConstraints = cs.solverState->generatedConstraints.size();
481479
PreviousScore = cs.CurrentScore;
482480

481+
cs.solverState->registerScope(this);
483482
++cs.solverState->NumStatesExplored;
484483
}
485484

@@ -495,28 +494,18 @@ ConstraintSystem::SolverScope::~SolverScope() {
495494
numSavedBindings);
496495

497496
// Move any remaining active constraints into the inactive list.
498-
while (!cs.ActiveConstraints.empty()) {
497+
if (!cs.ActiveConstraints.empty()) {
499498
for (auto &constraint : cs.ActiveConstraints) {
500499
constraint.setActive(false);
501500
}
502501
cs.InactiveConstraints.splice(cs.InactiveConstraints.end(),
503502
cs.ActiveConstraints);
504503
}
505504

506-
// Add the retired constraints back into circulation.
507-
cs.InactiveConstraints.splice(cs.InactiveConstraints.end(),
508-
cs.solverState->retiredConstraints,
509-
cs.solverState->retiredConstraints.begin(),
510-
firstRetired);
511-
512-
// Remove any constraints that were generated here.
513-
auto &generatedConstraints = cs.solverState->generatedConstraints;
514-
auto genStart = generatedConstraints.begin() + numGeneratedConstraints,
515-
genEnd = generatedConstraints.end();
516-
for (auto genI = genStart; genI != genEnd; ++genI) {
517-
cs.InactiveConstraints.erase(ConstraintList::iterator(*genI));
518-
}
519-
generatedConstraints.erase(genStart, genEnd);
505+
// Rollback all of the changes done to constraints by the current scope,
506+
// e.g. add retired constraints back to the circulation and remove generated
507+
// constraints introduced by the current scope.
508+
cs.solverState->rollback(this);
520509

521510
// Remove any constraint restrictions.
522511
truncate(cs.ConstraintRestrictions, numConstraintRestrictions);
@@ -2407,11 +2396,11 @@ bool ConstraintSystem::solveSimplified(
24072396
case SolutionKind::Error:
24082397
if (!failedConstraint)
24092398
failedConstraint = constraint;
2410-
solverState->retiredConstraints.push_back(constraint);
2399+
solverState->retireConstraint(constraint);
24112400
break;
24122401

24132402
case SolutionKind::Solved:
2414-
solverState->retiredConstraints.push_back(constraint);
2403+
solverState->retireConstraint(constraint);
24152404
break;
24162405

24172406
case SolutionKind::Unsolved:
@@ -2421,7 +2410,7 @@ bool ConstraintSystem::solveSimplified(
24212410
}
24222411

24232412
// Record this as a generated constraint.
2424-
solverState->generatedConstraints.push_back(constraint);
2413+
solverState->addGeneratedConstraint(constraint);
24252414

24262415
if (!solveRec(solutions, allowFreeTypeVariables)) {
24272416
firstSolvedConstraint = constraint;

lib/Sema/ConstraintGraph.cpp

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -740,23 +740,8 @@ void ConstraintGraph::removeEdge(Constraint *constraint) {
740740
}
741741
}
742742

743-
size_t index = 0;
744-
for (auto generated : CS.solverState->generatedConstraints) {
745-
if (generated == constraint) {
746-
unsigned last = CS.solverState->generatedConstraints.size()-1;
747-
auto lastConstraint = CS.solverState->generatedConstraints[last];
748-
if (lastConstraint == generated) {
749-
CS.solverState->generatedConstraints.pop_back();
750-
break;
751-
} else {
752-
CS.solverState->generatedConstraints[index] = lastConstraint;
753-
CS.solverState->generatedConstraints[last] = constraint;
754-
CS.solverState->generatedConstraints.pop_back();
755-
break;
756-
}
757-
}
758-
index++;
759-
}
743+
if (CS.solverState)
744+
CS.solverState->removeGeneratedConstraint(constraint);
760745

761746
removeConstraint(constraint);
762747
}

lib/Sema/ConstraintSystem.h

Lines changed: 122 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,13 +1016,6 @@ class ConstraintSystem {
10161016
/// \brief Whether to record failures or not.
10171017
bool recordFixes = false;
10181018

1019-
/// The list of constraints that have been retired along the
1020-
/// current path.
1021-
ConstraintList retiredConstraints;
1022-
1023-
/// The current set of generated constraints.
1024-
SmallVector<Constraint *, 4> generatedConstraints;
1025-
10261019
/// \brief The set of type variable bindings that have changed while
10271020
/// processing this constraint system.
10281021
SavedTypeVariableBindings savedBindings;
@@ -1039,6 +1032,124 @@ class ConstraintSystem {
10391032
// Statistics
10401033
#define CS_STATISTIC(Name, Description) unsigned Name = 0;
10411034
#include "ConstraintSolverStats.def"
1035+
1036+
/// \brief Register given scope to be tracked by the current solver state,
1037+
/// this helps to make sure that all of the retired/generated constraints
1038+
/// are dealt with correctly when the life time of the scope ends.
1039+
///
1040+
/// \param scope The scope to associate with current solver state.
1041+
void registerScope(SolverScope *scope) {
1042+
scopes.insert({ scope, std::make_pair(retiredConstraints.begin(),
1043+
generatedConstraints.size()) });
1044+
}
1045+
1046+
/// \brief Check whether there are any retired constraints present.
1047+
bool hasRetiredConstraints() const {
1048+
return !retiredConstraints.empty();
1049+
}
1050+
1051+
/// \brief Mark given constraint as retired along current solver path.
1052+
///
1053+
/// \param constraint The constraint to retire temporarily.
1054+
void retireConstraint(Constraint *constraint) {
1055+
retiredConstraints.push_front(constraint);
1056+
}
1057+
1058+
/// \brief Iterate over all of the retired constraints registered with
1059+
/// current solver state.
1060+
///
1061+
/// \param processor The processor function to be applied to each of
1062+
/// the constraints retrieved.
1063+
void forEachRetired(std::function<void(Constraint &)> processor) {
1064+
for (auto &constraint : retiredConstraints)
1065+
processor(constraint);
1066+
}
1067+
1068+
/// \brief Add new "generated" constraint along the current solver path.
1069+
///
1070+
/// \param constraint The newly generated constraint.
1071+
void addGeneratedConstraint(Constraint *constraint) {
1072+
generatedConstraints.push_back(constraint);
1073+
}
1074+
1075+
/// \brief Erase given constraint from the list of generated constraints
1076+
/// along the current solver path. Note that this operation doesn't
1077+
/// guarantee any ordering of the after it's application.
1078+
///
1079+
/// \param constraint The constraint to erase.
1080+
void removeGeneratedConstraint(Constraint *constraint) {
1081+
size_t index = 0;
1082+
for (auto generated : generatedConstraints) {
1083+
if (generated == constraint) {
1084+
unsigned last = generatedConstraints.size() - 1;
1085+
auto lastConstraint = generatedConstraints[last];
1086+
if (lastConstraint == generated) {
1087+
generatedConstraints.pop_back();
1088+
break;
1089+
} else {
1090+
generatedConstraints[index] = lastConstraint;
1091+
generatedConstraints[last] = constraint;
1092+
generatedConstraints.pop_back();
1093+
break;
1094+
}
1095+
}
1096+
index++;
1097+
}
1098+
}
1099+
1100+
/// \brief Restore all of the retired/generated constraints to the state
1101+
/// before given scope. This is required because retired constraints have
1102+
/// to be re-introduced to the system in order of arrival (LIFO) and list
1103+
/// of the generated constraints has to be truncated back to the
1104+
/// original size.
1105+
///
1106+
/// \param scope The solver scope to rollback.
1107+
void rollback(SolverScope *scope) {
1108+
auto entry = scopes.find(scope);
1109+
assert(entry != scopes.end() && "Unknown solver scope");
1110+
1111+
// Remove given scope from the circulation.
1112+
scopes.erase(scope);
1113+
1114+
// The position of last retired constraint before given scope.
1115+
ConstraintList::iterator lastRetiredPos;
1116+
// The original number of generated constraints before given scope.
1117+
unsigned numGenerated;
1118+
1119+
std::tie(lastRetiredPos, numGenerated) = entry->getSecond();
1120+
1121+
// Restore all of the retired constraints.
1122+
CS.InactiveConstraints.splice(CS.InactiveConstraints.end(),
1123+
retiredConstraints,
1124+
retiredConstraints.begin(), lastRetiredPos);
1125+
1126+
// And remove all of the generated constraints.
1127+
auto genStart = generatedConstraints.begin() + numGenerated,
1128+
genEnd = generatedConstraints.end();
1129+
for (auto genI = genStart; genI != genEnd; ++genI) {
1130+
CS.InactiveConstraints.erase(ConstraintList::iterator(*genI));
1131+
}
1132+
1133+
generatedConstraints.erase(genStart, genEnd);
1134+
}
1135+
1136+
private:
1137+
/// The list of constraints that have been retired along the
1138+
/// current path, this list is used in LIFO fasion when constaints
1139+
/// are added back to the circulation.
1140+
ConstraintList retiredConstraints;
1141+
1142+
/// The current set of generated constraints.
1143+
SmallVector<Constraint *, 4> generatedConstraints;
1144+
1145+
/// The collection which holds association between solver scope
1146+
/// and position of the last retired constraint and number of
1147+
/// constraints generated before registration of given scope,
1148+
/// this helps to rollback all of the constraints retired/generated
1149+
/// each of the registered scopes correct (LIFO) order.
1150+
llvm::SmallDenseMap<SolverScope *,
1151+
std::pair<ConstraintList::iterator, unsigned>>
1152+
scopes;
10421153
};
10431154

10441155
class CacheExprTypes : public ASTWalker {
@@ -1126,12 +1237,6 @@ class ConstraintSystem {
11261237
/// \brief The length of \c SavedBindings.
11271238
unsigned numSavedBindings;
11281239

1129-
/// The length of generatedConstraints.
1130-
unsigned numGeneratedConstraints;
1131-
1132-
/// \brief The last retired constraint in the list.
1133-
ConstraintList::iterator firstRetired;
1134-
11351240
/// \brief The length of \c ConstraintRestrictions.
11361241
unsigned numConstraintRestrictions;
11371242

@@ -1512,8 +1617,8 @@ class ConstraintSystem {
15121617

15131618
// Record this as a newly-generated constraint.
15141619
if (solverState) {
1515-
solverState->generatedConstraints.push_back(constraint);
1516-
solverState->retiredConstraints.push_back(constraint);
1620+
solverState->addGeneratedConstraint(constraint);
1621+
solverState->retireConstraint(constraint);
15171622
}
15181623
}
15191624

@@ -1528,7 +1633,7 @@ class ConstraintSystem {
15281633

15291634
// Record this as a newly-generated constraint.
15301635
if (solverState)
1531-
solverState->generatedConstraints.push_back(constraint);
1636+
solverState->addGeneratedConstraint(constraint);
15321637
}
15331638

15341639
/// \brief Remove an inactive constraint from the current constraint graph.
@@ -1537,7 +1642,7 @@ class ConstraintSystem {
15371642
InactiveConstraints.erase(constraint);
15381643

15391644
if (solverState)
1540-
solverState->retiredConstraints.push_back(constraint);
1645+
solverState->retireConstraint(constraint);
15411646
}
15421647

15431648
/// Retrieve the list of inactive constraints.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,13 +2696,13 @@ void ConstraintSystem::print(raw_ostream &out) {
26962696
out << "\n";
26972697
}
26982698

2699-
if (solverState && !solverState->retiredConstraints.empty()) {
2699+
if (solverState && !solverState->hasRetiredConstraints()) {
27002700
out << "\nRetired Constraints:\n";
2701-
for (auto &constraint : solverState->retiredConstraints) {
2701+
solverState->forEachRetired([&](Constraint &constraint) {
27022702
out.indent(2);
27032703
constraint.print(out, &getTypeChecker().Context.SourceMgr);
27042704
out << "\n";
2705-
}
2705+
});
27062706
}
27072707

27082708
if (resolvedOverloadSets) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
{
1010
let t:A:struct B
1111
{var f=.E=a(t

0 commit comments

Comments
 (0)