Skip to content

Commit 5ee97c5

Browse files
authored
Merge pull request swiftlang#78888 from slavapestov/fix-rdar143340082
Sema: Ignore inactive type variables in addTypeVariableConstraintsToWorkList()
2 parents 45b5050 + 2230c3a commit 5ee97c5

File tree

8 files changed

+66
-62
lines changed

8 files changed

+66
-62
lines changed

include/swift/Sema/ConstraintGraph.h

+10-17
Original file line numberDiff line numberDiff line change
@@ -300,25 +300,18 @@ class ConstraintGraph {
300300
/// to a type variable.
301301
void introduceToInference(TypeVariableType *typeVar, Type fixedType);
302302

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

316-
/// Gather the set of constraints that involve the given type variable,
317-
/// i.e., those constraints that will be affected when the type variable
318-
/// gets merged or bound to a fixed type.
309+
/// Gather all constraints that mention this type variable or type variables
310+
/// that it is a fixed binding of. Unlike EquivalenceClass, this looks
311+
/// through transitive fixed bindings. This can be used to find all the
312+
/// constraints that may be affected when binding a type variable.
319313
llvm::TinyPtrVector<Constraint *>
320-
gatherConstraints(TypeVariableType *typeVar,
321-
GatheringKind kind,
314+
gatherNearbyConstraints(TypeVariableType *typeVar,
322315
llvm::function_ref<bool(Constraint *)> acceptConstraint =
323316
[](Constraint *constraint) { return true; });
324317

lib/Sema/CSOptimizer.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ NullablePtr<Constraint> getApplicableFnConstraint(ConstraintGraph &CG,
143143
if (!boundVar)
144144
return nullptr;
145145

146-
auto constraints = CG.gatherConstraints(
147-
boundVar, ConstraintGraph::GatheringKind::EquivalenceClass,
146+
auto constraints = CG.gatherNearbyConstraints(
147+
boundVar,
148148
[](Constraint *constraint) {
149149
return constraint->getKind() == ConstraintKind::ApplicableFunction;
150150
});
@@ -1129,8 +1129,8 @@ selectBestBindingDisjunction(ConstraintSystem &cs,
11291129
if (!firstBindDisjunction)
11301130
firstBindDisjunction = disjunction;
11311131

1132-
auto constraints = cs.getConstraintGraph().gatherConstraints(
1133-
typeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
1132+
auto constraints = cs.getConstraintGraph().gatherNearbyConstraints(
1133+
typeVar,
11341134
[](Constraint *constraint) {
11351135
return constraint->getKind() == ConstraintKind::Conversion;
11361136
});

lib/Sema/CSSimplify.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -15843,8 +15843,8 @@ ConstraintSystem::addKeyPathApplicationRootConstraint(Type root, ConstraintLocat
1584315843
if (!typeVar)
1584415844
return;
1584515845

15846-
auto constraints = CG.gatherConstraints(
15847-
typeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
15846+
auto constraints = CG.gatherNearbyConstraints(
15847+
typeVar,
1584815848
[&keyPathExpr](Constraint *constraint) -> bool {
1584915849
if (constraint->getKind() != ConstraintKind::KeyPath)
1585015850
return false;

lib/Sema/CSSolver.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -1309,8 +1309,8 @@ ConstraintSystem::findConstraintThroughOptionals(
13091309
while (visitedVars.insert(rep).second) {
13101310
// Look for a disjunction that binds this type variable to an overload set.
13111311
TypeVariableType *optionalObjectTypeVar = nullptr;
1312-
auto constraints = getConstraintGraph().gatherConstraints(
1313-
rep, ConstraintGraph::GatheringKind::EquivalenceClass,
1312+
auto constraints = getConstraintGraph().gatherNearbyConstraints(
1313+
rep,
13141314
[&](Constraint *match) {
13151315
// If we have an "optional object of" constraint, we may need to
13161316
// look through it to find the constraint we're looking for.
@@ -1918,9 +1918,8 @@ void DisjunctionChoice::propagateConversionInfo(ConstraintSystem &cs) const {
19181918
}
19191919
}
19201920

1921-
auto constraints = cs.CG.gatherConstraints(
1921+
auto constraints = cs.CG.gatherNearbyConstraints(
19221922
typeVar,
1923-
ConstraintGraph::GatheringKind::EquivalenceClass,
19241923
[](Constraint *constraint) -> bool {
19251924
switch (constraint->getKind()) {
19261925
case ConstraintKind::Conversion:
@@ -1946,6 +1945,17 @@ bool ConjunctionElement::attempt(ConstraintSystem &cs) const {
19461945
llvm::SmallPtrSet<TypeVariableType *, 4> referencedVars;
19471946
findReferencedVariables(cs, referencedVars);
19481947

1948+
if (cs.isDebugMode()) {
1949+
auto indent = cs.solverState->getCurrentIndent();
1950+
auto &log = llvm::errs().indent(indent);
1951+
log << "(Element type variables in scope: ";
1952+
interleave(
1953+
referencedVars,
1954+
[&](TypeVariableType *typeVar) { log << "$T" << typeVar->getID(); },
1955+
[&] { log << ", "; });
1956+
log << ")\n";
1957+
}
1958+
19491959
for (auto *typeVar : referencedVars)
19501960
cs.addTypeVariable(typeVar);
19511961
}

lib/Sema/ConstraintGraph.cpp

+20-31
Original file line numberDiff line numberDiff line change
@@ -552,31 +552,26 @@ void ConstraintGraph::retractBindings(TypeVariableType *typeVar,
552552

553553
#pragma mark Algorithms
554554

555-
/// Perform a depth-first search.
556-
///
557-
/// \param cg The constraint graph.
558-
/// \param typeVar The type variable we're searching from.
559-
/// \param visitConstraint Called before considering a constraint.
560-
/// \param visitedConstraints Set of already-visited constraints, used
561-
/// internally to avoid duplicated work.
562555
static void depthFirstSearch(
563556
ConstraintGraph &cg,
564557
TypeVariableType *typeVar,
565-
llvm::function_ref<void(Constraint *)> visitConstraint,
566558
llvm::SmallPtrSet<TypeVariableType *, 4> &typeVars,
559+
llvm::TinyPtrVector<Constraint *> &constraints,
567560
llvm::SmallPtrSet<Constraint *, 8> &visitedConstraints) {
561+
// If we're not looking at this type variable right now because we're
562+
// solving a conjunction element, don't consider its adjacencies.
563+
if (!cg.getConstraintSystem().isActiveTypeVariable(typeVar))
564+
return;
565+
568566
// Visit this node. If we've already seen it, bail out.
569567
if (!typeVars.insert(typeVar).second)
570568
return;
571569

572570
// Local function to visit adjacent type variables.
573571
auto visitAdjacencies = [&](ArrayRef<TypeVariableType *> adjTypeVars) {
574572
for (auto adj : adjTypeVars) {
575-
if (adj == typeVar)
576-
continue;
577-
578-
// Recurse into this node.
579-
depthFirstSearch(cg, adj, visitConstraint, typeVars, visitedConstraints);
573+
if (adj != typeVar)
574+
depthFirstSearch(cg, adj, typeVars, constraints, visitedConstraints);
580575
}
581576
};
582577

@@ -587,7 +582,7 @@ static void depthFirstSearch(
587582
if (!visitedConstraints.insert(constraint).second)
588583
continue;
589584

590-
visitConstraint(constraint);
585+
constraints.push_back(constraint);
591586
}
592587

593588
// Visit all of the other nodes in the equivalence class.
@@ -606,28 +601,22 @@ static void depthFirstSearch(
606601
visitAdjacencies(node.getReferencedVars());
607602
}
608603

609-
llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
610-
TypeVariableType *typeVar, GatheringKind kind,
611-
llvm::function_ref<bool(Constraint *)> acceptConstraintFn) {
604+
llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherAllConstraints(
605+
TypeVariableType *typeVar) {
612606
llvm::TinyPtrVector<Constraint *> constraints;
613607
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
614608
llvm::SmallPtrSet<Constraint *, 8> visitedConstraints;
615609

616-
if (kind == GatheringKind::AllMentions) {
617-
// If we've been asked for "all mentions" of a type variable, search for
618-
// constraints involving both it and its fixed bindings.
619-
depthFirstSearch(
620-
*this, typeVar,
621-
[&](Constraint *constraint) {
622-
if (acceptConstraintFn(constraint))
623-
constraints.push_back(constraint);
624-
},
625-
typeVars, visitedConstraints);
626-
return constraints;
627-
}
610+
depthFirstSearch(*this, typeVar, typeVars, constraints, visitedConstraints);
611+
return constraints;
612+
}
628613

629-
// Otherwise only search in the type var's equivalence class and immediate
630-
// fixed bindings.
614+
llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherNearbyConstraints(
615+
TypeVariableType *typeVar,
616+
llvm::function_ref<bool(Constraint *)> acceptConstraintFn) {
617+
llvm::TinyPtrVector<Constraint *> constraints;
618+
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
619+
llvm::SmallPtrSet<Constraint *, 8> visitedConstraints;
631620

632621
// Local function to add constraints.
633622
auto addTypeVarConstraints = [&](TypeVariableType *adjTypeVar) {

lib/Sema/ConstraintSystem.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,7 @@ void ConstraintSystem::assignFixedType(TypeVariableType *typeVar, Type type,
267267
void ConstraintSystem::addTypeVariableConstraintsToWorkList(
268268
TypeVariableType *typeVar) {
269269
// Activate the constraints affected by a change to this type variable.
270-
auto gatheringKind = ConstraintGraph::GatheringKind::AllMentions;
271-
for (auto *constraint : CG.gatherConstraints(typeVar, gatheringKind))
270+
for (auto *constraint : CG.gatherAllConstraints(typeVar))
272271
if (!constraint->isActive())
273272
activateConstraint(constraint);
274273
}

lib/Sema/TypeOfReference.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2044,8 +2044,8 @@ void ConstraintSystem::bindOverloadType(
20442044
increaseScore(SK_KeyPathSubscript, locator);
20452045

20462046
auto boundTypeVar = boundType->castTo<TypeVariableType>();
2047-
auto constraints = getConstraintGraph().gatherConstraints(
2048-
boundTypeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
2047+
auto constraints = getConstraintGraph().gatherNearbyConstraints(
2048+
boundTypeVar,
20492049
[](Constraint *constraint) {
20502050
return constraint->getKind() == ConstraintKind::ApplicableFunction;
20512051
});

test/Constraints/rdar143340082.swift

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
struct Test {
4+
var v: String
5+
var i: Int
6+
}
7+
8+
do {
9+
let _ = Array(1 ... 20).map { i in
10+
_ = 0
11+
return Test(v: "\(i * 1000)", i: 1)
12+
}
13+
}

0 commit comments

Comments
 (0)