Sema: Ignore inactive type variables in addTypeVariableConstraintsToWorkList()

Fixes a regression from commit 0c128e5db7.

The old depthFirstSearch() walked all adjacencies via the constraint graph,
and thus it would visit type variables that are currently inactive because
we're solving a conjunction element.

This was inconsistent with the new union-find which only formed the
connected components from the currently active type variables; adjacencies
involving inactive type variables are no longer considered.

Fix the inconsistency by changing gatherConstraints(), which used from
addTypeVariableConstraintsToWorkList(), to also skip inactive type
variables.

Fixes rdar://problem/143340082.
This commit is contained in:
Slava Pestov
2025-01-24 12:49:54 -05:00
parent 9966e01415
commit 881c4f775b
3 changed files with 29 additions and 0 deletions

View File

@@ -1946,6 +1946,17 @@ bool ConjunctionElement::attempt(ConstraintSystem &cs) const {
llvm::SmallPtrSet<TypeVariableType *, 4> referencedVars;
findReferencedVariables(cs, referencedVars);
if (cs.isDebugMode()) {
auto indent = cs.solverState->getCurrentIndent();
auto &log = llvm::errs().indent(indent);
log << "(Element type variables in scope: ";
interleave(
referencedVars,
[&](TypeVariableType *typeVar) { log << "$T" << typeVar->getID(); },
[&] { log << ", "; });
log << ")\n";
}
for (auto *typeVar : referencedVars)
cs.addTypeVariable(typeVar);
}

View File

@@ -565,6 +565,11 @@ static void depthFirstSearch(
llvm::function_ref<void(Constraint *)> visitConstraint,
llvm::SmallPtrSet<TypeVariableType *, 4> &typeVars,
llvm::SmallPtrSet<Constraint *, 8> &visitedConstraints) {
// If we're not looking at this type variable right now because we're
// solving a conjunction element, don't consider its adjacencies.
if (!cg.getConstraintSystem().isActiveTypeVariable(typeVar))
return;
// Visit this node. If we've already seen it, bail out.
if (!typeVars.insert(typeVar).second)
return;

View File

@@ -0,0 +1,13 @@
// RUN: %target-typecheck-verify-swift
struct Test {
var v: String
var i: Int
}
do {
let _ = Array(1 ... 20).map { i in
_ = 0
return Test(v: "\(i * 1000)", i: 1)
}
}