Skip to content

Commit b47b2d3

Browse files
committed
RequirementMachine: Fix generating conformances
1 parent 70233ac commit b47b2d3

File tree

3 files changed

+34
-17
lines changed

3 files changed

+34
-17
lines changed

lib/AST/RequirementMachine/GeneratingConformances.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,38 @@ void HomotopyGenerator::findProtocolConformanceRules(
6464
&result,
6565
const RewriteSystem &system) const {
6666

67+
auto redundantRules = Path.findRulesAppearingOnceInEmptyContext();
68+
69+
bool foundAny = false;
70+
for (unsigned ruleID : redundantRules) {
71+
const auto &rule = system.getRule(ruleID);
72+
if (auto *proto = rule.isProtocolConformanceRule()) {
73+
result[proto].first.push_back(ruleID);
74+
foundAny = true;
75+
}
76+
}
77+
78+
if (!foundAny)
79+
return;
80+
6781
MutableTerm term = Basepoint;
6882

83+
// Now look for rewrite steps with conformance rules in empty right context,
84+
// that is something like X.(Y.[P] => Z) (or it's inverse, X.(Z => Y.[P])).
6985
for (const auto &step : Path) {
7086
switch (step.Kind) {
7187
case RewriteStep::ApplyRewriteRule: {
7288
const auto &rule = system.getRule(step.RuleID);
73-
if (!rule.isProtocolConformanceRule())
74-
break;
75-
76-
auto *proto = rule.getLHS().back().getProtocol();
77-
78-
if (!step.isInContext()) {
79-
result[proto].first.push_back(step.RuleID);
80-
} else if (step.StartOffset > 0 &&
81-
step.EndOffset == 0) {
82-
MutableTerm prefix(term.begin(), term.begin() + step.StartOffset);
83-
result[proto].second.emplace_back(prefix, step.RuleID);
89+
if (auto *proto = rule.isProtocolConformanceRule()) {
90+
if (step.StartOffset > 0 &&
91+
step.EndOffset == 0) {
92+
// Record the prefix term that is left unchanged by this rewrite step.
93+
//
94+
// In the above example where the rewrite step is X.(Y.[P] => Z),
95+
// the prefix term is 'X'.
96+
MutableTerm prefix(term.begin(), term.begin() + step.StartOffset);
97+
result[proto].second.emplace_back(prefix, step.RuleID);
98+
}
8499
}
85100

86101
break;

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ Optional<Symbol> Rule::isPropertyRule() const {
5252
}
5353

5454
/// If this is a rule of the form T.[p] => T where [p] is a protocol symbol,
55-
/// return true, otherwise return false.
56-
bool Rule::isProtocolConformanceRule() const {
57-
if (auto property = isPropertyRule())
58-
return property->getKind() == Symbol::Kind::Protocol;
55+
/// return the protocol, otherwise return nullptr.
56+
const ProtocolDecl *Rule::isProtocolConformanceRule() const {
57+
if (auto property = isPropertyRule()) {
58+
if (property->getKind() == Symbol::Kind::Protocol)
59+
return property->getProtocol();
60+
}
5961

60-
return false;
62+
return nullptr;
6163
}
6264

6365
/// If this is a rule of the form [P].[Q] => [P] where [P] and [Q] are

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class Rule final {
7878

7979
Optional<Symbol> isPropertyRule() const;
8080

81-
bool isProtocolConformanceRule() const;
81+
const ProtocolDecl *isProtocolConformanceRule() const;
8282

8383
bool isProtocolRefinementRule() const;
8484

0 commit comments

Comments
 (0)