Skip to content

Commit 670796a

Browse files
committed
RequirementMachine: Superclass and concrete type atoms
1 parent 3a5d44e commit 670796a

File tree

2 files changed

+387
-150
lines changed

2 files changed

+387
-150
lines changed

include/swift/AST/RewriteSystem.h

Lines changed: 61 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ namespace swift {
3535

3636
namespace rewriting {
3737

38-
class RewriteContext;
3938
class MutableTerm;
39+
class RewriteContext;
40+
class Term;
4041

4142
/// The smallest element in the rewrite system.
4243
///
@@ -46,35 +47,68 @@ class MutableTerm;
4647
/// case type([Protocol], Identifier)
4748
/// case genericParam(index: Int, depth: Int)
4849
/// case layout(LayoutConstraint)
50+
/// case superclass(CanType, substitutions: [Term])
51+
/// case concrete(CanType, substitutions: [Term])
4952
/// }
5053
///
54+
/// For the concrete type atoms (`superclass` and `concrete`),
55+
/// the type's structural components must either be concrete, or
56+
/// generic parameters. All generic parameters must have a depth
57+
/// of 0; the generic parameter index corresponds to an index in
58+
/// the `substitutions` array.
59+
///
60+
/// For example, the superclass requirement
61+
/// "T : MyClass<U.X, (Int) -> V.A.B>" is denoted with an atom
62+
/// structured as follows:
63+
///
64+
/// - type: MyClass<τ_0_0, (Int) -> τ_0_1>
65+
/// - substitutions:
66+
/// - U.X
67+
/// - V.A.B
68+
///
5169
/// Out-of-line methods are documented in RewriteSystem.cpp.
5270
class Atom final {
5371
public:
5472
enum class Kind : uint8_t {
73+
//////
74+
////// "Type-like" atom kinds:
75+
//////
76+
5577
/// An associated type [P:T] or [P&Q&...:T]. The parent term
5678
/// must be known to conform to P (or P, Q, ...).
5779
AssociatedType,
5880

5981
/// A generic parameter, uniquely identified by depth and
6082
/// index. Can only appear at the beginning of a term, where
61-
/// it represents a generic parameter of the top-level generic
83+
/// it denotes a generic parameter of the top-level generic
6284
/// signature.
6385
GenericParam,
6486

6587
/// An unbound identifier name.
6688
Name,
6789

68-
/// When appearing at the start of a term, represents a nested
90+
//////
91+
////// "Fact-like" atom kinds:
92+
//////
93+
94+
/// When appearing at the start of a term, denotes a nested
6995
/// type of a protocol 'Self' type.
7096
///
71-
/// When appearing at the end of a term, represents that the
72-
/// term conforms to the protocol.
97+
/// When appearing at the end of a term, denotes that the
98+
/// term's type conforms to the protocol.
7399
Protocol,
74100

75-
/// When appearring at the end of a term, represents that the
76-
/// term conforms to the layout.
77-
Layout
101+
/// When appearing at the end of a term, denotes that the
102+
/// term's type satisfies the layout constraint.
103+
Layout,
104+
105+
/// When appearing at the end of a term, denotes that the term
106+
/// is a subclass of the superclass constraint.
107+
Superclass,
108+
109+
/// When appearing at the end of a term, denotes that the term
110+
/// is exactly equal to the concrete type.
111+
ConcreteType,
78112
};
79113

80114
private:
@@ -100,6 +134,12 @@ class Atom final {
100134

101135
LayoutConstraint getLayoutConstraint() const;
102136

137+
CanType getSuperclass() const;
138+
139+
CanType getConcreteType() const;
140+
141+
ArrayRef<Term> getSubstitutions() const;
142+
103143
/// Returns an opaque pointer that uniquely identifies this atom.
104144
const void *getOpaquePointer() const {
105145
return Ptr;
@@ -125,6 +165,14 @@ class Atom final {
125165
static Atom forLayout(LayoutConstraint layout,
126166
RewriteContext &ctx);
127167

168+
static Atom forSuperclass(CanType type,
169+
ArrayRef<Term> substitutions,
170+
RewriteContext &ctx);
171+
172+
static Atom forConcreteType(CanType type,
173+
ArrayRef<Term> substitutions,
174+
RewriteContext &ctx);
175+
128176
int compare(Atom other, const ProtocolGraph &protos) const;
129177

130178
void dump(llvm::raw_ostream &out) const;
@@ -170,151 +218,14 @@ class Term final {
170218

171219
Atom operator[](size_t index) const;
172220

173-
static Term get(const MutableTerm &term, RewriteContext &ctx);
174-
175-
void dump(llvm::raw_ostream &out) const;
176-
};
177-
178-
/// Atoms are uniqued and immutable, stored as a single pointer;
179-
/// the Storage type is the allocated backing storage.
180-
struct Atom::Storage final
181-
: public llvm::FoldingSetNode,
182-
public llvm::TrailingObjects<Storage, const ProtocolDecl *, Term> {
183-
friend class Atom;
184-
185-
unsigned Kind : 3;
186-
unsigned NumProtocols : 15;
187-
unsigned NumSubstitutions : 14;
188-
189-
union {
190-
Identifier Name;
191-
LayoutConstraint Layout;
192-
const ProtocolDecl *Proto;
193-
GenericTypeParamType *GenericParam;
194-
};
195-
196-
explicit Storage(Identifier name) {
197-
Kind = unsigned(Atom::Kind::Name);
198-
NumProtocols = 0;
199-
NumSubstitutions = 0;
200-
Name = name;
201-
}
202-
203-
explicit Storage(LayoutConstraint layout) {
204-
Kind = unsigned(Atom::Kind::Layout);
205-
NumProtocols = 0;
206-
NumSubstitutions = 0;
207-
Layout = layout;
208-
}
209-
210-
explicit Storage(const ProtocolDecl *proto) {
211-
Kind = unsigned(Atom::Kind::Protocol);
212-
NumProtocols = 0;
213-
NumSubstitutions = 0;
214-
Proto = proto;
215-
}
216-
217-
explicit Storage(GenericTypeParamType *param) {
218-
Kind = unsigned(Atom::Kind::GenericParam);
219-
NumProtocols = 0;
220-
NumSubstitutions = 0;
221-
GenericParam = param;
222-
}
223-
224-
Storage(ArrayRef<const ProtocolDecl *> protos, Identifier name) {
225-
assert(!protos.empty());
226-
227-
Kind = unsigned(Atom::Kind::AssociatedType);
228-
NumProtocols = protos.size();
229-
assert(NumProtocols == protos.size() && "Overflow");
230-
NumSubstitutions = 0;
231-
Name = name;
232-
233-
for (unsigned i : indices(protos))
234-
getProtocols()[i] = protos[i];
235-
}
236-
237-
size_t numTrailingObjects(OverloadToken<const ProtocolDecl *>) const {
238-
return NumProtocols;
239-
}
240-
241-
size_t numTrailingObjects(OverloadToken<Term>) const {
242-
return NumSubstitutions;
243-
}
244-
245-
MutableArrayRef<const ProtocolDecl *> getProtocols() {
246-
return {getTrailingObjects<const ProtocolDecl *>(), NumProtocols};
247-
}
248-
249-
ArrayRef<const ProtocolDecl *> getProtocols() const {
250-
return {getTrailingObjects<const ProtocolDecl *>(), NumProtocols};
251-
}
252-
253-
void Profile(llvm::FoldingSetNodeID &id) {
254-
id.AddInteger(Kind);
255-
256-
switch (Atom::Kind(Kind)) {
257-
case Atom::Kind::Name:
258-
id.AddPointer(Name.get());
259-
return;
260-
261-
case Atom::Kind::Layout:
262-
id.AddPointer(Layout.getPointer());
263-
return;
264-
265-
case Atom::Kind::Protocol:
266-
id.AddPointer(Proto);
267-
return;
268-
269-
case Atom::Kind::GenericParam:
270-
id.AddPointer(GenericParam);
271-
return;
272-
273-
case Atom::Kind::AssociatedType: {
274-
auto protos = getProtocols();
275-
id.AddInteger(protos.size());
276-
277-
for (const auto *proto : protos)
278-
id.AddPointer(proto);
279-
280-
id.AddPointer(Name.get());
281-
return;
282-
}
283-
}
284-
285-
llvm_unreachable("Bad atom kind");
286-
}
287-
};
288-
289-
/// Terms are uniqued and immutable, stored as a single pointer;
290-
/// the Storage type is the allocated backing storage.
291-
struct Term::Storage final
292-
: public llvm::FoldingSetNode,
293-
public llvm::TrailingObjects<Storage, Atom> {
294-
friend class Atom;
295-
296-
unsigned Size;
297-
298-
explicit Storage(unsigned size) : Size(size) {}
299-
300-
size_t numTrailingObjects(OverloadToken<Atom>) const {
301-
return Size;
302-
}
303-
304-
MutableArrayRef<Atom> getElements() {
305-
return {getTrailingObjects<Atom>(), Size};
306-
}
307-
308-
ArrayRef<Atom> getElements() const {
309-
return {getTrailingObjects<Atom>(), Size};
221+
/// Returns an opaque pointer that uniquely identifies this term.
222+
const void *getOpaquePointer() const {
223+
return Ptr;
310224
}
311225

312-
void Profile(llvm::FoldingSetNodeID &id) {
313-
id.AddInteger(Size);
226+
static Term get(const MutableTerm &term, RewriteContext &ctx);
314227

315-
for (auto atom : getElements())
316-
id.AddPointer(atom.getOpaquePointer());
317-
}
228+
void dump(llvm::raw_ostream &out) const;
318229
};
319230

320231
/// A term is a sequence of one or more atoms.

0 commit comments

Comments
 (0)