Skip to content

Commit 25252cd

Browse files
authored
Merge pull request #77728 from slavapestov/cg-cleanup
Sema: Small ConstraintGraph cleanup
2 parents 8b61c9b + 60d34a4 commit 25252cd

File tree

11 files changed

+144
-103
lines changed

11 files changed

+144
-103
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,6 @@ struct LiteralRequirement {
218218
};
219219

220220
struct PotentialBindings {
221-
/// The constraint system this type variable and its bindings belong to.
222-
ConstraintSystem &CS;
223-
224-
TypeVariableType *TypeVar;
225-
226221
/// The set of all constraints that have been added via infer().
227222
llvm::SmallPtrSet<Constraint *, 2> Constraints;
228223

@@ -265,18 +260,13 @@ struct PotentialBindings {
265260
llvm::SmallSetVector<std::pair<TypeVariableType *, Constraint *>, 4> SupertypeOf;
266261
llvm::SmallSetVector<std::pair<TypeVariableType *, Constraint *>, 4> EquivalentTo;
267262

268-
PotentialBindings(ConstraintSystem &cs, TypeVariableType *typeVar)
269-
: CS(cs), TypeVar(typeVar) {}
270-
271263
void addDefault(Constraint *constraint);
272264

273265
void addLiteral(Constraint *constraint);
274266

275267
/// Add a potential binding to the list of bindings,
276268
/// coalescing supertype bounds when we are able to compute the meet.
277-
void addPotentialBinding(PotentialBinding binding);
278-
279-
bool isGenericParameter() const;
269+
void addPotentialBinding(TypeVariableType *typeVar, PotentialBinding binding);
280270

281271
bool isSubtypeOf(TypeVariableType *typeVar) const {
282272
return llvm::any_of(
@@ -291,17 +281,26 @@ struct PotentialBindings {
291281
/// Attempt to infer a new binding and other useful information
292282
/// (i.e. whether bindings should be delayed) from the given
293283
/// relational constraint.
294-
std::optional<PotentialBinding> inferFromRelational(Constraint *constraint);
284+
std::optional<PotentialBinding> inferFromRelational(
285+
ConstraintSystem &CS,
286+
TypeVariableType *TypeVar,
287+
Constraint *constraint);
295288

296289
public:
297-
void infer(Constraint *constraint);
290+
void infer(ConstraintSystem &CS,
291+
TypeVariableType *TypeVar,
292+
Constraint *constraint);
298293

299294
/// Retract all bindings and other information related to a given
300295
/// constraint from this binding set.
301296
///
302297
/// This would happen when constraint is simplified or solver backtracks
303298
/// (either from overload choice or (some) type variable binding).
304-
void retract(Constraint *constraint);
299+
void retract(ConstraintSystem &CS,
300+
TypeVariableType *TypeVar,
301+
Constraint *constraint);
302+
303+
void reset();
305304
};
306305

307306

@@ -388,8 +387,9 @@ class BindingSet {
388387
/// subtype/conversion/equivalence relations with other type variables.
389388
std::optional<llvm::SmallPtrSet<Constraint *, 4>> TransitiveProtocols;
390389

391-
BindingSet(const PotentialBindings &info)
392-
: CS(info.CS), TypeVar(info.TypeVar), Info(info) {
390+
BindingSet(ConstraintSystem &CS, TypeVariableType *TypeVar,
391+
const PotentialBindings &info)
392+
: CS(CS), TypeVar(TypeVar), Info(info) {
393393
for (const auto &binding : info.Bindings)
394394
addBinding(binding, /*isTransitive=*/false);
395395

@@ -405,7 +405,7 @@ class BindingSet {
405405

406406
ConstraintSystem &getConstraintSystem() const { return CS; }
407407

408-
TypeVariableType *getTypeVariable() const { return Info.TypeVar; }
408+
TypeVariableType *getTypeVariable() const { return TypeVar; }
409409

410410
/// Check whether this binding set belongs to a type variable
411411
/// that represents a result type of a closure.

include/swift/Sema/ConstraintGraph.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,10 @@ class ConstraintGraphNode {
8484
/// as this type variable.
8585
ArrayRef<TypeVariableType *> getEquivalenceClass() const;
8686

87-
inference::PotentialBindings &getCurrentBindings();
87+
inference::PotentialBindings &getCurrentBindings() {
88+
assert(forRepresentativeVar());
89+
return Bindings;
90+
}
8891

8992
private:
9093
/// Determines whether the type variable associated with this node
@@ -180,7 +183,7 @@ class ConstraintGraphNode {
180183
TypeVariableType *TypeVar;
181184

182185
/// The set of bindings associated with this type variable.
183-
std::optional<inference::PotentialBindings> Bindings;
186+
inference::PotentialBindings Bindings;
184187

185188
/// The vector of constraints that mention this type variable, in a stable
186189
/// order for iteration.
@@ -244,14 +247,11 @@ class ConstraintGraph {
244247
/// Retrieve the constraint system this graph describes.
245248
ConstraintSystem &getConstraintSystem() const { return CS; }
246249

247-
/// Access the node corresponding to the given type variable.
248-
ConstraintGraphNode &operator[](TypeVariableType *typeVar) {
249-
return lookupNode(typeVar).first;
250-
}
250+
/// Add a new vertex to the graph.
251+
void addTypeVariable(TypeVariableType *typeVar);
251252

252-
/// Retrieve the node and index corresponding to the given type variable.
253-
std::pair<ConstraintGraphNode &, unsigned>
254-
lookupNode(TypeVariableType *typeVar);
253+
/// Look up the vertex associated with the given type variable.
254+
ConstraintGraphNode &operator[](TypeVariableType *typeVar);
255255

256256
/// Add a new constraint to the graph.
257257
void addConstraint(Constraint *constraint);

include/swift/Sema/ConstraintSystem.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "swift/Basic/Debug.h"
3131
#include "swift/Basic/LLVM.h"
3232
#include "swift/Basic/OptionSet.h"
33-
#include "swift/Sema/CSBindings.h"
3433
#include "swift/Sema/CSFix.h"
3534
#include "swift/Sema/CSTrail.h"
3635
#include "swift/Sema/Constraint.h"
@@ -1494,7 +1493,7 @@ class Solution {
14941493
DeclContext *getDC() const;
14951494

14961495
/// The set of type bindings.
1497-
llvm::DenseMap<TypeVariableType *, Type> typeBindings;
1496+
llvm::MapVector<TypeVariableType *, Type> typeBindings;
14981497

14991498
/// The set of overload choices along with their types.
15001499
llvm::DenseMap<ConstraintLocator *, SelectedOverload> overloadChoices;
@@ -2689,10 +2688,6 @@ class ConstraintSystem {
26892688
/// we're exploring.
26902689
SolverState *solverState = nullptr;
26912690

2692-
bool isRecordingChanges() const {
2693-
return solverState && !solverState->Trail.isUndoActive();
2694-
}
2695-
26962691
void recordChange(SolverTrail::Change change) {
26972692
solverState->Trail.recordChange(change);
26982693
}

lib/IDE/KeyPathCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void KeyPathTypeCheckCompletionCallback::sawSolutionImpl(
5353
return Entry.first->getImpl().getLocator() == RootLocator;
5454
});
5555
if (BaseVariableTypeBinding != S.typeBindings.end()) {
56-
BaseType = S.simplifyType(BaseVariableTypeBinding->getSecond());
56+
BaseType = S.simplifyType(BaseVariableTypeBinding->second);
5757
}
5858
}
5959
} else {

lib/Sema/CSBindings.cpp

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ static std::optional<Type> checkTypeOfBinding(TypeVariableType *typeVar,
3535
Type type);
3636

3737
bool BindingSet::forClosureResult() const {
38-
return Info.TypeVar->getImpl().isClosureResultType();
38+
return TypeVar->getImpl().isClosureResultType();
3939
}
4040

4141
bool BindingSet::forGenericParameter() const {
42-
return bool(Info.TypeVar->getImpl().getGenericParameter());
42+
return bool(TypeVar->getImpl().getGenericParameter());
4343
}
4444

4545
bool BindingSet::canBeNil() const {
@@ -54,10 +54,10 @@ bool BindingSet::isDirectHole() const {
5454
return false;
5555

5656
return Bindings.empty() && getNumViableLiteralBindings() == 0 &&
57-
Defaults.empty() && Info.TypeVar->getImpl().canBindToHole();
57+
Defaults.empty() && TypeVar->getImpl().canBindToHole();
5858
}
5959

60-
bool PotentialBindings::isGenericParameter() const {
60+
static bool isGenericParameter(TypeVariableType *TypeVar) {
6161
auto *locator = TypeVar->getImpl().getLocator();
6262
return locator && locator->isLastElement<LocatorPathElt::GenericParameter>();
6363
}
@@ -178,7 +178,7 @@ bool BindingSet::involvesTypeVariables() const {
178178

179179
bool BindingSet::isPotentiallyIncomplete() const {
180180
// Generic parameters are always potentially incomplete.
181-
if (Info.isGenericParameter())
181+
if (isGenericParameter(TypeVar))
182182
return true;
183183

184184
// Key path literal type is incomplete until there is a
@@ -1168,7 +1168,8 @@ LiteralRequirement::isCoveredBy(const PotentialBinding &binding, bool canBeNil,
11681168
} while (true);
11691169
}
11701170

1171-
void PotentialBindings::addPotentialBinding(PotentialBinding binding) {
1171+
void PotentialBindings::addPotentialBinding(TypeVariableType *TypeVar,
1172+
PotentialBinding binding) {
11721173
assert(!binding.BindingType->is<ErrorType>());
11731174

11741175
// If the type variable can't bind to an lvalue, make sure the
@@ -1418,7 +1419,7 @@ BindingSet ConstraintSystem::getBindingsFor(TypeVariableType *typeVar,
14181419
"not a representative");
14191420
assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type");
14201421

1421-
BindingSet bindings{CG[typeVar].getCurrentBindings()};
1422+
BindingSet bindings(*this, typeVar, CG[typeVar].getCurrentBindings());
14221423

14231424
if (finalize) {
14241425
llvm::SmallDenseMap<TypeVariableType *, BindingSet> cache;
@@ -1461,7 +1462,9 @@ static std::optional<Type> checkTypeOfBinding(TypeVariableType *typeVar,
14611462
}
14621463

14631464
std::optional<PotentialBinding>
1464-
PotentialBindings::inferFromRelational(Constraint *constraint) {
1465+
PotentialBindings::inferFromRelational(ConstraintSystem &CS,
1466+
TypeVariableType *TypeVar,
1467+
Constraint *constraint) {
14651468
assert(constraint->getClassification() ==
14661469
ConstraintClassification::Relational &&
14671470
"only relational constraints handled here");
@@ -1657,7 +1660,7 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
16571660
// Since inference now happens during constraint generation,
16581661
// this hack should be allowed in both `Solving`
16591662
// (during non-diagnostic mode) and `ConstraintGeneration` phases.
1660-
if (isGenericParameter() &&
1663+
if (isGenericParameter(TypeVar) &&
16611664
(!CS.shouldAttemptFixes() ||
16621665
CS.getPhase() == ConstraintSystemPhase::ConstraintGeneration)) {
16631666
type = fnTy->withExtInfo(fnTy->getExtInfo().withNoEscape(false));
@@ -1766,12 +1769,14 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
17661769
/// Retrieve the set of potential type bindings for the given
17671770
/// representative type variable, along with flags indicating whether
17681771
/// those types should be opened.
1769-
void PotentialBindings::infer(Constraint *constraint) {
1772+
void PotentialBindings::infer(ConstraintSystem &CS,
1773+
TypeVariableType *TypeVar,
1774+
Constraint *constraint) {
17701775
if (!Constraints.insert(constraint).second)
17711776
return;
17721777

17731778
// Record the change, if there are active scopes.
1774-
if (CS.isRecordingChanges())
1779+
if (CS.solverState && !CS.solverState->Trail.isUndoActive())
17751780
CS.recordChange(SolverTrail::Change::InferredBindings(TypeVar, constraint));
17761781

17771782
switch (constraint->getKind()) {
@@ -1787,11 +1792,11 @@ void PotentialBindings::infer(Constraint *constraint) {
17871792
case ConstraintKind::OptionalObject:
17881793
case ConstraintKind::UnresolvedMemberChainBase:
17891794
case ConstraintKind::LValueObject: {
1790-
auto binding = inferFromRelational(constraint);
1795+
auto binding = inferFromRelational(CS, TypeVar, constraint);
17911796
if (!binding)
17921797
break;
17931798

1794-
addPotentialBinding(*binding);
1799+
addPotentialBinding(TypeVar, *binding);
17951800
break;
17961801
}
17971802
case ConstraintKind::KeyPathApplication: {
@@ -1940,12 +1945,14 @@ void PotentialBindings::infer(Constraint *constraint) {
19401945
}
19411946
}
19421947

1943-
void PotentialBindings::retract(Constraint *constraint) {
1948+
void PotentialBindings::retract(ConstraintSystem &CS,
1949+
TypeVariableType *TypeVar,
1950+
Constraint *constraint) {
19441951
if (!Constraints.erase(constraint))
19451952
return;
19461953

19471954
// Record the change, if there are active scopes.
1948-
if (CS.isRecordingChanges())
1955+
if (CS.solverState && !CS.solverState->Trail.isUndoActive())
19491956
CS.recordChange(SolverTrail::Change::RetractedBindings(TypeVar, constraint));
19501957

19511958
LLVM_DEBUG(
@@ -2011,6 +2018,23 @@ void PotentialBindings::retract(Constraint *constraint) {
20112018
EquivalentTo.remove_if(hasMatchingSource);
20122019
}
20132020

2021+
void PotentialBindings::reset() {
2022+
if (CONDITIONAL_ASSERT_enabled()) {
2023+
ASSERT(Constraints.empty());
2024+
ASSERT(Bindings.empty());
2025+
ASSERT(Protocols.empty());
2026+
ASSERT(Literals.empty());
2027+
ASSERT(Defaults.empty());
2028+
ASSERT(DelayedBy.empty());
2029+
ASSERT(AdjacentVars.empty());
2030+
ASSERT(SubtypeOf.empty());
2031+
ASSERT(SupertypeOf.empty());
2032+
ASSERT(EquivalentTo.empty());
2033+
}
2034+
2035+
AssociatedCodeCompletionToken = ASTNode();
2036+
}
2037+
20142038
void BindingSet::forEachLiteralRequirement(
20152039
llvm::function_ref<void(KnownProtocolKind)> callback) const {
20162040
for (const auto &literal : Literals) {

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4930,7 +4930,7 @@ bool ConstraintSystem::generateConstraints(
49304930
// Cache the outer generic environment, if it exists.
49314931
if (target.getPackElementEnv()) {
49324932
PackElementGenericEnvironments.push_back(target.getPackElementEnv());
4933-
ASSERT(!isRecordingChanges() && "Need to record a change");
4933+
ASSERT(!solverState && "Need to record a change");
49344934
}
49354935

49364936
// For a for-each statement, generate constraints for the pattern, where

lib/Sema/CSRanking.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,9 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
13501350
const auto &bindings2 = solutions[idx2].typeBindings;
13511351

13521352
for (const auto &binding1 : bindings1) {
1353+
if (!binding1.second)
1354+
continue;
1355+
13531356
auto *typeVar = binding1.first;
13541357
auto *loc = typeVar->getImpl().getLocator();
13551358

@@ -1375,6 +1378,9 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
13751378
if (binding2 == bindings2.end())
13761379
continue;
13771380

1381+
if (!binding2->second)
1382+
continue;
1383+
13781384
TypeBindingsToCompare typesToCompare(binding1.second, binding2->second);
13791385

13801386
// For short-form and self-delegating init calls, we want to prefer

lib/Sema/CSSolver.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ Solution ConstraintSystem::finalize() {
103103
// This type variable has no binding. Allowed only
104104
// when `FreeTypeVariableBinding::Allow` is set,
105105
// which is checked above.
106-
if (!getFixedType(tv))
106+
if (!getFixedType(tv)) {
107+
solution.typeBindings[tv] = Type();
107108
continue;
109+
}
108110

109111
solution.typeBindings[tv] = simplifyType(tv)->reconstituteSugar(false);
110112
}
@@ -274,10 +276,15 @@ void ConstraintSystem::replaySolution(const Solution &solution,
274276
if (shouldIncreaseScore)
275277
replayScore(solution.getFixedScore());
276278

277-
// Assign fixed types to the type variables solved by this solution.
278279
for (auto binding : solution.typeBindings) {
279280
// If we haven't seen this type variable before, record it now.
280281
addTypeVariable(binding.first);
282+
}
283+
284+
// Assign fixed types to the type variables solved by this solution.
285+
for (auto binding : solution.typeBindings) {
286+
if (!binding.second)
287+
continue;
281288

282289
// If we don't already have a fixed type for this type variable,
283290
// assign the fixed type from the solution.

0 commit comments

Comments
 (0)