Skip to content

Commit 7427b68

Browse files
committed
RequirementMachine: Introduce RewriteStep::ConcreteConformance and ::SuperclassConformance
1 parent e9b94c1 commit 7427b68

File tree

4 files changed

+137
-6
lines changed

4 files changed

+137
-6
lines changed

lib/AST/RequirementMachine/GeneratingConformances.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ void RewriteLoop::findProtocolConformanceRules(
134134
case RewriteStep::AdjustConcreteType:
135135
case RewriteStep::Shift:
136136
case RewriteStep::Decompose:
137+
case RewriteStep::ConcreteConformance:
138+
case RewriteStep::SuperclassConformance:
137139
break;
138140
}
139141
}

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
9696
case RewriteStep::AdjustConcreteType:
9797
case RewriteStep::Shift:
9898
case RewriteStep::Decompose:
99+
case RewriteStep::ConcreteConformance:
100+
case RewriteStep::SuperclassConformance:
99101
break;
100102
}
101103

@@ -210,6 +212,8 @@ RewritePath RewritePath::splitCycleAtRule(unsigned ruleID) const {
210212
case RewriteStep::AdjustConcreteType:
211213
case RewriteStep::Shift:
212214
case RewriteStep::Decompose:
215+
case RewriteStep::ConcreteConformance:
216+
case RewriteStep::SuperclassConformance:
213217
break;
214218
}
215219

@@ -306,6 +310,8 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
306310
case RewriteStep::AdjustConcreteType:
307311
case RewriteStep::Shift:
308312
case RewriteStep::Decompose:
313+
case RewriteStep::ConcreteConformance:
314+
case RewriteStep::SuperclassConformance:
309315
newSteps.push_back(step);
310316
break;
311317
}
@@ -339,6 +345,10 @@ bool RewriteStep::isInverseOf(const RewriteStep &other) const {
339345

340346
case RewriteStep::Decompose:
341347
return RuleID == other.RuleID;
348+
349+
case RewriteStep::ConcreteConformance:
350+
case RewriteStep::SuperclassConformance:
351+
return true;
342352
}
343353

344354
assert(EndOffset == other.EndOffset && "Bad whiskering?");
@@ -465,7 +475,7 @@ bool RewritePath::computeCyclicallyReducedLoop(MutableTerm &basepoint,
465475
break;
466476

467477
// Update the basepoint by applying the first step in the path.
468-
left.apply(evaluator, system);
478+
evaluator.apply(left, system);
469479

470480
++count;
471481
}
@@ -522,14 +532,16 @@ bool RewriteLoop::isInContext(const RewriteSystem &system) const {
522532
case RewriteStep::AdjustConcreteType:
523533
case RewriteStep::Shift:
524534
case RewriteStep::Decompose:
535+
case RewriteStep::ConcreteConformance:
536+
case RewriteStep::SuperclassConformance:
525537
break;
526538
}
527539

528540
if (minStartOffset == 0 && minEndOffset == 0)
529541
break;
530542
}
531543

532-
step.apply(evaluator, system);
544+
evaluator.apply(step, system);
533545
}
534546

535547
return (minStartOffset > 0 || minEndOffset > 0);

lib/AST/RequirementMachine/RewriteLoop.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ void RewriteStep::dump(llvm::raw_ostream &out,
6161
out << RuleID << ")";
6262
break;
6363
}
64+
case ConcreteConformance: {
65+
evaluator.applyConcreteConformance(*this, system);
66+
67+
out << (Inverse ? "ConcreteConformance⁻¹"
68+
: "ConcreteConformance");
69+
break;
70+
}
71+
case SuperclassConformance: {
72+
evaluator.applyConcreteConformance(*this, system);
73+
74+
out << (Inverse ? "SuperclassConformance⁻¹"
75+
: "SuperclassConformance");
76+
break;
77+
}
6478
}
6579
}
6680

@@ -312,6 +326,69 @@ void RewritePathEvaluator::applyDecompose(const RewriteStep &step,
312326
}
313327
}
314328

