Skip to content

Commit 327e7e5

Browse files
committed
RequirementMachine: Add importedRules parameter to RewriteSystem::initialize()
1 parent af443be commit 327e7e5

File tree

4 files changed

+76
-1
lines changed

4 files changed

+76
-1
lines changed

lib/AST/RequirementMachine/RequirementLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <vector>
2121
#include "Diagnostics.h"
2222
#include "RewriteContext.h"
23+
#include "Rule.h"
2324
#include "Symbol.h"
2425
#include "Term.h"
2526

@@ -93,6 +94,10 @@ struct RuleBuilder {
9394
/// being imported.
9495
std::vector<const ProtocolDecl *> ProtocolsToImport;
9596

97+
/// The rules representing a complete rewrite system for the above vector,
98+
/// pulled in by collectRulesFromReferencedProtocols().
99+
std::vector<Rule> ImportedRules;
100+
96101
/// New rules to add which will be marked 'permanent'. These are rules for
97102
/// introducing associated types, and relationships between layout,
98103
/// superclass and concrete type symbols. They are not eliminated by

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ RequirementMachine::initWithProtocolSignatureRequirements(
9191
// Add the initial set of rewrite rules to the rewrite system.
9292
System.initialize(/*recordLoops=*/true, protos,
9393
std::move(builder.WrittenRequirements),
94+
std::move(builder.ImportedRules),
9495
std::move(builder.PermanentRules),
9596
std::move(builder.RequirementRules));
9697

@@ -137,6 +138,7 @@ RequirementMachine::initWithGenericSignature(CanGenericSignature sig) {
137138
System.initialize(/*recordLoops=*/false,
138139
/*protos=*/ArrayRef<const ProtocolDecl *>(),
139140
std::move(builder.WrittenRequirements),
141+
std::move(builder.ImportedRules),
140142
std::move(builder.PermanentRules),
141143
std::move(builder.RequirementRules));
142144

@@ -181,6 +183,7 @@ RequirementMachine::initWithProtocolWrittenRequirements(
181183
// Add the initial set of rewrite rules to the rewrite system.
182184
System.initialize(/*recordLoops=*/true, protos,
183185
std::move(builder.WrittenRequirements),
186+
std::move(builder.ImportedRules),
184187
std::move(builder.PermanentRules),
185188
std::move(builder.RequirementRules));
186189

@@ -229,6 +232,7 @@ RequirementMachine::initWithWrittenRequirements(
229232
System.initialize(/*recordLoops=*/true,
230233
/*protos=*/ArrayRef<const ProtocolDecl *>(),
231234
std::move(builder.WrittenRequirements),
235+
std::move(builder.ImportedRules),
232236
std::move(builder.PermanentRules),
233237
std::move(builder.RequirementRules));
234238

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,41 @@ RewriteSystem::~RewriteSystem() {
3737
Context.RuleTrieRootHistogram);
3838
}
3939

40+
/// Initialize the rewrite system using rewrite rules built by the RuleBuilder.
41+
///
42+
/// - recordLoops: Whether this is a rewrite system built from user-written
43+
/// requirements, in which case we will perform minimization using rewrite
44+
/// loops recorded during completion.
45+
///
46+
/// - protos: If this is a rewrite system built from a protocol connected
47+
/// component, this contains the members of the protocol. For a rewrite
48+
/// system built from a generic signature, this is empty. Used by
49+
/// RewriteSystem::isInMinimizationDomain().
50+
///
51+
/// These parameters should be populated from the corresponding fields of the
52+
/// RuleBuilder instance:
53+
///
54+
/// - writtenRequirements: The user-written requirements, if any, used to
55+
/// track source locations for redundancy diagnostics.
56+
///
57+
/// - importedRules: Rewrite rules for referenced protocols. These come from
58+
/// the Requirement Machine instances for these protocols' connected
59+
/// components, so they are already confluent and can be imported verbatim.
60+
///
61+
/// - permanentRules: Permanent rules, such as associated type introduction
62+
/// rules for associated types defined in protocols in this connected
63+
/// component.
64+
///
65+
/// - requirementRules: Rules corresponding to generic requirements written
66+
/// by the user.
67+
///
68+
/// This can only be called once. It adds the rules to the rewrite system,
69+
/// allowing computeConfluentCompletion() to be called to compute the
70+
/// complete rewrite system.
4071
void RewriteSystem::initialize(
4172
bool recordLoops, ArrayRef<const ProtocolDecl *> protos,
4273
ArrayRef<StructuralRequirement> writtenRequirements,
74+
std::vector<Rule> &&importedRules,
4375
std::vector<std::pair<MutableTerm, MutableTerm>> &&permanentRules,
4476
std::vector<std::tuple<MutableTerm, MutableTerm, Optional<unsigned>>>
4577
&&requirementRules) {
@@ -50,6 +82,36 @@ void RewriteSystem::initialize(
5082
Protos = protos;
5183
WrittenRequirements = writtenRequirements;
5284

85+
// Pre-populate our rules vector with the list of imported rules, and note
86+
// the position of the first local (not imported) rule.
87+
Rules = std::move(importedRules);
88+
FirstLocalRule = Rules.size();
89+
90+
// Add the imported rules to the trie.
91+
for (unsigned newRuleID : indices(Rules)) {
92+
const auto &newRule = Rules[newRuleID];
93+
// Skip simplified rules. At the very least we need to skip RHS-simplified
94+
// rules since their left hand sides might duplicate existing rules; the
95+
// others are skipped purely as an optimization.
96+
if (newRule.isLHSSimplified() ||
97+
newRule.isRHSSimplified() ||
98+
newRule.isSubstitutionSimplified())
99+
continue;
100+
101+
auto oldRuleID = Trie.insert(newRule.getLHS().begin(),
102+
newRule.getLHS().end(),
103+
newRuleID);
104+
if (oldRuleID) {
105+
llvm::errs() << "Imported rules have duplicate left hand sides!\n";
106+
llvm::errs() << "New rule #" << newRuleID << ": " << newRule << "\n";
107+
const auto &oldRule = getRule(*oldRuleID);
108+
llvm::errs() << "Old rule #" << *oldRuleID << ": " << oldRule << "\n\n";
109+
dump(llvm::errs());
110+
abort();
111+
}
112+
}
113+
114+
// Now add our own rules.
53115
for (const auto &rule : permanentRules)
54116
addPermanentRule(rule.first, rule.second);
55117

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class RewriteSystem final {
7272
/// as rules introduced by the completion procedure.
7373
std::vector<Rule> Rules;
7474

75+
unsigned FirstLocalRule = 0;
76+
7577
/// A prefix trie of rule left hand sides to optimize lookup. The value
7678
/// type is an index into the Rules array defined above.
7779
Trie<unsigned, MatchKind::Shortest> Trie;
@@ -122,8 +124,10 @@ class RewriteSystem final {
122124

123125
DebugOptions getDebugOptions() const { return Debug; }
124126

125-
void initialize(bool recordLoops, ArrayRef<const ProtocolDecl *> protos,
127+
void initialize(bool recordLoops,
128+
ArrayRef<const ProtocolDecl *> protos,
126129
ArrayRef<StructuralRequirement> writtenRequirements,
130+
std::vector<Rule> &&importedRules,
127131
std::vector<std::pair<MutableTerm, MutableTerm>> &&permanentRules,
128132
std::vector<std::tuple<MutableTerm, MutableTerm, Optional<unsigned>>> &&requirementRules);
129133

0 commit comments

Comments
 (0)