Skip to content

Commit f563de5

Browse files
authored
Merge pull request #76759 from slavapestov/cstrail-part-0
Unify ConstraintGraph change tracking with SavedTypeVariableBindings
2 parents b24a810 + 4548880 commit f563de5

14 files changed

+636
-528
lines changed

include/swift/Sema/CSTrail.h

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
//===--- CSTrail.h - Constraint Solver Trail --------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the \c SolverTrail class, which records the decisions taken
14+
// while attempting to find a solution.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
#ifndef SWIFT_SEMA_CSTRAIL_H
18+
#define SWIFT_SEMA_CSTRAIL_H
19+
20+
#include <vector>
21+
22+
namespace llvm {
23+
class raw_ostream;
24+
}
25+
26+
namespace swift {
27+
28+
class TypeBase;
29+
class TypeVariableType;
30+
31+
namespace constraints {
32+
33+
class Constraint;
34+
35+
class SolverTrail {
36+
public:
37+
38+
/// The kind of change made to the graph.
39+
enum class ChangeKind {
40+
/// Added a type variable to the constraint graph.
41+
AddedTypeVariable,
42+
/// Added a new constraint to the constraint graph.
43+
AddedConstraint,
44+
/// Removed an existing constraint from the constraint graph.
45+
RemovedConstraint,
46+
/// Extended the equivalence class of a type variable in the constraint graph.
47+
ExtendedEquivalenceClass,
48+
/// Added a fixed binding for a type variable in the constraint graph.
49+
BoundTypeVariable,
50+
/// Introduced a type variable's fixed type to inference.
51+
IntroducedToInference,
52+
/// Set the fixed type or parent and flags for a type variable.
53+
UpdatedTypeVariable,
54+
};
55+
56+
/// A change made to the constraint system.
57+
///
58+
/// Each change can be undone (once, and in reverse order) by calling the
59+
/// undo() method.
60+
class Change {
61+
public:
62+
/// The kind of change.
63+
ChangeKind Kind;
64+
65+
union {
66+
TypeVariableType *TypeVar;
67+
Constraint *TheConstraint;
68+
69+
struct {
70+
/// The type variable whose equivalence class was extended.
71+
TypeVariableType *TypeVar;
72+
73+
/// The previous size of the equivalence class.
74+
unsigned PrevSize;
75+
} EquivClass;
76+
77+
struct {
78+
/// The type variable being bound to a fixed type.
79+
TypeVariableType *TypeVar;
80+
81+
/// The fixed type to which the type variable was bound.
82+
TypeBase *FixedType;
83+
} Binding;
84+
85+
struct {
86+
/// The type variable being updated.
87+
TypeVariableType *TypeVar;
88+
89+
/// The representative of the equivalence class, or the fixed type.
90+
llvm::PointerUnion<TypeVariableType *, TypeBase *> ParentOrFixed;
91+
92+
/// The saved value of TypeVariableType::Implementation::getRawOptions().
93+
unsigned Options;
94+
} Update;
95+
};
96+
97+
Change() : Kind(ChangeKind::AddedTypeVariable), TypeVar(nullptr) { }
98+
99+
/// Create a change that added a type variable.
100+
static Change addedTypeVariable(TypeVariableType *typeVar);
101+
102+
/// Create a change that added a constraint.
103+
static Change addedConstraint(Constraint *constraint);
104+
105+
/// Create a change that removed a constraint.
106+
static Change removedConstraint(Constraint *constraint);
107+
108+
/// Create a change that extended an equivalence class.
109+
static Change extendedEquivalenceClass(TypeVariableType *typeVar,
110+
unsigned prevSize);
111+
112+
/// Create a change that bound a type variable to a fixed type.
113+
static Change boundTypeVariable(TypeVariableType *typeVar, Type fixed);
114+
115+
/// Create a change that introduced a type variable to inference.
116+
static Change introducedToInference(TypeVariableType *typeVar, Type fixed);
117+
118+
/// Create a change that updated a type variable.
119+
static Change updatedTypeVariable(
120+
TypeVariableType *typeVar,
121+
llvm::PointerUnion<TypeVariableType *, TypeBase *> parentOrFixed,
122+
unsigned options);
123+
124+
/// Undo this change, reverting the constraint graph to the state it
125+
/// had prior to this change.
126+
///
127+
/// Changes must be undone in stack order.
128+
void undo(ConstraintSystem &cs) const;
129+
130+
void dump(llvm::raw_ostream &out, ConstraintSystem &cs,
131+
unsigned indent = 0) const;
132+
};
133+
134+
SolverTrail(ConstraintSystem &cs) : CS(cs) {}
135+
136+
~SolverTrail();
137+
138+
SolverTrail(const SolverTrail &) = delete;
139+
SolverTrail &operator=(const SolverTrail &) = delete;
140+
141+
bool isUndoActive() const { return UndoActive; }
142+
143+
void recordChange(Change change);
144+
145+
void dumpActiveScopeChanges(llvm::raw_ostream &out,
146+
unsigned fromIndex,
147+
unsigned indent = 0) const;
148+
149+
unsigned size() const {
150+
return Changes.size();
151+
}
152+
153+
void undo(unsigned toIndex);
154+
155+
private:
156+
ConstraintSystem &CS;
157+
158+
/// The list of changes made to this constraint system.
159+
std::vector<Change> Changes;
160+
161+
bool UndoActive = false;
162+
unsigned Total = 0;
163+
unsigned Max = 0;
164+
};
165+
166+
} // namespace constraints
167+
} // namespace swift
168+
169+
#endif // SWIFT_SEMA_CSTRAIL_H

