Skip to content

Commit 9e721a3

Browse files
authored
Merge pull request #79914 from slavapestov/retry-removing-one-way-equal
Sema: Mostly remove one-way constraints
2 parents bc6c766 + 6d8b55a commit 9e721a3

11 files changed

+61
-639
lines changed

include/swift/Sema/Constraint.h

-5
Original file line numberDiff line numberDiff line change
@@ -865,11 +865,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
865865
/// from the rest of the constraint system.
866866
bool isIsolated() const { return IsIsolated; }
867867

868-
/// Whether this is a one-way constraint.
869-
bool isOneWayConstraint() const {
870-
return Kind == ConstraintKind::OneWayEqual;
871-
}
872-
873868
/// Retrieve the overload choice for an overload-binding constraint.
874869
OverloadChoice getOverloadChoice() const {
875870
ASSERT(Kind == ConstraintKind::BindOverload);

include/swift/Sema/ConstraintGraph.h

+10-28
Original file line numberDiff line numberDiff line change
@@ -295,25 +295,18 @@ class ConstraintGraph {
295295
/// to a type variable.
296296
void introduceToInference(TypeVariableType *typeVar, Type fixedType);
297297

298-
/// Describes which constraints \c gatherConstraints should gather.
299-
enum class GatheringKind {
300-
/// Gather constraints associated with all of the variables within the
301-
/// same equivalence class as the given type variable, as well as its
302-
/// immediate fixed bindings.
303-
EquivalenceClass,
304-
/// Gather all constraints that mention this type variable or type variables
305-
/// that it is a fixed binding of. Unlike EquivalenceClass, this looks
306-
/// through transitive fixed bindings. This can be used to find all the
307-
/// constraints that may be affected when binding a type variable.
308-
AllMentions,
309-
};
298+
/// Gather constraints associated with all of the variables within the
299+
/// same equivalence class as the given type variable, as well as its
300+
/// immediate fixed bindings.
301+
llvm::TinyPtrVector<Constraint *>
302+
gatherAllConstraints(TypeVariableType *typeVar);
310303

311-
/// Gather the set of constraints that involve the given type variable,
312-
/// i.e., those constraints that will be affected when the type variable
313-
/// gets merged or bound to a fixed type.
304+
/// Gather all constraints that mention this type variable or type variables
305+
/// that it is a fixed binding of. Unlike EquivalenceClass, this looks
306+
/// through transitive fixed bindings. This can be used to find all the
307+
/// constraints that may be affected when binding a type variable.
314308
llvm::TinyPtrVector<Constraint *>
315-
gatherConstraints(TypeVariableType *typeVar,
316-
GatheringKind kind,
309+
gatherNearbyConstraints(TypeVariableType *typeVar,
317310
llvm::function_ref<bool(Constraint *)> acceptConstraint =
318311
[](Constraint *constraint) { return true; });
319312

@@ -338,12 +331,6 @@ class ConstraintGraph {
338331
/// The constraints in this component.
339332
TinyPtrVector<Constraint *> constraints;
340333

341-
/// The set of components that this component depends on, such that
342-
/// the partial solutions of the those components need to be available
343-
/// before this component can be solved.
344-
///
345-
SmallVector<unsigned, 2> dependencies;
346-
347334
public:
348335
Component(unsigned solutionIndex) : solutionIndex(solutionIndex) { }
349336

@@ -359,11 +346,6 @@ class ConstraintGraph {
359346
return constraints;
360347
}
361348

362-
/// Records a component which this component depends on.
363-
void recordDependency(const Component &component);
364-
365-
ArrayRef<unsigned> getDependencies() const { return dependencies; }
366-
367349
unsigned getNumDisjunctions() const { return numDisjunctions; }
368350
};
369351

lib/Sema/CSGen.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,8 @@ namespace {
400400

401401
llvm::SmallSetVector<ProtocolDecl *, 2> literalProtos;
402402
if (auto argTypeVar = argTy->getAs<TypeVariableType>()) {
403-
auto constraints = CS.getConstraintGraph().gatherConstraints(
404-
argTypeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
403+
auto constraints = CS.getConstraintGraph().gatherNearbyConstraints(
404+
argTypeVar,
405405
[](Constraint *constraint) {
406406
return constraint->getKind() == ConstraintKind::LiteralConformsTo;
407407
});

lib/Sema/CSSimplify.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -15982,8 +15982,8 @@ ConstraintSystem::addKeyPathApplicationRootConstraint(Type root, ConstraintLocat
1598215982
if (!typeVar)
1598315983
return;
1598415984

15985-
auto constraints = CG.gatherConstraints(
15986-
typeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
15985+
auto constraints = CG.gatherNearbyConstraints(
15986+
typeVar,
1598715987
[&keyPathExpr](Constraint *constraint) -> bool {
1598815988
if (constraint->getKind() != ConstraintKind::KeyPath)
1598915989
return false;

lib/Sema/CSSolver.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -1880,8 +1880,8 @@ static Constraint *selectBestBindingDisjunction(
18801880
if (!firstBindDisjunction)
18811881
firstBindDisjunction = disjunction;
18821882

1883-
auto constraints = cs.getConstraintGraph().gatherConstraints(
1884-
typeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
1883+
auto constraints = cs.getConstraintGraph().gatherNearbyConstraints(
1884+
typeVar,
18851885
[](Constraint *constraint) {
18861886
return constraint->getKind() == ConstraintKind::Conversion;
18871887
});
@@ -1910,8 +1910,8 @@ ConstraintSystem::findConstraintThroughOptionals(
19101910
while (visitedVars.insert(rep).second) {
19111911
// Look for a disjunction that binds this type variable to an overload set.
19121912
TypeVariableType *optionalObjectTypeVar = nullptr;
1913-
auto constraints = getConstraintGraph().gatherConstraints(
1914-
rep, ConstraintGraph::GatheringKind::EquivalenceClass,
1913+
auto constraints = getConstraintGraph().gatherNearbyConstraints(
1914+
rep,
19151915
[&](Constraint *match) {
19161916
// If we have an "optional object of" constraint, we may need to
19171917
// look through it to find the constraint we're looking for.
@@ -2553,9 +2553,8 @@ void DisjunctionChoice::propagateConversionInfo(ConstraintSystem &cs) const {
25532553
}
25542554
}
25552555

2556-
auto constraints = cs.CG.gatherConstraints(
2556+
auto constraints = cs.CG.gatherNearbyConstraints(
25572557
typeVar,
2558-
ConstraintGraph::GatheringKind::EquivalenceClass,
25592558
[](Constraint *constraint) -> bool {
25602559
switch (constraint->getKind()) {
25612560
case ConstraintKind::Conversion:

lib/Sema/CSStep.cpp

+5-99
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ void SplitterStep::computeFollowupSteps(
126126
// Take the orphaned constraints, because they'll go into a component now.
127127
OrphanedConstraints = CG.takeOrphanedConstraints();
128128

129-
IncludeInMergedResults.resize(numComponents, true);
130129
Components.resize(numComponents);
131130
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4>[]>(
132131
new SmallVector<Solution, 4>[numComponents]);
@@ -135,26 +134,9 @@ void SplitterStep::computeFollowupSteps(
135134
for (unsigned i : indices(components)) {
136135
unsigned solutionIndex = components[i].solutionIndex;
137136

138-
// If there are no dependencies, build a normal component step.
139-
if (components[i].getDependencies().empty()) {
140-
steps.push_back(std::make_unique<ComponentStep>(
141-
CS, solutionIndex, &Components[i], std::move(components[i]),
142-
PartialSolutions[solutionIndex]));
143-
continue;
144-
}
145-
146-
// Note that the partial results from any dependencies of this component
147-
// need not be included in the final merged results, because they'll
148-
// already be part of the partial results for this component.
149-
for (auto dependsOn : components[i].getDependencies()) {
150-
IncludeInMergedResults[dependsOn] = false;
151-
}
152-
153-
// Otherwise, build a dependent component "splitter" step, which
154-
// handles all combinations of incoming partial solutions.
155-
steps.push_back(std::make_unique<DependentComponentSplitterStep>(
156-
CS, &Components[i], solutionIndex, std::move(components[i]),
157-
llvm::MutableArrayRef(PartialSolutions.get(), numComponents)));
137+
steps.push_back(std::make_unique<ComponentStep>(
138+
CS, solutionIndex, &Components[i], std::move(components[i]),
139+
PartialSolutions[solutionIndex]));
158140
}
159141

160142
assert(CS.InactiveConstraints.empty() && "Missed a constraint");
@@ -223,8 +205,7 @@ bool SplitterStep::mergePartialSolutions() const {
223205
SmallVector<unsigned, 2> countsVec;
224206
countsVec.reserve(numComponents);
225207
for (unsigned idx : range(numComponents)) {
226-
countsVec.push_back(
227-
IncludeInMergedResults[idx] ? PartialSolutions[idx].size() : 1);
208+
countsVec.push_back(PartialSolutions[idx].size());
228209
}
229210

230211
// Produce all combinations of partial solutions.
@@ -237,9 +218,6 @@ bool SplitterStep::mergePartialSolutions() const {
237218
// solutions.
238219
ConstraintSystem::SolverScope scope(CS);
239220
for (unsigned i : range(numComponents)) {
240-
if (!IncludeInMergedResults[i])
241-
continue;
242-
243221
CS.replaySolution(PartialSolutions[i][indices[i]]);
244222
}
245223

@@ -271,87 +249,15 @@ bool SplitterStep::mergePartialSolutions() const {
271249
return anySolutions;
272250
}
273251

274-
StepResult DependentComponentSplitterStep::take(bool prevFailed) {
275-
// "split" is considered a failure if previous step failed,
276-
// or there is a failure recorded by constraint system, or
277-
// system can't be simplified.
278-
if (prevFailed || CS.getFailedConstraint() || CS.simplify())
279-
return done(/*isSuccess=*/false);
280-
281-
// Figure out the sets of partial solutions that this component depends on.
282-
SmallVector<const SmallVector<Solution, 4> *, 2> dependsOnSets;
283-
for (auto index : Component.getDependencies()) {
284-
dependsOnSets.push_back(&AllPartialSolutions[index]);
285-
}
286-
287-
// Produce all combinations of partial solutions for the inputs.
288-
SmallVector<std::unique_ptr<SolverStep>, 4> followup;
289-
SmallVector<unsigned, 2> indices(Component.getDependencies().size(), 0);
290-
auto dependsOnSetsRef = llvm::ArrayRef(dependsOnSets);
291-
do {
292-
// Form the set of input partial solutions.
293-
SmallVector<const Solution *, 2> dependsOnSolutions;
294-
for (auto index : swift::indices(indices)) {
295-
dependsOnSolutions.push_back(&(*dependsOnSets[index])[indices[index]]);
296-
}
297-
ContextualSolutions.push_back(std::make_unique<SmallVector<Solution, 2>>());
298-
299-
followup.push_back(std::make_unique<ComponentStep>(
300-
CS, Index, Constraints, Component, std::move(dependsOnSolutions),
301-
*ContextualSolutions.back()));
302-
} while (nextCombination(dependsOnSetsRef, indices));
303-
304-
/// Wait until all of the component steps are done.
305-
return suspend(followup);
306-
}
307-
308-
StepResult DependentComponentSplitterStep::resume(bool prevFailed) {
309-
for (auto &ComponentStepSolutions : ContextualSolutions) {
310-
Solutions.append(std::make_move_iterator(ComponentStepSolutions->begin()),
311-
std::make_move_iterator(ComponentStepSolutions->end()));
312-
}
313-
return done(/*isSuccess=*/!Solutions.empty());
314-
}
315-
316-
void DependentComponentSplitterStep::print(llvm::raw_ostream &Out) {
317-
Out << "DependentComponentSplitterStep for dependencies on [";
318-
interleave(
319-
Component.getDependencies(), [&](unsigned index) { Out << index; },
320-
[&] { Out << ", "; });
321-
Out << "]\n";
322-
}
323-
324252
StepResult ComponentStep::take(bool prevFailed) {
325253
// One of the previous components created by "split"
326254
// failed, it means that we can't solve this component.
327-
if ((prevFailed && DependsOnPartialSolutions.empty()) ||
328-
CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
255+
if (prevFailed || CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
329256
return done(/*isSuccess=*/false);
330257

331258
// Setup active scope, only if previous component didn't fail.
332259
setupScope();
333260

334-
// If there are any dependent partial solutions to compose, do so now.
335-
if (!DependsOnPartialSolutions.empty()) {
336-
for (auto partial : DependsOnPartialSolutions) {
337-
CS.replaySolution(*partial);
338-
}
339-
340-
// Activate all of the one-way constraints.
341-
SmallVector<Constraint *, 4> oneWayConstraints;
342-
for (auto &constraint : CS.InactiveConstraints) {
343-
if (constraint.isOneWayConstraint())
344-
oneWayConstraints.push_back(&constraint);
345-
}
346-
for (auto constraint : oneWayConstraints) {
347-
CS.activateConstraint(constraint);
348-
}
349-
350-
// Simplify again.
351-
if (CS.failedConstraint || CS.simplify())
352-
return done(/*isSuccess=*/false);
353-
}
354-
355261
/// Try to figure out what this step is going to be,
356262
/// after the scope has been established.
357263
SmallString<64> potentialBindings;

lib/Sema/CSStep.h

+1-65
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,6 @@ class SplitterStep final : public SolverStep {
240240

241241
SmallVector<Constraint *, 4> OrphanedConstraints;
242242

243-
/// Whether to include the partial results of this component in the final
244-
/// merged results.
245-
SmallVector<bool, 4> IncludeInMergedResults;
246-
247243
public:
248244
SplitterStep(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions)
249245
: SolverStep(cs, solutions) {}
@@ -269,56 +265,6 @@ class SplitterStep final : public SolverStep {
269265
bool mergePartialSolutions() const;
270266
};
271267

272-
/// `DependentComponentSplitterStep` is responsible for composing the partial
273-
/// solutions from other components (on which this component depends) into
274-
/// the inputs based on which we can solve a particular component.
275-
class DependentComponentSplitterStep final : public SolverStep {
276-
/// Constraints "in scope" of this step.
277-
ConstraintList *Constraints;
278-
279-
/// Index into the parent splitter step.
280-
unsigned Index;
281-
282-
/// The component that has dependencies.
283-
ConstraintGraph::Component Component;
284-
285-
/// Array containing all of the partial solutions for the parent split.
286-
MutableArrayRef<SmallVector<Solution, 4>> AllPartialSolutions;
287-
288-
/// The solutions computed the \c ComponentSteps created for each partial
289-
/// solution combinations. Will be merged into the final \c Solutions vector
290-
/// in \c resume.
291-
std::vector<std::unique_ptr<SmallVector<Solution, 2>>> ContextualSolutions;
292-
293-
/// Take all of the constraints in this component and put them into
294-
/// \c Constraints.
295-
void injectConstraints() {
296-
for (auto constraint : Component.getConstraints()) {
297-
Constraints->erase(constraint);
298-
Constraints->push_back(constraint);
299-
}
300-
}
301-
302-
public:
303-
DependentComponentSplitterStep(
304-
ConstraintSystem &cs,
305-
ConstraintList *constraints,
306-
unsigned index,
307-
ConstraintGraph::Component &&component,
308-
MutableArrayRef<SmallVector<Solution, 4>> allPartialSolutions)
309-
: SolverStep(cs, allPartialSolutions[index]), Constraints(constraints),
310-
Index(index), Component(std::move(component)),
311-
AllPartialSolutions(allPartialSolutions) {
312-
assert(!Component.getDependencies().empty() && "Should use ComponentStep");
313-
injectConstraints();
314-
}
315-
316-
StepResult take(bool prevFailed) override;
317-
StepResult resume(bool prevFailed) override;
318-
319-
void print(llvm::raw_ostream &Out) override;
320-
};
321-
322268

323269
/// `ComponentStep` represents a set of type variables and related
324270
/// constraints which could be solved independently. It's further
@@ -381,10 +327,6 @@ class ComponentStep final : public SolverStep {
381327
/// Constraints "in scope" of this step.
382328
ConstraintList *Constraints;
383329

384-
/// The set of partial solutions that should be composed before evaluating
385-
/// this component.
386-
SmallVector<const Solution *, 2> DependsOnPartialSolutions;
387-
388330
/// Constraint which doesn't have any free type variables associated
389331
/// with it, which makes it disconnected in the graph.
390332
Constraint *OrphanedConstraint = nullptr;
@@ -419,8 +361,6 @@ class ComponentStep final : public SolverStep {
419361
constraints->erase(constraint);
420362
Constraints->push_back(constraint);
421363
}
422-
423-
assert(component.getDependencies().empty());
424364
}
425365

426366
/// Create a component step that composes existing partial solutions before
@@ -429,15 +369,11 @@ class ComponentStep final : public SolverStep {
429369
ConstraintSystem &cs, unsigned index,
430370
ConstraintList *constraints,
431371
const ConstraintGraph::Component &component,
432-
llvm::SmallVectorImpl<const Solution *> &&dependsOnPartialSolutions,
433372
SmallVectorImpl<Solution> &solutions)
434373
: SolverStep(cs, solutions), Index(index), IsSingle(false),
435374
OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
436-
Constraints(constraints),
437-
DependsOnPartialSolutions(std::move(dependsOnPartialSolutions)) {
375+
Constraints(constraints) {
438376
TypeVars = component.typeVars;
439-
assert(DependsOnPartialSolutions.size() ==
440-
component.getDependencies().size());
441377

442378
for (auto constraint : component.getConstraints()) {
443379
constraints->erase(constraint);

0 commit comments

Comments
 (0)