Skip to content

Commit b49be98

Browse files
authored
Merge pull request #36038 from xedin/add-retract-to-potential-bindings
[CSBindings] Add an ability to retract previously inferred bindings
2 parents cd724d4 + 321cc07 commit b49be98

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ struct LiteralRequirement {
206206
bool canBeNil,
207207
DeclContext *useDC) const;
208208

209+
void resetCoverage() {
210+
assert(isCovered() && "literal requirement is uncovered");
211+
CoveredBy = nullptr;
212+
}
213+
209214
/// Determines whether literal protocol associated with this
210215
/// meta-information is viable for inclusion as a defaultable binding.
211216
bool viableAsBinding() const { return !isCovered() && hasDefaultType(); }
@@ -465,6 +470,13 @@ struct PotentialBindings {
465470
public:
466471
void infer(Constraint *constraint);
467472

473+
/// Retract all bindings and other information related to a given
474+
/// constraint from this binding set.
475+
///
476+
/// This would happen when constraint is simplified or solver backtracks
477+
/// (either from overload choice or (some) type variable binding).
478+
void retract(Constraint *constraint);
479+
468480
/// Finalize binding computation for this type variable by
469481
/// inferring bindings from context e.g. transitive bindings.
470482
void finalize(llvm::SmallDenseMap<TypeVariableType *, PotentialBindings>

lib/Sema/CSBindings.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,67 @@ 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+
for (auto &literal : Literals) {
1302+
if (literal.second.CoveredBy == constraint)
1303+
literal.second.resetCoverage();
1304+
}
1305+
1306+
DelayedBy.erase(llvm::remove_if(DelayedBy, isMatchingConstraint),
1307+
DelayedBy.end());
1308+
1309+
SubtypeOf.remove_if(hasMatchingSource);
1310+
SupertypeOf.remove_if(hasMatchingSource);
1311+
EquivalentTo.remove_if(hasMatchingSource);
1312+
}
1313+
12531314
LiteralBindingKind PotentialBindings::getLiteralKind() const {
12541315
LiteralBindingKind kind = LiteralBindingKind::None;
12551316

0 commit comments

Comments
 (0)