Skip to content

Commit 6008e6a

Browse files
committed
RequirementMachine: Initial skeleton implementation
1 parent 0974ad9 commit 6008e6a

File tree

10 files changed

+828
-4
lines changed

10 files changed

+828
-4
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ namespace swift {
111111
class TupleTypeElt;
112112
class EnumElementDecl;
113113
class ProtocolDecl;
114+
class RequirementMachine;
114115
class SubstitutableType;
115116
class SourceManager;
116117
class ValueDecl;
@@ -1132,6 +1133,11 @@ class ASTContext final {
11321133
GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(
11331134
CanGenericSignature sig);
11341135

1136+
/// Retrieve or create a term rewriting system for answering queries on
1137+
/// type parameters written against the given generic signature.
1138+
RequirementMachine *getOrCreateRequirementMachine(
1139+
CanGenericSignature sig);
1140+
11351141
/// Retrieve a generic signature with a single unconstrained type parameter,
11361142
/// like `<T>`.
11371143
CanGenericSignature getSingleGenericParameterSignature() const;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===--- RequirementMachine.h - Generics with term rewriting ----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021 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+
#ifndef SWIFT_REQUIREMENTMACHINE_H
14+
#define SWIFT_REQUIREMENTMACHINE_H
15+
16+
namespace swift {
17+
18+
class ASTContext;
19+
class AssociatedTypeDecl;
20+
class CanGenericSignature;
21+
class CanType;
22+
class GenericSignature;
23+
class ProtocolDecl;
24+
class Requirement;
25+
26+
namespace rewriting {
27+
class Term;
28+
}
29+
30+
class RequirementMachine final {
31+
friend class ASTContext;
32+
33+
struct Implementation;
34+
35+
ASTContext &Context;
36+
Implementation *Impl;
37+
38+
explicit RequirementMachine(ASTContext &ctx);
39+
40+
RequirementMachine(const RequirementMachine &) = delete;
41+
RequirementMachine(RequirementMachine &&) = delete;
42+
RequirementMachine &operator=(const RequirementMachine &) = delete;
43+
RequirementMachine &operator=(RequirementMachine &&) = delete;
44+
45+
void addGenericSignature(CanGenericSignature sig);
46+
void addProtocolRequirementSignature(const ProtocolDecl *proto);
47+
void addRequirement(const Requirement &req, const ProtocolDecl *proto);
48+
void addAssociatedType(const AssociatedTypeDecl *type,
49+
const ProtocolDecl *proto);
50+
void processWorklist();
51+
52+
bool isComplete() const;
53+
void markComplete();
54+
55+
rewriting::Term getTermForType(CanType paramType,
56+
const ProtocolDecl *proto) const;
57+
58+
public:
59+
~RequirementMachine();
60+
};
61+
62+
} // end namespace swift
63+
64+
#endif

include/swift/AST/RewriteSystem.h

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
//===--- RewriteSystem.h - Generics with term rewriting ---------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2021 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+
#ifndef SWIFT_REWRITESYSTEM_H
14+
#define SWIFT_REWRITESYSTEM_H
15+
16+
#include "swift/AST/Decl.h"
17+
#include "swift/AST/Identifier.h"
18+
#include "swift/AST/Types.h"
19+
#include "llvm/ADT/PointerUnion.h"
20+
#include "llvm/ADT/SmallVector.h"
21+
22+
namespace llvm {
23+
class raw_ostream;
24+
}
25+
26+
namespace swift {
27+
28+
namespace rewriting {
29+
30+
class Atom final {
31+
using Storage = llvm::PointerUnion<Identifier,
32+
const ProtocolDecl *,
33+
const AssociatedTypeDecl *,
34+
GenericTypeParamType *>;
35+
Storage Value;
36+
37+
explicit Atom(Storage value) : Value(value) {}
38+
39+
public:
40+
static Atom forName(Identifier name) {
41+
return Atom(name);
42+
}
43+
44+
static Atom forProtocol(const ProtocolDecl *proto) {
45+
assert(proto != nullptr);
46+
return Atom(proto);
47+
}
48+
49+
static Atom forAssociatedType(const AssociatedTypeDecl *type) {
50+
assert(type != nullptr);
51+
return Atom(type);
52+
}
53+
54+
static Atom forGenericParam(GenericTypeParamType *param) {
55+
assert(param->isCanonical());
56+
return Atom(param);
57+
}
58+
59+
enum class Kind : uint8_t {
60+
AssociatedType,
61+
GenericParam,
62+
Name,
63+
Protocol,
64+
};
65+
66+
Kind getKind() const {
67+
if (Value.is<Identifier>())
68+
return Kind::Name;
69+
if (Value.is<const ProtocolDecl *>())
70+
return Kind::Protocol;
71+
if (Value.is<const AssociatedTypeDecl *>())
72+
return Kind::AssociatedType;
73+
if (Value.is<GenericTypeParamType *>())
74+
return Kind::GenericParam;
75+
llvm_unreachable("Bad term rewriting atom");
76+
}
77+
78+
Identifier getName() const {
79+
return Value.get<Identifier>();
80+
}
81+
82+
const ProtocolDecl *getProtocol() const {
83+
return Value.get<const ProtocolDecl *>();
84+
}
85+
86+
const AssociatedTypeDecl *getAssociatedType() const {
87+
return Value.get<const AssociatedTypeDecl *>();
88+
}
89+
90+
GenericTypeParamType *getGenericParam() const {
91+
return Value.get<GenericTypeParamType *>();
92+
}
93+
94+
int compare(Atom other) const;
95+
96+
void dump(llvm::raw_ostream &out) const;
97+
98+
friend bool operator==(Atom lhs, Atom rhs) {
99+
return lhs.Value == rhs.Value;
100+
}
101+
};
102+
103+
class Term final {
104+
llvm::SmallVector<Atom, 3> Atoms;
105+
106+
public:
107+
Term() {}
108+
109+
explicit Term(llvm::SmallVector<Atom, 3> &&atoms)
110+
: Atoms(atoms) {}
111+
112+
explicit Term(ArrayRef<Atom> atoms)
113+
: Atoms(atoms.begin(), atoms.end()) {}
114+
115+
void add(Atom atom) {
116+
Atoms.push_back(atom);
117+
}
118+
119+
int compare(const Term &other) const;
120+
121+
size_t size() const { return Atoms.size(); }
122+
123+
decltype(Atoms)::const_iterator begin() const { return Atoms.begin(); }
124+
decltype(Atoms)::const_iterator end() const { return Atoms.end(); }
125+
126+
decltype(Atoms)::iterator begin() { return Atoms.begin(); }
127+
decltype(Atoms)::iterator end() { return Atoms.end(); }
128+
129+
const Atom &operator[](size_t index) const {
130+
return Atoms[index];
131+
}
132+
133+
decltype(Atoms)::const_iterator findSubTerm(const Term &other) const;
134+
135+
decltype(Atoms)::iterator findSubTerm(const Term &other);
136+
137+
bool containsSubTerm(const Term &other) const {
138+
return findSubTerm(other) != end();
139+
}
140+
141+
bool rewriteSubTerm(const Term &lhs, const Term &rhs);
142+
143+
bool checkForOverlap(const Term &other, Term &result) const;
144+
145+
void dump(llvm::raw_ostream &out) const;
146+
};
147+
148+
class Rule final {
149+
Term LHS;
150+
Term RHS;
151+
bool deleted;
152+
153+
public:
154+
Rule(const Term &lhs, const Term &rhs)
155+
: LHS(lhs), RHS(rhs), deleted(false) {
156+
assert(LHS.compare(RHS) > 0);
157+
}
158+
159+
bool apply(Term &term) const {
160+
assert(!deleted);
161+
return term.rewriteSubTerm(LHS, RHS);
162+
}
163+
164+
bool checkForOverlap(const Rule &other, Term &result) const {
165+
return LHS.checkForOverlap(other.LHS, result);
166+
}
167+
168+
bool canReduceLeftHandSide(const Rule &other) const {
169+
return LHS.containsSubTerm(other.LHS);
170+
}
171+
172+
bool isDeleted() const {
173+
return deleted;
174+
}
175+
176+
void markDeleted() {
177+
assert(!deleted);
178+
deleted = true;
179+
}
180+
181+
void dump(llvm::raw_ostream &out) const;
182+
};
183+
184+
class RewriteSystem final {
185+
std::vector<Rule> Rules;
186+
187+
public:
188+
bool addRule(Term lhs, Term rhs);
189+
190+
bool simplify(Term &term) const;
191+
192+
void computeConfluentCompletion(unsigned maxIterations);
193+
194+
void dump(llvm::raw_ostream &out) const;
195+
};
196+
197+
} // end namespace rewriting
198+
199+
} // end namespace swift
200+
201+
#endif

include/swift/Basic/LangOptions.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,12 @@ namespace swift {
427427
ASTVerifierOverrideKind ASTVerifierOverride =
428428
ASTVerifierOverrideKind::NoOverride;
429429

430+
/// Whether the new experimental generics implementation is enabled.
431+
bool EnableRequirementMachine = false;
432+
433+
/// Enables debugging output from the requirement machine.
434+
bool DebugRequirementMachine = false;
435+
430436
/// Sets the target we are building for and updates platform conditions
431437
/// to match.
432438
///
@@ -563,6 +569,9 @@ namespace swift {
563569
/// Flags for developers
564570
///
565571

572+
/// Debug the generic signatures computed by the generic signature builder.
573+
bool DebugGenericSignatures = false;
574+
566575
/// Whether we are debugging the constraint solver.
567576
///
568577
/// This option enables verbose debugging output from the constraint
@@ -577,9 +586,6 @@ namespace swift {
577586
/// Should be stored sorted.
578587
llvm::SmallVector<unsigned, 4> DebugConstraintSolverOnLines;
579588

580-
/// Debug the generic signatures computed by the generic signature builder.
581-
bool DebugGenericSignatures = false;
582-
583589
/// Triggers llvm fatal_error if typechecker tries to typecheck a decl or an
584590
/// identifier reference with the provided prefix name.
585591
/// This is for testing purposes.

include/swift/Option/FrontendOptions.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,15 @@ def debug_constraints_on_line_EQ : Joined<["-"], "debug-constraints-on-line=">,
274274
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
275275
HelpText<"Disable per-name lazy member loading">;
276276

277+
def enable_requirement_machine : Flag<["-"], "enable-requirement-machine">,
278+
HelpText<"Enable experimental generics implementation">;
279+
280+
def disable_requirement_machine : Flag<["-"], "disable-requirement-machine">,
281+
HelpText<"Disable experimental generics implementation">;
282+
283+
def debug_requirement_machine : Flag<["-"], "debug-requirement-machine">,
284+
HelpText<"Enables debugging output from the generics implementation">;
285+
277286
def debug_generic_signatures : Flag<["-"], "debug-generic-signatures">,
278287
HelpText<"Debug generic signatures">;
279288

0 commit comments

Comments
 (0)