Skip to content

Commit 661f636

Browse files
committed
[ConstraintSystem] Deduplicate generic requirements after merging type variables
This comes up, for example, when `Self` type parameter is bound to its argument in a member reference, both argument and parameter can refer to exact same requirements, that have to be deduplicated otherwise they are just going to get "fixed" N times, which complicates diagnostics.
1 parent b26272f commit 661f636

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,33 @@ void ConstraintSystem::mergeEquivalenceClasses(TypeVariableType *typeVar1,
126126
// Merge nodes in the constraint graph.
127127
CG.mergeNodes(typeVar1, typeVar2);
128128

129+
// Let's try to de-duplicate any generic requirements
130+
// associated with given type variable, if it represents
131+
// a generic parameter.
132+
if (typeVar1->getImpl().getGenericParameter()) {
133+
auto requirements = CG.gatherConstraints(
134+
typeVar1, ConstraintGraph::GatheringKind::EquivalenceClass,
135+
[](Constraint *constraint) -> bool {
136+
if (auto *locator = constraint->getLocator()) {
137+
return locator->isLastElement(
138+
ConstraintLocator::TypeParameterRequirement) ||
139+
locator->isLastElement(
140+
ConstraintLocator::ConditionalRequirement);
141+
}
142+
143+
return false;
144+
});
145+
146+
llvm::SmallPtrSet<TypeBase *, 4> existingRequirements;
147+
for (auto *req : requirements) {
148+
auto constraintTy = req->getSecondType();
149+
// If this constraint has already been recorded in the
150+
// constraint system, there is no reason to check it twice.
151+
if (!existingRequirements.insert(constraintTy.getPointer()).second)
152+
retireConstraint(req);
153+
}
154+
}
155+
129156
if (updateWorkList) {
130157
addTypeVariableConstraintsToWorkList(typeVar1);
131158
}

0 commit comments

Comments
 (0)