329+
void
330+
RewritePathEvaluator::applyConcreteConformance(const RewriteStep &step,
331+
const RewriteSystem &system) {
332+
checkA();
333+
auto &term = A.back();
334+
335+
auto &ctx = system.getRewriteContext();
336+
337+
if (!step.Inverse) {
338+
assert(term.size() > 2);
339+
auto concreteType = *(term.end() - 2);
340+
auto proto = *(term.end() - 1);
341+
assert(proto.getKind() == Symbol::Kind::Protocol);
342+
343+
MutableTerm newTerm(term.begin(), term.end() - 2);
344+
if (step.Kind == RewriteStep::ConcreteConformance) {
345+
assert(concreteType.getKind() == Symbol::Kind::ConcreteType);
346+
347+
newTerm.add(Symbol::forConcreteConformance(
348+
concreteType.getConcreteType(),
349+
concreteType.getSubstitutions(),
350+
proto.getProtocol(),
351+
ctx));
352+
} else {
353+
assert(step.Kind == RewriteStep::SuperclassConformance);
354+
assert(concreteType.getKind() == Symbol::Kind::Superclass);
355+
356+
newTerm.add(Symbol::forConcreteConformance(
357+
concreteType.getSuperclass(),
358+
concreteType.getSubstitutions(),
359+
proto.getProtocol(),
360+
ctx));
361+
}
362+
363+
term = newTerm;
364+
} else {
365+
assert(term.size() > 1);
366+
auto concreteConformance = term.back();
367+
assert(concreteConformance.getKind() == Symbol::Kind::ConcreteConformance);
368+
369+
MutableTerm newTerm(term.begin(), term.end() - 1);
370+
371+
if (step.Kind == RewriteStep::ConcreteConformance) {
372+
newTerm.add(Symbol::forConcreteType(
373+
concreteConformance.getConcreteType(),
374+
concreteConformance.getSubstitutions(),
375+
ctx));
376+
} else {
377+
assert(step.Kind == RewriteStep::SuperclassConformance);
378+
newTerm.add(Symbol::forSuperclass(
379+
concreteConformance.getConcreteType(),
380+
concreteConformance.getSubstitutions(),
381+
ctx));
382+
}
383+
384+
newTerm.add(Symbol::forProtocol(
385+
concreteConformance.getProtocol(),
386+
ctx));
387+
388+
term = newTerm;
389+
}
390+
}
391+
315392
void RewritePathEvaluator::apply(const RewriteStep &step,
316393
const RewriteSystem &system) {
317394
switch (step.Kind) {
@@ -330,5 +407,10 @@ void RewritePathEvaluator::apply(const RewriteStep &step,
330407
case RewriteStep::Decompose:
331408
applyDecompose(step, system);
332409
break;
410+
411+
case RewriteStep::ConcreteConformance:
412+
case RewriteStep::SuperclassConformance:
413+
applyConcreteConformance(step, system);
414+
break;
333415
}
334416
}

lib/AST/RequirementMachine/RewriteLoop.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,41 @@ struct RewriteStep {
7373
/// new substitutions replace the substitutions in that symbol.
7474
///
7575
/// The RuleID field encodes the number of substitutions.
76-
Decompose
76+
Decompose,
77+
78+
/// If not inverted: the top of the A stack must be a term ending in a
79+
/// concrete type symbol [concrete: C] followed by a protocol symbol [P].
80+
/// These two symbols are combined into a single concrete conformance
81+
/// symbol [concrete: C : P].
82+
///
83+
/// If inverted: the top of the A stack must be a term ending in a
84+
/// concrete conformance symbol [concrete: C : P]. This symbol is replaced
85+
/// with the concrete type symbol [concrete: C] followed by the protocol
86+
/// symbol [P].
87+
ConcreteConformance,
88+
89+
/// If not inverted: the top of the A stack must be a term ending in a
90+
/// superclass symbol [superclass: C] followed by a protocol symbol [P].
91+
/// These two symbols are combined into a single concrete conformance
92+
/// symbol [concrete: C : P].
93+
///
94+
/// If inverted: the top of the A stack must be a term ending in a
95+
/// concrete conformance symbol [concrete: C : P]. This symbol is replaced
96+
/// with the superclass symbol [superclass: C] followed by the protocol
97+
/// symbol [P].
98+
SuperclassConformance
7799
};
78100

79101
/// The rewrite step kind.
80-
StepKind Kind : 2;
102+
StepKind Kind : 3;
81103

82104
/// The size of the left whisker, which is the position within the term where
83105
/// the rule is being applied. In A.(X => Y).B, this is |A|=1.
84-
unsigned StartOffset : 15;
106+
unsigned StartOffset : 14;
85107

86108
/// The size of the right whisker, which is the length of the remaining suffix
87109
/// after the rule is applied. In A.(X => Y).B, this is |B|=1.
88-
unsigned EndOffset : 15;
110+
unsigned EndOffset : 14;
89111

90112
/// If Kind is ApplyRewriteRule, the index of the rule in the rewrite system.
91113
///
@@ -132,6 +154,16 @@ struct RewriteStep {
132154
/*ruleID=*/numSubstitutions, inverse);
133155
}
134156

157+
static RewriteStep forConcreteConformance(bool inverse) {
158+
return RewriteStep(ConcreteConformance, /*startOffset=*/0, /*endOffset=*/0,
159+
/*ruleID=*/0, inverse);
160+
}
161+
162+
static RewriteStep forSuperclassConformance(bool inverse) {
163+
return RewriteStep(SuperclassConformance, /*startOffset=*/0, /*endOffset=*/0,
164+
/*ruleID=*/0, inverse);
165+
}
166+
135167
bool isInContext() const {
136168
return StartOffset > 0 || EndOffset > 0;
137169
}
@@ -303,6 +335,9 @@ struct RewritePathEvaluator {
303335
void applyDecompose(const RewriteStep &step,
304336
const RewriteSystem &system);
305337

338+
void applyConcreteConformance(const RewriteStep &step,
339+
const RewriteSystem &system);
340+
306341
void dump(llvm::raw_ostream &out) const;
307342
};
308343

0 commit comments

Comments
 (0)