Skip to content

Commit acee063

Browse files
committed
RequirementMachine: Compute recursive rules
1 parent 2e5a013 commit acee063

File tree

4 files changed

+66
-1
lines changed

4 files changed

+66
-1
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,41 @@ void RewriteSystem::propagateRedundantRequirementIDs() {
179179
}
180180
}
181181

182+
/// Find concrete type or superclass rules where the right hand side occurs as a
183+
/// proper prefix of one of its substitutions.
184+
///
185+
/// eg, (T.[concrete: G<T.[P:A]>] => T).
186+
void RewriteSystem::computeRecursiveRules() {
187+
for (unsigned ruleID = FirstLocalRule, e = Rules.size();
188+
ruleID < e; ++ruleID) {
189+
auto &rule = getRule(ruleID);
190+
191+
if (rule.isPermanent() ||
192+
rule.isRedundant())
193+
continue;
194+
195+
auto optSymbol = rule.isPropertyRule();
196+
if (!optSymbol)
197+
continue;
198+
199+
auto kind = optSymbol->getKind();
200+
if (kind != Symbol::Kind::ConcreteType &&
201+
kind != Symbol::Kind::Superclass) {
202+
continue;
203+
}
204+
205+
auto rhs = rule.getRHS();
206+
for (auto term : optSymbol->getSubstitutions()) {
207+
if (term.size() > rhs.size() &&
208+
std::equal(rhs.begin(), rhs.end(), term.begin())) {
209+
RecursiveRules.push_back(ruleID);
210+
rule.markRecursive();
211+
break;
212+
}
213+
}
214+
}
215+
}
216+
182217
/// Find a rule to delete by looking through all loops for rewrite rules appearing
183218
/// once in empty context. Returns a pair consisting of a loop ID and a rule ID,
184219
/// otherwise returns None.
@@ -579,6 +614,7 @@ void RewriteSystem::minimizeRewriteSystem() {
579614
});
580615

581616
propagateRedundantRequirementIDs();
617+
computeRecursiveRules();
582618

583619
// Check invariants after homotopy reduction.
584620
verifyRewriteLoops();
@@ -628,7 +664,7 @@ GenericSignatureErrors RewriteSystem::getErrors() const {
628664
rule.containsUnresolvedSymbols())
629665
result |= GenericSignatureErrorFlags::HasInvalidRequirements;
630666

631-
if (rule.isConflicting())
667+
if (rule.isConflicting() || rule.isRecursive())
632668
result |= GenericSignatureErrorFlags::HasInvalidRequirements;
633669

634670
if (!rule.isRedundant())

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,18 @@ class RewriteSystem final {
357357
/// minimization.
358358
std::vector<std::pair<unsigned, unsigned>> ConflictingRules;
359359

360+
/// A 'recursive' rule is a concrete type or superclass rule where the right
361+
/// hand side occurs as a prefix of one of its substitutions.
362+
///
363+
/// Populated by computeRecursiveRules().
364+
std::vector<unsigned> RecursiveRules;
365+
360366
void propagateExplicitBits();
361367

362368
void propagateRedundantRequirementIDs();
363369

370+
void computeRecursiveRules();
371+
364372
using EliminationPredicate = llvm::function_ref<bool(unsigned loopID,
365373
unsigned ruleID)>;
366374

lib/AST/RequirementMachine/Rule.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,6 @@ void Rule::dump(llvm::raw_ostream &out) const {
286286
out << " [redundant]";
287287
if (Conflicting)
288288
out << " [conflicting]";
289+
if (Recursive)
290+
out << " [recursive]";
289291
}

lib/AST/RequirementMachine/Rule.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ class Rule final {
8080
/// dropped from the minimal set of requirements.
8181
unsigned Conflicting : 1;
8282

83+
/// A 'recursive' rule is a concrete type or superclass rule where the right
84+
/// hand side occurs as a proper prefix of one of its substitutions.
85+
///
86+
/// Recursive rules are detected in RewriteSystem::computeRecursiveRules(),
87+
/// and are dropped from the minimal set of requirements.
88+
unsigned Recursive : 1;
89+
8390
/// Whether this rule is now finalized and immutable.
8491
unsigned Frozen : 1;
8592

@@ -94,6 +101,7 @@ class Rule final {
94101
SubstitutionSimplified = false;
95102
Redundant = false;
96103
Conflicting = false;
104+
Recursive = false;
97105
Frozen = false;
98106
}
99107

@@ -156,6 +164,10 @@ class Rule final {
156164
return Conflicting;
157165
}
158166

167+
bool isRecursive() const {
168+
return Recursive;
169+
}
170+
159171
bool isFrozen() const {
160172
return Frozen;
161173
}
@@ -217,6 +229,13 @@ class Rule final {
217229
Conflicting = true;
218230
}
219231

232+
void markRecursive() {
233+
assert(!Frozen);
234+
assert(!Permanent && "Permanent rule should not be recursive");
235+
assert(!Recursive);
236+
Recursive = true;
237+
}
238+
220239
void freeze() {
221240
Redundant = false;
222241
RequirementID = 0;

0 commit comments

Comments
 (0)