Skip to content

Commit 7708c75

Browse files
committed
RequirementMachine: Introduce RewriteStep::SameTypeWitness
1 parent 5a2b193 commit 7708c75

File tree

4 files changed

+113
-1
lines changed

4 files changed

+113
-1
lines changed

lib/AST/RequirementMachine/GeneratingConformances.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ void RewriteLoop::findProtocolConformanceRules(
138138
case RewriteStep::ConcreteConformance:
139139
case RewriteStep::SuperclassConformance:
140140
case RewriteStep::ConcreteTypeWitness:
141+
case RewriteStep::SameTypeWitness:
141142
break;
142143
}
143144
}

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
9393
case RewriteStep::ConcreteConformance:
9494
case RewriteStep::SuperclassConformance:
9595
case RewriteStep::ConcreteTypeWitness:
96+
case RewriteStep::SameTypeWitness:
9697
break;
9798
}
9899

@@ -210,6 +211,7 @@ RewritePath RewritePath::splitCycleAtRule(unsigned ruleID) const {
210211
case RewriteStep::ConcreteConformance:
211212
case RewriteStep::SuperclassConformance:
212213
case RewriteStep::ConcreteTypeWitness:
214+
case RewriteStep::SameTypeWitness:
213215
break;
214216
}
215217

@@ -309,6 +311,7 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
309311
case RewriteStep::ConcreteConformance:
310312
case RewriteStep::SuperclassConformance:
311313
case RewriteStep::ConcreteTypeWitness:
314+
case RewriteStep::SameTypeWitness:
312315
newSteps.push_back(step);
313316
break;
314317
}

lib/AST/RequirementMachine/RewriteLoop.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ void RewriteStep::dump(llvm::raw_ostream &out,
8585
: "ConcreteTypeWitness");
8686
break;
8787
}
88+
case SameTypeWitness: {
89+
evaluator.applySameTypeWitness(*this, system);
90+
91+
out << (Inverse ? "SameTypeWitness⁻¹"
92+
: "SameTypeWitness");
93+
break;
94+
}
8895

8996
}
9097
}
@@ -482,6 +489,71 @@ void RewritePathEvaluator::applyConcreteTypeWitness(const RewriteStep &step,
482489
}
483490
}
484491

