Skip to content

Commit 10df9d2

Browse files
committed
[CSBindings] An attempt to make isViable filter out duplicate bindings
1 parent 1817ddc commit 10df9d2

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ class BindingSet {
398398
}
399399

400400
/// Check if this binding is viable for inclusion in the set.
401-
bool isViable(PotentialBinding &binding) const;
401+
bool isViable(PotentialBinding &binding);
402402

403403
explicit operator bool() const {
404404
return hasViableBindings() || isDirectHole();

lib/Sema/CSBindings.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -891,22 +891,47 @@ void PotentialBindings::addLiteral(Constraint *constraint) {
891891
Literals.insert(constraint);
892892
}
893893

894-
bool BindingSet::isViable(PotentialBinding &binding) const {
894+
bool BindingSet::isViable(PotentialBinding &binding) {
895895
// Prevent against checking against the same opened nominal type
896896
// over and over again. Doing so means redundant work in the best
897897
// case. In the worst case, we'll produce lots of duplicate solutions
898898
// for this constraint system, which is problematic for overload
899899
// resolution.
900900
auto type = binding.BindingType;
901-
if (type->hasTypeVariable()) {
902-
auto *NTD = type->getAnyNominal();
903-
if (!NTD)
904-
return true;
905901

906-
for (auto &existing : Bindings) {
907-
auto *existingNTD = existing.BindingType->getAnyNominal();
908-
if (existingNTD && NTD == existingNTD)
909-
return false;
902+
auto *NTD = type->getAnyNominal();
903+
if (!NTD)
904+
return true;
905+
906+
for (auto existing = Bindings.begin(); existing != Bindings.end();
907+
++existing) {
908+
auto existingType = existing->BindingType;
909+
910+
auto *existingNTD = existingType->getAnyNominal();
911+
if (!existingNTD || NTD != existingNTD)
912+
continue;
913+
914+
// If new type has a type variable it shouldn't
915+
// be considered viable.
916+
if (type->hasTypeVariable())
917+
return false;
918+
919+
// If new type doesn't have any type variables,
920+
// but existing binding does, let's replace existing
921+
// binding with new one.
922+
if (existingType->hasTypeVariable()) {
923+
// First, let's remove all of the adjacent type
924+
// variables associated with this binding.
925+
{
926+
SmallPtrSet<TypeVariableType *, 4> referencedVars;
927+
existingType->getTypeVariables(referencedVars);
928+
for (auto *var : referencedVars)
929+
AdjacentVars.erase(var);
930+
}
931+
932+
// And now let's remove the binding itself.
933+
Bindings.erase(existing);
934+
break;
910935
}
911936
}
912937

0 commit comments

Comments
 (0)