Skip to content

Commit c408271

Browse files
committed
RequirementMachine: Write a bunch of comments
1 parent 20d5d77 commit c408271

File tree

6 files changed

+480
-13
lines changed

6 files changed

+480
-13
lines changed

include/swift/AST/ProtocolGraph.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,33 @@ class AssociatedTypeDecl;
2525

2626
namespace rewriting {
2727

28+
/// Stores cached information about a protocol.
2829
struct ProtocolInfo {
30+
/// All immediately-inherited protocols.
2931
ArrayRef<ProtocolDecl *> Inherited;
32+
33+
/// Transitive closure of inherited protocols; does not include the protocol
34+
/// itself. Computed by ProtocolGraph::computeInheritedProtocols().
3035
llvm::TinyPtrVector<const ProtocolDecl *> AllInherited;
36+
37+
/// Transitive closure of inherited associated types together with all
38+
/// associated types from the protocol itself. Computed by
39+
/// ProtocolGraph::computeInheritedAssociatedTypes().
3140
llvm::TinyPtrVector<AssociatedTypeDecl *> AssociatedTypes;
41+
42+
/// The protocol's requirement signature.
3243
ArrayRef<Requirement> Requirements;
3344

34-
// Used by computeDepth() to detect circularity.
45+
/// Used by ProtocolGraph::computeProtocolDepth() to detect circularity.
3546
unsigned Mark : 1;
3647

37-
// Longest chain of protocol refinements, including this one.
38-
// Greater than zero on valid code, might be zero if there's
39-
// a cycle.
48+
/// Longest chain of protocol refinements, including this one. Greater than
49+
/// zero on valid code, might be zero if there's a cycle. Computed by
50+
/// ProtocolGraph::computeLinearOrder().
4051
unsigned Depth : 31;
4152

42-
// Index of the protocol in the linear order.
53+
/// Index of the protocol in the linear order. Computed by
54+
/// ProtocolGraph::computeLinearOrder().
4355
unsigned Index : 32;
4456

4557
ProtocolInfo() {
@@ -60,6 +72,10 @@ struct ProtocolInfo {
6072
}
6173
};
6274

75+
/// Stores cached information about all protocols transtively
76+
/// referenced from a set of generic requirements.
77+
///
78+
/// Out-of-line methods are documented in ProtocolGraph.cpp.
6379
struct ProtocolGraph {
6480
llvm::DenseMap<const ProtocolDecl *, ProtocolInfo> Info;
6581
std::vector<const ProtocolDecl *> Protocols;
@@ -93,4 +109,5 @@ struct ProtocolGraph {
93109
} // end namespace rewriting
94110

95111
} // end namespace swift
112+
96113
#endif

include/swift/AST/RequirementMachine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Term getTermForType(CanType paramType, const ProtocolDecl *proto);
3131

3232
} // end namespace rewriting
3333

34+
/// Wraps a rewrite system with higher-level operations in terms of
35+
/// generic signatures and interface types.
3436
class RequirementMachine final {
3537
friend class ASTContext;
3638

include/swift/AST/RewriteSystem.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ namespace swift {
3131

3232
namespace rewriting {
3333

34+
/// The most primitive term in the rewrite system.
35+
///
36+
/// enum Atom {
37+
/// case name(Identifier)
38+
/// case protocol(Protocol)
39+
/// case type([Protocol], Identifier)
40+
/// case genericParam(index: Int, depth: Int)
41+
/// case layout(LayoutConstraint)
42+
/// }
43+
///
44+
/// Out-of-line methods are documented in RewriteSystem.cpp.
3445
class Atom final {
3546
using Storage = llvm::PointerUnion<Identifier,
3647
GenericTypeParamType *,
@@ -47,42 +58,70 @@ class Atom final {
4758
}
4859

4960
public:
61+
/// Creates a new name atom.
5062
static Atom forName(Identifier name) {
5163
return Atom({}, name);
5264
}
5365

66+
/// Creates a new protocol atom.
5467
static Atom forProtocol(const ProtocolDecl *proto) {
5568
return Atom({proto}, Storage());
5669
}
5770

71+
/// Creates a new associated type atom for a single protocol.
5872
static Atom forAssociatedType(const ProtocolDecl *proto,
5973
Identifier name) {
6074
assert(proto != nullptr);
6175
return Atom({proto}, name);
6276
}
6377

78+
/// Creates a merged associated type atom to represent a nested
79+
/// type that conforms to multiple protocols, all of which have
80+
/// an associated type with the same name.
6481
static Atom forAssociatedType(
6582
llvm::TinyPtrVector<const ProtocolDecl *>protos,
6683
Identifier name) {
6784
assert(!protos.empty());
6885
return Atom(protos, name);
6986
}
7087

88+
/// Creates a generic parameter atom, representing a generic
89+
/// parameter in the top-level generic signature from which the
90+
/// rewrite system is built.
7191
static Atom forGenericParam(GenericTypeParamType *param) {
7292
assert(param->isCanonical());
7393
return Atom({}, param);
7494
}
7595

96+
/// Creates a layout atom, representing a layout constraint.
7697
static Atom forLayout(LayoutConstraint layout) {
7798
assert(layout->isKnownLayout());
7899
return Atom({}, layout);
79100
}
80101

81102
enum class Kind : uint8_t {
103+
/// An associated type [P:T] or [P&Q&...:T]. The parent term
104+
/// must be known to conform to P (or P, Q, ...).
82105
AssociatedType,
106+
107+
/// A generic parameter, uniquely identified by depth and
108+
/// index. Can only appear at the beginning of a term, where
109+
/// it represents a generic parameter of the top-level generic
110+
/// signature.
83111
GenericParam,
112+
113+
/// An unbound identifier name.
84114
Name,
115+
116+
/// When appearing at the start of a term, represents a nested
117+
/// type of a protocol 'Self' type.
118+
///
119+
/// When appearing at the end of a term, represents that the
120+
/// term conforms to the protocol.
85121
Protocol,
122+
123+
/// When appearring at the end of a term, represents that the
124+
/// term conforms to the layout.
86125
Layout
87126
};
88127

@@ -111,30 +150,37 @@ class Atom final {
111150
llvm_unreachable("Bad term rewriting atom");
112151
}
113152

153+
/// Get the identifier associated with an unbound name atom or an
154+
/// associated type atom.
114155
Identifier getName() const {
115156
assert(getKind() == Kind::Name ||
116157
getKind() == Kind::AssociatedType);
117158
return Value.get<Identifier>();
118159
}
119160

161+
/// Get the single protocol declaration associate with a protocol atom.
120162
const ProtocolDecl *getProtocol() const {
121163
assert(getKind() == Kind::Protocol);
122164
assert(Protos.size() == 1);
123165
return Protos.front();
124166
}
125167

168+
/// Get the list of protocols associated with a protocol or associated
169+
/// type atom.
126170
llvm::TinyPtrVector<const ProtocolDecl *> getProtocols() const {
127171
assert(getKind() == Kind::Protocol ||
128172
getKind() == Kind::AssociatedType);
129173
assert(!Protos.empty());
130174
return Protos;
131175
}
132176

177+
/// Get the generic parameter associated with a generic parameter atom.
133178
GenericTypeParamType *getGenericParam() const {
134179
assert(getKind() == Kind::GenericParam);
135180
return Value.get<GenericTypeParamType *>();
136181
}
137182

183+
/// Get the layout constraint associated with a layout constraint atom.
138184
LayoutConstraint getLayoutConstraint() const {
139185
assert(getKind() == Kind::Layout);
140186
return Value.get<LayoutConstraint>();
@@ -156,6 +202,14 @@ class Atom final {
156202
}
157203
};
158204

205+
/// A term is a sequence of one or more atoms.
206+
///
207+
/// The first atom in the term must be a protocol, generic parameter, or
208+
/// associated type atom.
209+
///
210+
/// A layout constraint atom must only appear at the end of a term.
211+
///
212+
/// Out-of-line methods are documented in RewriteSystem.cpp.
159213
class Term final {
160214
llvm::SmallVector<Atom, 3> Atoms;
161215

@@ -202,6 +256,7 @@ class Term final {
202256

203257
decltype(Atoms)::iterator findSubTerm(const Term &other);
204258

259+
/// Returns true if this term contains, or is equal to, \p other.
205260
bool containsSubTerm(const Term &other) const {
206261
return findSubTerm(other) != end();
207262
}
@@ -213,6 +268,11 @@ class Term final {
213268
void dump(llvm::raw_ostream &out) const;
214269
};
215270

271+
/// A rewrite rule that replaces occurrences of LHS with RHS.
272+
///
273+
/// LHS must be greater than RHS in the linear order over terms.
274+
///
275+
/// Out-of-line methods are documented in RewriteSystem.cpp.
216276
class Rule final {
217277
Term LHS;
218278
Term RHS;
@@ -238,19 +298,27 @@ class Rule final {
238298
return LHS.containsSubTerm(other.LHS);
239299
}
240300

301+
/// Returns if the rule was deleted.
241302
bool isDeleted() const {
242303
return deleted;
243304
}
244305

306+
/// Deletes the rule, which removes it from consideration in term
307+
/// simplification and completion. Deleted rules are simply marked as
308+
/// such instead of being physically removed from the rules vector
309+
/// in the rewrite system, to ensure that indices remain valid across
310+
/// deletion.
245311
void markDeleted() {
246312
assert(!deleted);
247313
deleted = true;
248314
}
249315

316+
/// Returns the length of the left hand side.
250317
unsigned getDepth() const {
251318
return LHS.size();
252319
}
253320

321+
/// Partial order on rules orders rules by their left hand side.
254322
int compare(const Rule &other,
255323
const ProtocolGraph &protos) const {
256324
return LHS.compare(other.LHS, protos);
@@ -259,12 +327,35 @@ class Rule final {
259327
void dump(llvm::raw_ostream &out) const;
260328
};
261329

330+
/// A term rewrite system for working with types in a generic signature.
331+
///
332+
/// Out-of-line methods are documented in RewriteSystem.cpp.
262333
class RewriteSystem final {
334+
/// The rules added so far, including rules from our client, as well
335+
/// as rules introduced by the completion procedure.
263336
std::vector<Rule> Rules;
337+
338+
/// The graph of all protocols transitively referenced via our set of
339+
/// rewrite rules, used for the linear order on atoms.
264340
ProtocolGraph Protos;
341+
342+
/// A list of pending terms for the associated type merging completion
343+
/// heuristic.
344+
///
345+
/// The pair (lhs, rhs) satisfies the following conditions:
346+
/// - lhs > rhs
347+
/// - all atoms but the last are pair-wise equal in lhs and rhs
348+
/// - the last atom in both lhs and rhs is an associated type atom
349+
/// - the last atom in both lhs and rhs has the same name
350+
///
351+
/// See RewriteSystem::processMergedAssociatedTypes() for details.
265352
std::vector<std::pair<Term, Term>> MergedAssociatedTypes;
353+
354+
/// A list of pending pairs for checking overlap in the completion
355+
/// procedure.
266356
std::deque<std::pair<unsigned, unsigned>> Worklist;
267357

358+
/// Set these to true to enable debugging output.
268359
unsigned DebugSimplify : 1;
269360
unsigned DebugAdd : 1;
270361
unsigned DebugMerge : 1;
@@ -291,8 +382,14 @@ class RewriteSystem final {
291382
bool simplify(Term &term) const;
292383

293384
enum class CompletionResult {
385+
/// Confluent completion was computed successfully.
294386
Success,
387+
388+
/// Maximum number of iterations reached.
295389
MaxIterations,
390+
391+
/// Completion produced a rewrite rule whose left hand side has a length
392+
/// exceeding the limit.
296393
MaxDepth
297394
};
298395

0 commit comments

Comments
 (0)