include/swift/Sema/ConstraintGraph.h

Lines changed: 22 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ namespace constraints {
4242

4343
class Constraint;
4444
class ConstraintGraph;
45-
class ConstraintGraphScope;
4645
class ConstraintSystem;
4746
class TypeVariableBinding;
4847

@@ -58,6 +57,13 @@ class ConstraintGraphNode {
5857
/// Retrieve the type variable this node represents.
5958
TypeVariableType *getTypeVariable() const { return TypeVar; }
6059

60+
void reset();
61+
62+
void initTypeVariable(TypeVariableType *typeVar) {
63+
ASSERT(!TypeVar);
64+
TypeVar = typeVar;
65+
}
66+
6167
/// Retrieve the set of constraints that mention this type variable.
6268
///
6369
/// These are the hyperedges of the graph, connecting this node to
@@ -148,9 +154,7 @@ class ConstraintGraphNode {
148154
void introduceToInference(Type fixedType);
149155

150156
/// Opposite of \c introduceToInference(Type)
151-
void
152-
retractFromInference(Type fixedType,
153-
SmallPtrSetImpl<TypeVariableType *> &referencedVars);
157+
void retractFromInference(Type fixedType);
154158

155159
/// Drop all previously collected bindings and re-infer based on the
156160
/// current set constraints associated with this equivalence class.
@@ -216,6 +220,7 @@ class ConstraintGraphNode {
216220
friend class ConstraintGraph;
217221
friend class ConstraintSystem;
218222
friend class TypeVariableBinding;
223+
friend class SolverTrail;
219224
};
220225

221226
/// A graph that describes the relationships among the various type variables
@@ -266,6 +271,9 @@ class ConstraintGraph {
266271
/// Bind the given type variable to the given fixed type.
267272
void bindTypeVariable(TypeVariableType *typeVar, Type fixedType);
268273

274+
/// Introduce the type variable's fixed type to inference.
275+
void introduceToInference(TypeVariableType *typeVar, Type fixedType);
276+
269277
/// Describes which constraints \c gatherConstraints should gather.
270278
enum class GatheringKind {
271279
/// Gather constraints associated with all of the variables within the
@@ -387,7 +395,6 @@ class ConstraintGraph {
387395
/// Print the graph.
388396
void print(ArrayRef<TypeVariableType *> typeVars, llvm::raw_ostream &out);
389397
void dump(llvm::raw_ostream &out);
390-
void dumpActiveScopeChanges(llvm::raw_ostream &out, unsigned indent = 0);
391398

392399
// FIXME: Potentially side-effectful.
393400
SWIFT_DEBUG_HELPER(void dump());
@@ -423,6 +430,12 @@ class ConstraintGraph {
423430
/// caution.
424431
void unbindTypeVariable(TypeVariableType *typeVar, Type fixedType);
425432

433+
/// Retract the given type variable from inference.
434+
///
435+
/// Note that this change is not recorded and cannot be undone. Use with
436+
/// caution.
437+
void retractFromInference(TypeVariableType *typeVar, Type fixedType);
438+
426439
/// Perform edge contraction on the constraint graph, merging equivalence
427440
/// classes until a fixed point is reached.
428441
bool contractEdges();
@@ -436,90 +449,14 @@ class ConstraintGraph {
436449
/// Constraints that are "orphaned" because they contain no type variables.
437450
SmallVector<Constraint *, 4> OrphanedConstraints;
438451

452+
/// Unused nodes.
453+
SmallVector<ConstraintGraphNode *> FreeList;
454+
439455
/// Increment the number of constraints considered per attempt
440456
/// to contract constraint graph edges.
441457
void incrementConstraintsPerContractionCounter();
442458

443-
/// The kind of change made to the graph.
444-
enum class ChangeKind {
445-
/// Added a type variable.
446-
AddedTypeVariable,
447-
/// Added a new constraint.
448-
AddedConstraint,
449-
/// Removed an existing constraint
450-
RemovedConstraint,
451-
/// Extended the equivalence class of a type variable.
452-
ExtendedEquivalenceClass,
453-
/// Added a fixed binding for a type variable.
454-
BoundTypeVariable,
455-
};
456-
457-
/// A change made to the constraint graph.
458-
///
459-
/// Each change can be undone (once, and in reverse order) by calling the
460-
/// undo() method.
461-
class Change {
462-
public:
463-
/// The kind of change.
464-
ChangeKind Kind;
465-
466-
union {
467-
TypeVariableType *TypeVar;
468-
Constraint *TheConstraint;
469-
470-
struct {
471-
/// The type variable whose equivalence class was extended.
472-
TypeVariableType *TypeVar;
473-
474-
/// The previous size of the equivalence class.
475-
unsigned PrevSize;
476-
} EquivClass;
477-
478-
struct {
479-
/// The type variable being bound to a fixed type.
480-
TypeVariableType *TypeVar;
481-
482-
/// The fixed type to which the type variable was bound.
483-
TypeBase *FixedType;
484-
} Binding;
485-
};
486-
487-
Change() : Kind(ChangeKind::AddedTypeVariable), TypeVar(nullptr) { }
488-
489-
/// Create a change that added a type variable.
490-
static Change addedTypeVariable(TypeVariableType *typeVar);
491-
492-
/// Create a change that added a constraint.
493-
static Change addedConstraint(Constraint *constraint);
494-
495-
/// Create a change that removed a constraint.
496-
static Change removedConstraint(Constraint *constraint);
497-
498-
/// Create a change that extended an equivalence class.
499-
static Change extendedEquivalenceClass(TypeVariableType *typeVar,
500-
unsigned prevSize);
501-
502-
/// Create a change that bound a type variable to a fixed type.
503-
static Change boundTypeVariable(TypeVariableType *typeVar, Type fixed);
504-
505-
/// Undo this change, reverting the constraint graph to the state it
506-
/// had prior to this change.
507-
///
508-
/// Changes must be undone in stack order.
509-
void undo(ConstraintGraph &cg);
510-
};
511-
512-
/// The currently active scope, or null if we aren't tracking changes made
513-
/// to the constraint graph.
514-
ConstraintGraphScope *ActiveScope = nullptr;
515-
516-
/// The set of changes made to this constraint graph.
517-
///
518-
/// As the constraint graph is extended and mutated, additional changes are
519-
/// introduced into this vector. Each scope
520-
llvm::SmallVector<Change, 4> Changes;
521-
522-
friend class ConstraintGraphScope;
459+
friend class SolverTrail;
523460
};
524461

525462
} // end namespace constraints

0 commit comments

Comments
 (0)