Skip to content

Commit b3284c6

Browse files
committed
[CSBindings] Track source constraint of an adjacent variable
This makes it much easier to remove adjacencies when constraint is retracted from the bindings.
1 parent 9297a35 commit b3284c6

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ struct PotentialBindings {
231231
/// bindings (contained in the binding type e.g. `Foo<$T0>`), or
232232
/// reachable through subtype/conversion relationship e.g.
233233
/// `$T0 subtype of $T1` or `$T0 arg conversion $T1`.
234-
llvm::SmallPtrSet<TypeVariableType *, 2> AdjacentVars;
234+
llvm::SmallDenseSet<std::pair<TypeVariableType *, Constraint *>, 2>
235+
AdjacentVars;
235236

236237
ASTNode AssociatedCodeCompletionToken = ASTNode();
237238

lib/Sema/CSBindings.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ bool PotentialBindings::involvesTypeVariables() const {
119119
// on each step of the solver, but once bindings are computed
120120
// incrementally it becomes more important to double-check that
121121
// any adjacent type variables found previously are still unresolved.
122-
return llvm::any_of(AdjacentVars, [](TypeVariableType *typeVar) {
123-
return !typeVar->getImpl().getFixedType(/*record=*/nullptr);
122+
return llvm::any_of(AdjacentVars, [](const auto &adjacent) {
123+
return !adjacent.first->getImpl().getFixedType(/*record=*/nullptr);
124124
});
125125
}
126126

@@ -983,7 +983,8 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
983983
findInferableTypeVars(second, typeVars);
984984

985985
if (typeVars.erase(TypeVar)) {
986-
AdjacentVars.insert(typeVars.begin(), typeVars.end());
986+
for (auto *typeVar : typeVars)
987+
AdjacentVars.insert({typeVar, constraint});
987988
}
988989

989990
return None;
@@ -1016,9 +1017,21 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
10161017
if (type->getWithoutSpecifierType()
10171018
->lookThroughAllOptionalTypes()
10181019
->is<DependentMemberType>()) {
1019-
type->getTypeVariables(AdjacentVars);
1020+
llvm::SmallPtrSet<TypeVariableType *, 4> referencedVars;
1021+
type->getTypeVariables(referencedVars);
1022+
1023+
bool containsSelf = false;
1024+
for (auto *var : referencedVars) {
1025+
// Add all type variables encountered in the type except
1026+
// to the current type variable.
1027+
if (var != TypeVar) {
1028+
AdjacentVars.insert({var, constraint});
1029+
continue;
1030+
}
1031+
1032+
containsSelf = true;
1033+
}
10201034

1021-
bool containsSelf = AdjacentVars.erase(TypeVar);
10221035
// If inferred type doesn't contain the current type variable,
10231036
// let's mark bindings as delayed until dependent member type
10241037
// is resolved.
@@ -1043,15 +1056,20 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
10431056
// Check whether we can perform this binding.
10441057
if (auto boundType = checkTypeOfBinding(TypeVar, type)) {
10451058
type = *boundType;
1046-
if (type->hasTypeVariable())
1047-
type->getTypeVariables(AdjacentVars);
1059+
if (type->hasTypeVariable()) {
1060+
llvm::SmallPtrSet<TypeVariableType *, 4> referencedVars;
1061+
type->getTypeVariables(referencedVars);
1062+
for (auto *var : referencedVars) {
1063+
AdjacentVars.insert({var, constraint});
1064+
}
1065+
}
10481066
} else {
10491067
auto *bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>();
10501068

10511069
if (!bindingTypeVar)
10521070
return None;
10531071

1054-
AdjacentVars.insert(bindingTypeVar);
1072+
AdjacentVars.insert({bindingTypeVar, constraint});
10551073

10561074
// If current type variable is associated with a code completion token
10571075
// it's possible that it doesn't have enough contextual information

0 commit comments

Comments
 (0)