Skip to content

Commit 8e90882

Browse files
committed
[CSBindings] Allow retracting constraints previously used to compute potential bindings
This allows to avoid having to recompute bindings when solver backtracks.
1 parent 1efcd3f commit 8e90882

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,13 @@ struct PotentialBindings {
465465
public:
466466
void infer(Constraint *constraint);
467467

468+
/// Retract all bindings and other information related to a given
469+
/// constraint from this binding set.
470+
///
471+
/// This would happen when constraint is simplified or solver backtracks
472+
/// (either from overload choice or (some) type variable binding).
473+
void retract(Constraint *constraint);
474+
468475
/// Finalize binding computation for this type variable by
469476
/// inferring bindings from context e.g. transitive bindings.
470477
void finalize(llvm::SmallDenseMap<TypeVariableType *, PotentialBindings>

lib/Sema/CSBindings.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,62 @@ void PotentialBindings::infer(Constraint *constraint) {
12501250
}
12511251
}
12521252

1253+
void PotentialBindings::retract(Constraint *constraint) {
1254+
Bindings.remove_if([&constraint](const PotentialBinding &binding) {
1255+
return binding.getSource() == constraint;
1256+
});
1257+
1258+
auto isMatchingConstraint = [&constraint](Constraint *existing) {
1259+
return existing == constraint;
1260+
};
1261+
1262+
auto hasMatchingSource =
1263+
[&constraint](
1264+
const std::pair<TypeVariableType *, Constraint *> &adjacency) {
1265+
return adjacency.second == constraint;
1266+
};
1267+
1268+
switch (constraint->getKind()) {
1269+
case ConstraintKind::ConformsTo:
1270+
case ConstraintKind::SelfObjectOfProtocol:
1271+
Protocols.erase(llvm::remove_if(Protocols, isMatchingConstraint),
1272+
Protocols.end());
1273+
break;
1274+
1275+
case ConstraintKind::LiteralConformsTo:
1276+
Literals.erase(constraint->getProtocol());
1277+
break;
1278+
1279+
case ConstraintKind::Defaultable:
1280+
case ConstraintKind::DefaultClosureType: {
1281+
auto defaultType = constraint->getSecondType();
1282+
Defaults.erase(defaultType->getCanonicalType());
1283+
break;
1284+
}
1285+
1286+
default:
1287+
break;
1288+
}
1289+
1290+
{
1291+
llvm::SmallPtrSet<TypeVariableType *, 2> unviable;
1292+
for (const auto &adjacent : AdjacentVars) {
1293+
if (adjacent.second == constraint)
1294+
unviable.insert(adjacent.first);
1295+
}
1296+
1297+
for (auto *adjacentVar : unviable)
1298+
AdjacentVars.erase(std::make_pair(adjacentVar, constraint));
1299+
}
1300+
1301+
DelayedBy.erase(llvm::remove_if(DelayedBy, isMatchingConstraint),
1302+
DelayedBy.end());
1303+
1304+
SubtypeOf.remove_if(hasMatchingSource);
1305+
SupertypeOf.remove_if(hasMatchingSource);
1306+
EquivalentTo.remove_if(hasMatchingSource);
1307+
}
1308+
12531309
LiteralBindingKind PotentialBindings::getLiteralKind() const {
12541310
LiteralBindingKind kind = LiteralBindingKind::None;
12551311

0 commit comments

Comments
 (0)