Skip to content

Commit 86c15ad

Browse files
committed
RequirementMachine: Generating conformances can reason about concrete conformances now
1 parent 0686cd5 commit 86c15ad

File tree

5 files changed

+61
-16
lines changed

5 files changed

+61
-16
lines changed

lib/AST/RequirementMachine/GeneratingConformances.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void RewriteLoop::findProtocolConformanceRules(
8989
for (unsigned ruleID : redundantRules) {
9090
const auto &rule = system.getRule(ruleID);
9191

92-
if (auto *proto = rule.isProtocolConformanceRule()) {
92+
if (auto *proto = rule.isAnyConformanceRule()) {
9393
if (rule.isIdentityConformanceRule()) {
9494
result[proto].SawIdentityConformance = true;
9595
continue;
@@ -116,7 +116,7 @@ void RewriteLoop::findProtocolConformanceRules(
116116
if (rule.isIdentityConformanceRule())
117117
break;
118118

119-
if (auto *proto = rule.isProtocolConformanceRule()) {
119+
if (auto *proto = rule.isAnyConformanceRule()) {
120120
if (step.StartOffset > 0 &&
121121
step.EndOffset == 0) {
122122
// Record the prefix term that is left unchanged by this rewrite step.
@@ -171,7 +171,7 @@ RewriteSystem::decomposeTermIntoConformanceRuleLeftHandSides(
171171

172172
#ifndef NDEBUG
173173
const auto &rule = getRule(step.RuleID);
174-
assert(rule.isProtocolConformanceRule());
174+
assert(rule.isAnyConformanceRule());
175175
assert(!rule.isIdentityConformanceRule());
176176
#endif
177177

@@ -199,7 +199,7 @@ RewriteSystem::decomposeTermIntoConformanceRuleLeftHandSides(
199199
MutableTerm term, unsigned ruleID,
200200
SmallVectorImpl<unsigned> &result) const {
201201
const auto &rule = getRule(ruleID);
202-
assert(rule.isProtocolConformanceRule());
202+
assert(rule.isAnyConformanceRule());
203203
assert(!rule.isIdentityConformanceRule());
204204

205205
// Compute domain(V).
@@ -412,15 +412,27 @@ void RewriteSystem::computeCandidateConformancePaths(
412412
bool RewriteSystem::isValidConformancePath(
413413
llvm::SmallDenseSet<unsigned, 4> &visited,
414414
llvm::DenseSet<unsigned> &redundantConformances,
415-
const llvm::SmallVectorImpl<unsigned> &path,
415+
const llvm::SmallVectorImpl<unsigned> &path, bool allowConcrete,
416416
const llvm::MapVector<unsigned, SmallVector<unsigned, 2>> &parentPaths,
417417
const llvm::MapVector<unsigned,
418418
std::vector<SmallVector<unsigned, 2>>>
419419
&conformancePaths) const {
420-
for (unsigned ruleID : path) {
420+
421+
unsigned lastIdx = path.size() - 1;
422+
423+
for (unsigned ruleIdx : indices(path)) {
424+
unsigned ruleID = path[ruleIdx];
421425
if (visited.count(ruleID) > 0)
422426
return false;
423427

428+
bool isLastElement = (ruleIdx == lastIdx);
429+
430+
if (!allowConcrete || !isLastElement) {
431+
if (getRule(ruleID).getLHS().back().getKind()
432+
== Symbol::Kind::ConcreteConformance)
433+
return false;
434+
}
435+
424436
if (redundantConformances.count(ruleID)) {
425437
SWIFT_DEFER {
426438
visited.erase(ruleID);
@@ -433,6 +445,7 @@ bool RewriteSystem::isValidConformancePath(
433445
bool foundValidConformancePath = false;
434446
for (const auto &otherPath : found->second) {
435447
if (isValidConformancePath(visited, redundantConformances, otherPath,
448+
allowConcrete && isLastElement,
436449
parentPaths, conformancePaths)) {
437450
foundValidConformancePath = true;
438451
break;
@@ -454,6 +467,7 @@ bool RewriteSystem::isValidConformancePath(
454467
// `T.[P.]A : Q', we want to make sure that we have a
455468
// non-redundant derivation for 'T : P'.
456469
if (!isValidConformancePath(visited, redundantConformances, found->second,
470+
/*allowConcrete=*/false,
457471
parentPaths, conformancePaths)) {
458472
return false;
459473
}
@@ -581,7 +595,8 @@ void RewriteSystem::verifyGeneratingConformanceEquations(
581595
static const ProtocolDecl *getParentConformanceForTerm(Term lhs) {
582596
// The last element is a protocol symbol, because this is the left hand side
583597
// of a conformance rule.
584-
assert(lhs.back().getKind() == Symbol::Kind::Protocol);
598+
assert(lhs.back().getKind() == Symbol::Kind::Protocol ||
599+
lhs.back().getKind() == Symbol::Kind::ConcreteConformance);
585600

586601
// The second to last symbol is either an associated type, protocol or generic
587602
// parameter symbol.
@@ -664,7 +679,7 @@ void RewriteSystem::computeGeneratingConformances(
664679
if (rule.containsUnresolvedSymbols())
665680
continue;
666681

667-
if (!rule.isProtocolConformanceRule())
682+
if (!rule.isAnyConformanceRule())
668683
continue;
669684

670685
conformanceRules.push_back(ruleID);
@@ -757,6 +772,7 @@ void RewriteSystem::computeGeneratingConformances(
757772
visited.insert(ruleID);
758773

759774
if (isValidConformancePath(visited, redundantConformances, path,
775+
/*allowConcrete=*/true,
760776
parentPaths, conformancePaths)) {
761777
redundantConformances.insert(ruleID);
762778
break;

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ isCandidateForDeletion(unsigned ruleID,
354354
// means that the set of generating conformances is always a superset
355355
// (or equal to) of the set of minimal protocol conformance
356356
// requirements that homotopy reduction alone would produce.
357-
if (rule.isProtocolConformanceRule()) {
357+
if (rule.isAnyConformanceRule()) {
358358
if (!redundantConformances)
359359
return false;
360360

@@ -634,7 +634,7 @@ void RewriteSystem::verifyRedundantConformances(
634634
"Permanent rule cannot be redundant");
635635
assert(!rule.isIdentityConformanceRule() &&
636636
"Identity conformance cannot be redundant");
637-
assert(rule.isProtocolConformanceRule() &&
637+
assert(rule.isAnyConformanceRule() &&
638638
"Redundant conformance is not a conformance rule?");
639639

640640
if (!rule.isRedundant()) {

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ RequirementMachine::buildRequirementsFromRules(
141141
}
142142

143143
case Symbol::Kind::ConcreteConformance:
144-
// FIXME
145-
llvm::errs() << "Concrete conformance: " << rule << "\n";
146-
break;
144+
// "Concrete conformance requirements" are not recorded in the generic
145+
// signature.
146+
return;
147147

148148
case Symbol::Kind::Name:
149149
case Symbol::Kind::AssociatedType:

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ Optional<Symbol> Rule::isPropertyRule() const {
4343
return property;
4444
}
4545

46-
/// If this is a rule of the form T.[p] => T where [p] is a protocol symbol,
47-
/// return the protocol, otherwise return nullptr.
46+
/// If this is a rule of the form T.[P] => T where [P] is a protocol symbol,
47+
/// return the protocol P, otherwise return nullptr.
4848
const ProtocolDecl *Rule::isProtocolConformanceRule() const {
4949
if (auto property = isPropertyRule()) {
5050
if (property->getKind() == Symbol::Kind::Protocol)
@@ -54,6 +54,33 @@ const ProtocolDecl *Rule::isProtocolConformanceRule() const {
5454
return nullptr;
5555
}
5656

57+
/// If this is a rule of the form T.[concrete: C : P] => T where
58+
/// [concrete: C : P] is a concrete conformance symbol, return the protocol P,
59+
/// otherwise return nullptr.
60+
const ProtocolDecl *Rule::isAnyConformanceRule() const {
61+
if (auto property = isPropertyRule()) {
62+
switch (property->getKind()) {
63+
case Symbol::Kind::ConcreteConformance:
64+
case Symbol::Kind::Protocol:
65+
return property->getProtocol();
66+
67+
case Symbol::Kind::Layout:
68+
case Symbol::Kind::Superclass:
69+
case Symbol::Kind::ConcreteType:
70+
return nullptr;
71+
72+
case Symbol::Kind::Name:
73+
case Symbol::Kind::AssociatedType:
74+
case Symbol::Kind::GenericParam:
75+
break;
76+
}
77+
78+
llvm_unreachable("Bad symbol kind");
79+
}
80+
81+
return nullptr;
82+
}
83+
5784
/// If this is a rule of the form [P].[P] => [P] where [P] is a protocol
5885
/// symbol, return true, otherwise return false.
5986
bool Rule::isIdentityConformanceRule() const {

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class Rule final {
8282

8383
const ProtocolDecl *isProtocolConformanceRule() const;
8484

85+
const ProtocolDecl *isAnyConformanceRule() const;
86+
8587
bool isIdentityConformanceRule() const;
8688

8789
bool isProtocolRefinementRule() const;
@@ -379,7 +381,7 @@ class RewriteSystem final {
379381
bool isValidConformancePath(
380382
llvm::SmallDenseSet<unsigned, 4> &visited,
381383
llvm::DenseSet<unsigned> &redundantConformances,
382-
const llvm::SmallVectorImpl<unsigned> &path,
384+
const llvm::SmallVectorImpl<unsigned> &path, bool allowConcrete,
383385
const llvm::MapVector<unsigned, SmallVector<unsigned, 2>> &parentPaths,
384386
const llvm::MapVector<unsigned,
385387
std::vector<SmallVector<unsigned, 2>>>

0 commit comments

Comments
 (0)