Skip to content

Commit 654953c

Browse files
committed
RequirementMachine: Introduce RewriteStep::ConcreteTypeWitness
1 parent c6441c0 commit 654953c

File tree

4 files changed

+97
-1
lines changed

4 files changed

+97
-1
lines changed

lib/AST/RequirementMachine/GeneratingConformances.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ void RewriteLoop::findProtocolConformanceRules(
137137
case RewriteStep::Decompose:
138138
case RewriteStep::ConcreteConformance:
139139
case RewriteStep::SuperclassConformance:
140+
case RewriteStep::ConcreteTypeWitness:
140141
break;
141142
}
142143
}

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
9292
case RewriteStep::Decompose:
9393
case RewriteStep::ConcreteConformance:
9494
case RewriteStep::SuperclassConformance:
95+
case RewriteStep::ConcreteTypeWitness:
9596
break;
9697
}
9798

@@ -208,6 +209,7 @@ RewritePath RewritePath::splitCycleAtRule(unsigned ruleID) const {
208209
case RewriteStep::Decompose:
209210
case RewriteStep::ConcreteConformance:
210211
case RewriteStep::SuperclassConformance:
212+
case RewriteStep::ConcreteTypeWitness:
211213
break;
212214
}
213215

@@ -306,6 +308,7 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
306308
case RewriteStep::Decompose:
307309
case RewriteStep::ConcreteConformance:
308310
case RewriteStep::SuperclassConformance:
311+
case RewriteStep::ConcreteTypeWitness:
309312
newSteps.push_back(step);
310313
break;
311314
}

lib/AST/RequirementMachine/RewriteLoop.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ void RewriteStep::dump(llvm::raw_ostream &out,
7878
: "SuperclassConformance");
7979
break;
8080
}
81+
case ConcreteTypeWitness: {
82+
evaluator.applyConcreteTypeWitness(*this, system);
83+
84+
out << (Inverse ? "ConcreteTypeWitness⁻¹"
85+
: "ConcreteTypeWitness");
86+
break;
87+
}
88+
8189
}
8290
}
8391

@@ -416,6 +424,64 @@ RewritePathEvaluator::applyConcreteConformance(const RewriteStep &step,
416424
}
417425
}
418426

427+
void RewritePathEvaluator::applyConcreteTypeWitness(const RewriteStep &step,
428+
const RewriteSystem &system) {
429+
checkA();
430+
auto &term = A.back();
431+
432+
const auto &witness = system.getConcreteTypeWitness(step.RuleID);
433+
auto fail = [&]() {
434+
llvm::errs() << "Bad concrete type witness term:\n";
435+
llvm::errs() << term << "\n\n";
436+
llvm::errs() << "Conformance: " << witness.ConcreteConformance << "\n";
437+
llvm::errs() << "Assoc type: " << witness.AssocType << "\n";
438+
llvm::errs() << "Concrete type: " << witness.ConcreteType << "\n";
439+
abort();
440+
};
441+
442+
if (!step.Inverse) {
443+
// Make sure the term takes the following form, where |V| == EndOffset:
444+
//
445+
// U.[concrete: C : P].[P:X].[concrete: C.X].V
446+
if (term.size() <= step.EndOffset + 3 ||
447+
*(term.end() - step.EndOffset - 3) != witness.ConcreteConformance ||
448+
*(term.end() - step.EndOffset - 2) != witness.AssocType ||
449+
*(term.end() - step.EndOffset - 1) != witness.ConcreteType) {
450+
fail();
451+
}
452+
453+
// Get the subterm U.[concrete: C : P].[P:X].
454+
MutableTerm newTerm(term.begin(), term.end() - step.EndOffset - 1);
455+
456+
// Add the subterm V, to get U.[concrete: C : P].[P:X].V.
457+
newTerm.append(term.end() - step.EndOffset, term.end());
458+
459+
term = newTerm;
460+
} else {
461+
// Make sure the term takes the following form, where |V| == EndOffset:
462+
//
463+
// U.[concrete: C : P].[P:X].V
464+
if (term.size() <= step.EndOffset + 2 ||
465+
*(term.end() - step.EndOffset - 2) != witness.ConcreteConformance ||
466+
*(term.end() - step.EndOffset - 1) != witness.AssocType) {
467+
fail();
468+
}
469+
470+
// Get the subterm U.[concrete: C : P].[P:X].
471+
MutableTerm newTerm(term.begin(), term.end() - step.EndOffset);
472+
473+
// Add the symbol [concrete: C.X].
474+
newTerm.add(witness.ConcreteType);
475+
476+
// Add the subterm V, to get
477+
//
478+
// U.[concrete: C : P].[P:X].[concrete: C.X].V
479+
newTerm.append(term.end() - step.EndOffset, term.end());
480+
481+
term = newTerm;
482+
}
483+
}
484+
419485
void RewritePathEvaluator::apply(const RewriteStep &step,
420486
const RewriteSystem &system) {
421487
switch (step.Kind) {
@@ -439,5 +505,9 @@ void RewritePathEvaluator::apply(const RewriteStep &step,
439505
case RewriteStep::SuperclassConformance:
440506
applyConcreteConformance(step, system);
441507
break;
508+
509+
case RewriteStep::ConcreteTypeWitness:
510+
applyConcreteTypeWitness(step, system);
511+
break;
442512
}
443513
}

lib/AST/RequirementMachine/RewriteLoop.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,21 @@ struct RewriteStep {
9595
/// concrete conformance symbol [concrete: C : P]. This symbol is replaced
9696
/// with the superclass symbol [superclass: C] followed by the protocol
9797
/// symbol [P].
98-
SuperclassConformance
98+
SuperclassConformance,
99+
100+
/// If not inverted: the top of the A stack must be a term ending in a
101+
/// concrete conformance symbol [concrete: C : P] followed by an associated
102+
/// type symbol [P:X], and the concrete type symbol [concrete: C.X] for the
103+
/// type witness of 'X' in the conformance 'C : P'. The concrete type symbol
104+
/// is eliminated.
105+
///
106+
/// If inverted: the concrete type symbol [concrete: C.X] is introduced.
107+
///
108+
/// The RuleID field is repurposed to store the result of calling
109+
/// RewriteSystem::recordConcreteTypeWitness(). This index is then
110+
/// passed in to RewriteSystem::getConcreteTypeWitness() when applying
111+
/// the step.
112+
ConcreteTypeWitness
99113
};
100114

101115
/// The rewrite step kind.
@@ -165,6 +179,11 @@ struct RewriteStep {
165179
/*ruleID=*/0, inverse);
166180
}
167181

182+
static RewriteStep forConcreteTypeWitness(unsigned witnessID, bool inverse) {
183+
return RewriteStep(ConcreteTypeWitness, /*startOffset=*/0, /*endOffset=*/0,
184+
/*ruleID=*/witnessID, inverse);
185+
}
186+
168187
bool isInContext() const {
169188
return StartOffset > 0 || EndOffset > 0;
170189
}
@@ -331,6 +350,9 @@ struct RewritePathEvaluator {
331350
void applyConcreteConformance(const RewriteStep &step,
332351
const RewriteSystem &system);
333352

353+
void applyConcreteTypeWitness(const RewriteStep &step,
354+
const RewriteSystem &system);
355+
334356
void dump(llvm::raw_ostream &out) const;
335357
};
336358

0 commit comments

Comments
 (0)