Skip to content

Commit 6ec2aad

Browse files
committed
RequirementMachine: Don't add unnecessary rule in merged associated types step
If we have a rewrite rule of the form X.[P:A] => X.[Q:A] We introduce a pair of rules X.[P:A] => X.[P&Q:A] X.[Q:A] => X.[P&Q:A] But in reality only the second one is necessary. The first one is redundant because you obtain the same result by applying the original rule followed by the second rule.
1 parent 7de1d9b commit 6ec2aad

File tree

2 files changed

+23
-25
lines changed

2 files changed

+23
-25
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
123123
lhs.back().getKind() == Symbol::Kind::AssociatedType &&
124124
rhs.back().getKind() == Symbol::Kind::AssociatedType &&
125125
lhs.back().getName() == rhs.back().getName()) {
126+
if (Debug.contains(DebugFlags::Merge)) {
127+
llvm::dbgs() << "## Associated type merge candidate ";
128+
llvm::dbgs() << lhs << " => " << rhs << "\n\n";
129+
}
126130
MergedAssociatedTypes.emplace_back(lhs, rhs);
127131
}
128132

lib/AST/RequirementMachine/RewriteSystemCompletion.cpp

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -152,39 +152,38 @@ Symbol RewriteContext::mergeAssociatedTypes(Symbol lhs, Symbol rhs,
152152
/// [P2].T => [P2:T]
153153
/// [P1:T].[P1] => [P1:T]
154154
/// [P2:T].[P1] => [P2:T]
155-
/// <T>.[P1] => <T>
156-
/// <T>.[P2] => <T>
157-
/// <T>.T => <T>.[P1:T]
158-
/// <T>.[P2:T] => <T>.[P1:T]
155+
/// τ_0_0.[P1] => τ_0_0
156+
/// τ_0_0.[P2] => τ_0_0
157+
/// τ_0_0.T => τ_0_0.[P1:T]
158+
/// τ_0_0.[P2:T] => τ_0_0.[P1:T]
159159
///
160160
/// The completion procedure ends up adding an infinite series of rules of the
161161
/// form
162162
///
163-
/// <T>.[P1:T].[P2] => <T>.[P1:T]
164-
/// <T>.[P1:T].[P2:T] => <T>.[P1:T].[P1:T]
163+
/// τ_0_0.[P1:T].[P2] => τ_0_0.[P1:T]
164+
/// τ_0_0.[P1:T].[P2:T] => τ_0_0.[P1:T].[P1:T]
165165
///
166-
/// <T>.[P1:T].[P1:T].[P2] => <T>.[P1:T].[P1:T]
167-
/// <T>.[P1:T].[P1:T].[P2:T] => <T>.[P1:T].[P1:T].[P1:T]
166+
/// τ_0_0.[P1:T].[P1:T].[P2] => τ_0_0.[P1:T].[P1:T]
167+
/// τ_0_0.[P1:T].[P1:T].[P2:T] => τ_0_0.[P1:T].[P1:T].[P1:T]
168168
///
169-
/// <T>.[P1:T].[P1:T].[P1:T].[P2] => <T>.[P1:T].[P1:T].[P1.T]
170-
/// <T>.[P1:T].[P1:T].[P1:T].[P2:T] => <T>.[P1:T].[P1:T].[P1:T].[P1.T]
169+
/// τ_0_0.[P1:T].[P1:T].[P1:T].[P2] => τ_0_0.[P1:T].[P1:T].[P1.T]
170+
/// τ_0_0.[P1:T].[P1:T].[P1:T].[P2:T] => τ_0_0.[P1:T].[P1:T].[P1:T].[P1.T]
171171
///
172172
/// The difficulty here stems from the fact that an arbitrary sequence of
173-
/// [P1:T] following a <T> is known to conform to P2, but P1:T itself
173+
/// [P1:T] following a τ_0_0 is known to conform to P2, but P1:T itself
174174
/// does not conform to P2.
175175
///
176176
/// We use a heuristic to compute a completion in this case by using
177177
/// merged associated type terms.
178178
///
179179
/// The key is the following rewrite rule:
180180
///
181-
/// <T>.[P2:T] => <T>.[P1:T]
181+
/// τ_0_0.[P2:T] => τ_0_0.[P1:T]
182182
///
183-
/// When we add this rule, we introduce a new merged symbol [P1&P2:T] in
184-
/// a pair of new rules:
183+
/// When we add this rule, we introduce a new merged symbol [P1&P2:T] and
184+
/// a new rule:
185185
///
186-
/// <T>.[P1:T] => <T>.[P1&P2:T]
187-
/// <T>.[P2:T] => <T>.[P1&P2:T]
186+
/// τ_0_0.[P1:T] => τ_0_0.[P1&P2:T]
188187
///
189188
/// We also look for any existing rules of the form [P1:T].[Q] => [P1:T]
190189
/// or [P2:T].[Q] => [P2:T], and introduce a new rule:
@@ -194,15 +193,13 @@ Symbol RewriteContext::mergeAssociatedTypes(Symbol lhs, Symbol rhs,
194193
/// In the above example, we have such a rule for Q == P1 and Q == P2, so
195194
/// in total we end up adding the following four rules:
196195
///
197-
/// <T>.[P1:T] => <T>.[P1&P2:T]
198-
/// <T>.[P2:T] => <T>.[P1&P2:T]
196+
/// τ_0_0.[P1:T] => τ_0_0.[P1&P2:T]
199197
/// [P1&P2:T].[P1] => [P1&P2:T]
200198
/// [P1&P2:T].[P2] => [P1&P2:T]
201199
///
202200
/// Intuitively, since the conformance requirements on the merged term
203-
/// are not prefixed by the root <T>, they apply at any level; we've
204-
/// "tied off" the recursion, and now the rewrite system has a confluent
205-
/// completion.
201+
/// are not prefixed by the root τ_0_0, they apply at any level; we've
202+
/// "tied off" the recursion, and the rewrite system is now convergent.
206203
void RewriteSystem::processMergedAssociatedTypes() {
207204
if (MergedAssociatedTypes.empty())
208205
return;
@@ -220,7 +217,7 @@ void RewriteSystem::processMergedAssociatedTypes() {
220217
// X.[P1:T] => X.[P1&P2:T]
221218
// X.[P2:T] => X.[P1&P2:T]
222219
if (Debug.contains(DebugFlags::Merge)) {
223-
llvm::dbgs() << "## Associated type merge candidate ";
220+
llvm::dbgs() << "## Processing associated type merge candidate ";
224221
llvm::dbgs() << lhs << " => " << rhs << "\n";
225222
}
226223

@@ -237,9 +234,6 @@ void RewriteSystem::processMergedAssociatedTypes() {
237234
// Add the rule X.[P1:T] => X.[P1&P2:T].
238235
addRule(rhs, mergedTerm);
239236

240-
// Add the rule X.[P2:T] => X.[P1&P2:T].
241-
addRule(lhs, mergedTerm);
242-
243237
// Collect new rules here so that we're not adding rules while traversing
244238
// the trie.
245239
SmallVector<std::pair<MutableTerm, MutableTerm>, 2> inducedRules;

0 commit comments

Comments
 (0)