Skip to content

Commit 2737989

Browse files
committed
RequirementMachine: Fix 'relations' where one rule is a suffix of the other
1 parent 5ced0f8 commit 2737989

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,19 @@ RewriteSystem::getRelation(unsigned index) const {
6464
return Relations[index];
6565
}
6666

67-
/// Given two property rules (T.[p1] => T) and (T.[p2] => T) where [p1] < [p2],
68-
/// record a rewrite loop that makes the second rule redundant from the first.
69-
static void recordRelation(unsigned lhsRuleID, unsigned rhsRuleID,
67+
/// Given a key T, a rule (V.[p1] => V) where T == U.V, and a property [p2]
68+
/// where [p1] < [p2], record a rule (T.[p2] => T) that is implied by
69+
/// the original rule (V.[p1] => V).
70+
static void recordRelation(Term key,
71+
unsigned lhsRuleID,
72+
Symbol rhsProperty,
7073
RewriteSystem &system,
7174
SmallVectorImpl<InducedRule> &inducedRules,
7275
bool debug) {
7376
const auto &lhsRule = system.getRule(lhsRuleID);
74-
const auto &rhsRule = system.getRule(rhsRuleID);
75-
7677
auto lhsProperty = lhsRule.getLHS().back();
77-
auto rhsProperty = rhsRule.getLHS().back();
78+
79+
assert(key.size() >= lhsRule.getRHS().size());
7880

7981
assert(lhsProperty.isProperty());
8082
assert(rhsProperty.isProperty());
@@ -89,35 +91,34 @@ static void recordRelation(unsigned lhsRuleID, unsigned rhsRuleID,
8991

9092
/// Build the following rewrite path:
9193
///
92-
/// (T => T.[p1]).[p2] ⊗ T.Relation([p1].[p2] => [p1]) ⊗ (T.[p1] => T).
94+
/// U.(V => V.[p1]).[p2] ⊗ U.V.Relation([p1].[p2] => [p1]) ⊗ U.(V.[p1] => V).
9395
///
9496
RewritePath path;
9597

96-
/// Starting from T.[p2], the LHS rule in reverse to get T.[p1].[p2].
97-
path.add(RewriteStep::forRewriteRule(/*startOffset=*/0,
98-
/*endOffset=*/1,
99-
/*ruleID=*/lhsRuleID,
100-
/*inverse=*/true));
98+
/// Starting from U.V.[p2], apply the rule in reverse to get U.V.[p1].[p2].
99+
path.add(RewriteStep::forRewriteRule(
100+
/*startOffset=*/key.size() - lhsRule.getRHS().size(),
101+
/*endOffset=*/1,
102+
/*ruleID=*/lhsRuleID,
103+
/*inverse=*/true));
101104

102-
/// T.Relation([p1].[p2] => [p1]).
105+
/// U.V.Relation([p1].[p2] => [p1]).
103106
path.add(RewriteStep::forRelation(relationID, /*inverse=*/false));
104107

105-
/// (T.[p1] => T).
106-
path.add(RewriteStep::forRewriteRule(/*startOffset=*/0,
107-
/*endOffset=*/0,
108-
/*ruleID=*/lhsRuleID,
109-
/*inverse=*/false));
108+
/// U.(V.[p1] => V).
109+
path.add(RewriteStep::forRewriteRule(
110+
/*startOffset=*/key.size() - lhsRule.getRHS().size(),
111+
/*endOffset=*/0,
112+
/*ruleID=*/lhsRuleID,
113+
/*inverse=*/false));
110114

111115
/// Add the rule (T.[p2] => T) with the above rewrite path.
112-
///
113-
/// Since a rule (T.[p2] => T) *already exists*, both sides of the new
114-
/// rule will simplify down to T, and the rewrite path will become a loop.
115-
///
116-
/// This loop encodes the fact that (T.[p1] => T) makes (T.[p2] => T)
117-
/// redundant.
118-
inducedRules.emplace_back(MutableTerm(rhsRule.getLHS()),
119-
MutableTerm(rhsRule.getRHS()),
120-
path);
116+
MutableTerm lhs(key);
117+
lhs.add(rhsProperty);
118+
119+
MutableTerm rhs(key);
120+
121+
inducedRules.emplace_back(lhs, rhs, path);
121122
}
122123

123124
static void recordConflict(Term key,
@@ -446,15 +447,16 @@ void PropertyMap::addProperty(
446447
// the new layout requirement is redundant.
447448
if (mergedLayout == props->Layout) {
448449
if (checkRulePairOnce(*props->LayoutRule, ruleID)) {
449-
recordRelation(*props->LayoutRule, ruleID, System,
450+
recordRelation(key, *props->LayoutRule, property, System,
450451
inducedRules, debug);
451452
}
452453

453454
// If the intersection is equal to the new layout requirement, the
454455
// existing layout requirement is redundant.
455456
} else if (mergedLayout == newLayout) {
456-
if (checkRulePairOnce(*props->LayoutRule, ruleID)) {
457-
recordRelation(ruleID, *props->LayoutRule, System,
457+
if (checkRulePairOnce(ruleID, *props->LayoutRule)) {
458+
auto oldProperty = System.getRule(*props->LayoutRule).getLHS().back();
459+
recordRelation(key, ruleID, oldProperty, System,
458460
inducedRules, debug);
459461
}
460462

test/Generics/superclass_and_layout_requirement.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,32 @@
22

33
class C {}
44

5-
// CHECK: superclass_and_layout_requirement.(file).P1@
6-
// CHECK: Requirement signature: <Self where Self.T : C>
5+
// CHECK-LABEL: superclass_and_layout_requirement.(file).P1@
6+
// CHECK-LABEL: Requirement signature: <Self where Self.T : C>
77
protocol P1 {
88
associatedtype T : C
99
}
1010

11-
// CHECK: superclass_and_layout_requirement.(file).P2@
12-
// CHECK: Requirement signature: <Self where Self.T : C>
11+
// CHECK-LABEL: superclass_and_layout_requirement.(file).P2@
12+
// CHECK-LABEL: Requirement signature: <Self where Self.T : C>
1313
protocol P2 {
1414
associatedtype T where T : C, T : AnyObject
1515
}
16+
17+
// CHECK-LABEL: superclass_and_layout_requirement.(file).P3a@
18+
// CHECK-LABEL: Requirement signature: <Self where Self.T : P1>
19+
protocol P3a {
20+
associatedtype T : P1 where T.T : AnyObject
21+
}
22+
23+
// CHECK-LABEL: superclass_and_layout_requirement.(file).P4a@
24+
// CHECK-LABEL: Requirement signature: <Self where Self.T : AnyObject>
25+
protocol P4a {
26+
associatedtype T : AnyObject
27+
}
28+
29+
// CHECK-LABEL: superclass_and_layout_requirement.(file).P5a@
30+
// CHECK-LABEL: Requirement signature: <Self where Self.T : P4a, Self.T.T : C>
31+
protocol P5a {
32+
associatedtype T where T : P4a, T.T : C
33+
}

0 commit comments

Comments
 (0)