Skip to content

Commit e3ab64a

Browse files
committed
RequirementMachine: Compute recursive rules
1 parent 15b99ae commit e3ab64a

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
@@ -180,6 +180,41 @@ void RewriteSystem::propagateRedundantRequirementIDs() {
180180
}
181181
}
182182

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

582617
propagateRedundantRequirementIDs();
618+
computeRecursiveRules();
583619

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

632-
if (rule.isConflicting())
668+
if (rule.isConflicting() || rule.isRecursive())
633669
result |= GenericSignatureErrorFlags::HasInvalidRequirements;
634670

635671
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)