Skip to content

Commit b999cea

Browse files
committed
RequirementMachine: Try to minimize away concrete conformances first
1 parent ffd675d commit b999cea

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

lib/AST/RequirementMachine/GeneratingConformances.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class GeneratingConformances {
219219

220220
void verifyGeneratingConformanceEquations() const;
221221

222-
void computeGeneratingConformances();
222+
void computeGeneratingConformances(bool firstPass);
223223

224224
void verifyGeneratingConformances() const;
225225

@@ -799,10 +799,37 @@ void GeneratingConformances::verifyGeneratingConformanceEquations() const {
799799

800800
/// Find a minimal set of generating conformances by marking all other
801801
/// conformances redundant.
802-
void GeneratingConformances::computeGeneratingConformances() {
802+
///
803+
/// In the first pass, we only consider conformance requirements that are
804+
/// made redundant by concrete conformances.
805+
void GeneratingConformances::computeGeneratingConformances(
806+
bool firstPass) {
803807
for (unsigned ruleID : ConformanceRules) {
804808
const auto &paths = ConformancePaths[ruleID];
805809

810+
if (firstPass) {
811+
bool derivedViaConcrete = false;
812+
for (const auto &path : paths) {
813+
if (path.empty())
814+
break;
815+
816+
if (System.getRule(path.back()).getLHS().back().getKind() ==
817+
Symbol::Kind::ConcreteConformance) {
818+
derivedViaConcrete = true;
819+
break;
820+
}
821+
}
822+
823+
// If this rule doesn't involve concrete conformances it will be
824+
// considered in the second pass.
825+
if (!derivedViaConcrete)
826+
continue;
827+
} else {
828+
// Ignore rules already determined to be redundant by the first pass.
829+
if (RedundantConformances.count(ruleID) > 0)
830+
continue;
831+
}
832+
806833
bool isProtocolRefinement = ProtocolRefinements.count(ruleID) > 0;
807834

808835
for (const auto &path : paths) {
@@ -893,7 +920,8 @@ void RewriteSystem::computeGeneratingConformances(
893920
}
894921

895922
builder.verifyGeneratingConformanceEquations();
896-
builder.computeGeneratingConformances();
923+
builder.computeGeneratingConformances(/*firstPass=*/true);
924+
builder.computeGeneratingConformances(/*firstPass=*/false);
897925
builder.verifyGeneratingConformances();
898926

899927
if (Debug.contains(DebugFlags::GeneratingConformances)) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify 2>&1 | %FileCheck %s
2+
3+
protocol P {
4+
associatedtype T
5+
}
6+
struct S : P {
7+
typealias T = S
8+
}
9+
10+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).R0@
11+
// CHECK-LABEL: Requirement signature: <Self where Self.A == S>
12+
13+
protocol R0 {
14+
associatedtype A where A : P, A == S
15+
}
16+
17+
////
18+
19+
struct G<T> : P {}
20+
21+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).R1@
22+
// CHECK-LABEL: Requirement signature: <Self where Self.B == G<Self.A>>
23+
24+
protocol R1 {
25+
associatedtype A
26+
associatedtype B where B : P, B == G<A>
27+
}
28+
29+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).R2@
30+
// CHECK-LABEL: Requirement signature: <Self where Self.A == G<Self.B>>
31+
32+
protocol R2 {
33+
associatedtype A where A : P, A == G<B>
34+
associatedtype B
35+
}
36+
37+
////
38+
39+
protocol PP {
40+
associatedtype T : P
41+
}
42+
43+
struct GG<T : P> : PP {}
44+
45+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR3@
46+
// CHECK-LABEL: Requirement signature: <Self where Self.A : P, Self.B == GG<Self.A>>
47+
48+
protocol RR3 {
49+
associatedtype A : P
50+
associatedtype B where B : PP, B == GG<A>
51+
}
52+
53+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR4@
54+
// CHECK-LABEL: Requirement signature: <Self where Self.A == GG<Self.B>, Self.B : P>
55+
56+
protocol RR4 {
57+
associatedtype A where A : PP, A == GG<B>
58+
associatedtype B : P
59+
}
60+
61+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR5@
62+
// CHECK-LABEL: Requirement signature: <Self where Self.A : PP, Self.B == GG<Self.A.T>>
63+
64+
protocol RR5 {
65+
associatedtype A : PP
66+
associatedtype B where B : PP, B == GG<A.T>
67+
}
68+
69+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR6@
70+
// CHECK-LABEL: Requirement signature: <Self where Self.A == GG<Self.B.T>, Self.B : PP>
71+
72+
protocol RR6 {
73+
associatedtype A where A : PP, A == GG<B.T>
74+
associatedtype B : PP
75+
}

0 commit comments

Comments
 (0)