492+
void RewritePathEvaluator::applySameTypeWitness(const RewriteStep &step,
493+
const RewriteSystem &system) {
494+
checkA();
495+
auto &term = A.back();
496+
497+
const auto &witness = system.getConcreteTypeWitness(step.RuleID);
498+
auto fail = [&]() {
499+
llvm::errs() << "Bad concrete type witness term:\n";
500+
llvm::errs() << term << "\n\n";
501+
llvm::errs() << "Conformance: " << witness.ConcreteConformance << "\n";
502+
llvm::errs() << "Assoc type: " << witness.AssocType << "\n";
503+
llvm::errs() << "Concrete type: " << witness.ConcreteType << "\n";
504+
abort();
505+
};
506+
507+
#ifndef NDEBUG
508+
if ((witness.ConcreteType.getConcreteType() !=
509+
witness.ConcreteConformance.getConcreteType()) ||
510+
(witness.ConcreteType.getSubstitutions() !=
511+
witness.ConcreteConformance.getSubstitutions())) {
512+
fail();
513+
}
514+
#endif
515+
516+
if (!step.Inverse) {
517+
// Make sure the term takes the following form, where |V| == EndOffset:
518+
//
519+
// U.[concrete: C : P].[P:X].V
520+
if (term.size() <= step.EndOffset + 2 ||
521+
*(term.end() - step.EndOffset - 2) != witness.ConcreteConformance ||
522+
*(term.end() - step.EndOffset - 1) != witness.AssocType) {
523+
fail();
524+
}
525+
526+
// Get the subterm U.[concrete: C : P].
527+
MutableTerm newTerm(term.begin(), term.end() - step.EndOffset - 1);
528+
529+
// Add the subterm V, to get U.[concrete: C : P].V.
530+
newTerm.append(term.end() - step.EndOffset, term.end());
531+
532+
term = newTerm;
533+
} else {
534+
// Make sure the term takes the following form, where |V| == EndOffset:
535+
//
536+
// U.[concrete: C : P].V
537+
if (term.size() <= step.EndOffset + 1 ||
538+
*(term.end() - step.EndOffset - 1) != witness.ConcreteConformance) {
539+
fail();
540+
}
541+
542+
// Get the subterm U.[concrete: C : P].
543+
MutableTerm newTerm(term.begin(), term.end() - step.EndOffset);
544+
545+
// Add the symbol [P:X].
546+
newTerm.add(witness.AssocType);
547+
548+
// Add the subterm V, to get
549+
//
550+
// U.[concrete: C : P].[P:X].V
551+
newTerm.append(term.end() - step.EndOffset, term.end());
552+
553+
term = newTerm;
554+
}
555+
}
556+
485557
void RewritePathEvaluator::apply(const RewriteStep &step,
486558
const RewriteSystem &system) {
487559
switch (step.Kind) {
@@ -509,5 +581,9 @@ void RewritePathEvaluator::apply(const RewriteStep &step,
509581
case RewriteStep::ConcreteTypeWitness:
510582
applyConcreteTypeWitness(step, system);
511583
break;
584+
585+
case RewriteStep::SameTypeWitness:
586+
applySameTypeWitness(step, system);
587+
break;
512588
}
513589
}

lib/AST/RequirementMachine/RewriteLoop.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ struct RewritePathEvaluator;
3434
/// Records an evaluation step in a rewrite path.
3535
struct RewriteStep {
3636
enum StepKind : unsigned {
37+
///
38+
/// *** Rewrite step kinds introduced by Knuth-Bendix completion ***
39+
///
40+
3741
/// Apply a rewrite rule to the term at the top of the A stack.
3842
///
3943
/// Formally, this is a whiskered, oriented rewrite rule. For example,
@@ -60,6 +64,10 @@ struct RewriteStep {
6064
/// The StartOffset field encodes the length of the prefix.
6165
AdjustConcreteType,
6266

67+
///
68+
/// *** Rewrite step kinds introduced by simplifySubstitutions() ***
69+
///
70+
6371
/// Move a term from the A stack to the B stack (if not inverted) or
6472
/// B stack to A stack (if inverted).
6573
Shift,
@@ -75,6 +83,10 @@ struct RewriteStep {
7583
/// The RuleID field encodes the number of substitutions.
7684
Decompose,
7785

86+
///
87+
/// *** Rewrite step kinds introduced by the property map ***
88+
///
89+
7890
/// If not inverted: the top of the A stack must be a term ending in a
7991
/// concrete type symbol [concrete: C] followed by a protocol symbol [P].
8092
/// These two symbols are combined into a single concrete conformance
@@ -109,7 +121,19 @@ struct RewriteStep {
109121
/// RewriteSystem::recordConcreteTypeWitness(). This index is then
110122
/// passed in to RewriteSystem::getConcreteTypeWitness() when applying
111123
/// the step.
112-
ConcreteTypeWitness
124+
ConcreteTypeWitness,
125+
126+
/// If not inverted: the top of the A stack must be a term ending in a
127+
/// concrete conformance symbol [concrete: C : P] followed by an associated
128+
/// type symbol [P:X]. The associated type symbol is eliminated.
129+
///
130+
/// If inverted: the associated type symbol [P:X] is introduced.
131+
///
132+
/// The RuleID field is repurposed to store the result of calling
133+
/// RewriteSystem::recordConcreteTypeWitness(). This index is then
134+
/// passed in to RewriteSystem::getConcreteTypeWitness() when applying
135+
/// the step.
136+
SameTypeWitness,
113137
};
114138

115139
/// The rewrite step kind.
@@ -184,6 +208,11 @@ struct RewriteStep {
184208
/*ruleID=*/witnessID, inverse);
185209
}
186210

211+
static RewriteStep forSameTypeWitness(unsigned witnessID, bool inverse) {
212+
return RewriteStep(SameTypeWitness, /*startOffset=*/0, /*endOffset=*/0,
213+
/*ruleID=*/witnessID, inverse);
214+
}
215+
187216
bool isInContext() const {
188217
return StartOffset > 0 || EndOffset > 0;
189218
}
@@ -353,6 +382,9 @@ struct RewritePathEvaluator {
353382
void applyConcreteTypeWitness(const RewriteStep &step,
354383
const RewriteSystem &system);
355384

385+
void applySameTypeWitness(const RewriteStep &step,
386+
const RewriteSystem &system);
387+
356388
void dump(llvm::raw_ostream &out) const;
357389
};
358390

0 commit comments

Comments
 (0)