Skip to content

Commit 1f83cd0

Browse files
committed
RequirementMachine: Don't eliminate a rule via a path involving a protocol typealias rule
If a rule is not a protocol typealias rule, and does not contain any unresolved symbols, do not attempt to eliminate it via a protocol typealias rule. This fixes a bunch of cases where the RequirementMachine was overly-eager to remove rules.
1 parent a259844 commit 1f83cd0

File tree

6 files changed

+114
-17
lines changed

6 files changed

+114
-17
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,9 +910,14 @@ void RewriteSystem::minimizeRewriteSystem() {
910910
}
911911

912912
performHomotopyReduction([&](unsigned loopID, unsigned ruleID) -> bool {
913+
const auto &loop = Loops[loopID];
913914
const auto &rule = getRule(ruleID);
914915

915-
if (!rule.isAnyConformanceRule())
916+
if (rule.isProtocolTypeAliasRule())
917+
return true;
918+
919+
if (!loop.hasConcreteTypeAliasRule(*this) &&
920+
!rule.isAnyConformanceRule())
916921
return true;
917922

918923
return false;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-inferred-signatures=verify -requirement-machine-protocol-signatures=verify 2>&1 | %FileCheck %s
2+
3+
protocol P1a {
4+
typealias X = Int
5+
}
6+
7+
// CHECK-LABEL: .P1b@
8+
// CHECK-NEXT: Requirement signature: <Self where Self : P1a, Self.[P1b]X == Int>
9+
protocol P1b : P1a {
10+
associatedtype X
11+
}
12+
13+
protocol P2a {
14+
associatedtype A
15+
typealias B = Int
16+
}
17+
18+
// CHECK-LABEL: .P2b@
19+
// CHECK-NEXT: <Self where Self : P2a, Self.[P2a]A == Int>
20+
protocol P2b : P2a where Self.A == Self.B {}
21+
22+
struct G<X> {}
23+
24+
protocol P3a {
25+
typealias T = G<X>
26+
associatedtype X
27+
}
28+
29+
protocol P3b {
30+
typealias T = G<Y>
31+
associatedtype Y
32+
}
33+
34+
// CHECK-LABEL: .P3c@
35+
// CHECK-NEXT: <Self where Self : P3a, Self : P3b, Self.[P3a]X == Self.[P3b]Y>
36+
protocol P3c : P3a, P3b {}
37+
38+
protocol P4a {
39+
typealias T = G<X>
40+
associatedtype X
41+
}
42+
43+
// CHECK-LABEL: .P4b@
44+
// CHECK-NEXT: <Self where Self : P4a, Self.[P4b]A == G<Self.[P4b]B>, Self.[P4b]B == Self.[P4a]X>
45+
protocol P4b : P4a where A == T, A == G<B> {
46+
associatedtype A
47+
associatedtype B
48+
}
49+
50+
// CHECK-LABEL: .P5@
51+
// CHECK-NEXT: <Self where Self.[P5]B == Int>
52+
protocol P5 {
53+
typealias A = Int
54+
associatedtype B where B == A
55+
}
56+
57+
protocol P6a {
58+
typealias A = Int
59+
typealias B = A
60+
}
61+
62+
// CHECK-LABEL: .P6b@
63+
// CHECK-NEXT: <Self where Self : P6a, Self.[P6b]C == Int>
64+
protocol P6b : P6a where C == B {
65+
associatedtype C
66+
}
67+
68+
protocol P7a {
69+
typealias A = Int
70+
}
71+
72+
protocol P7b : P7a {
73+
typealias B = A
74+
}
75+
76+
// CHECK-LABEL: .P7c@
77+
// CHECK-NEXT: <Self where Self : P7b, Self.[P7c]C == Int>
78+
protocol P7c : P7b {
79+
associatedtype C where C == B
80+
}
81+
82+
protocol P8a {
83+
associatedtype C
84+
}
85+
86+
// CHECK-LABEL: .f1@
87+
// CHECK-NEXT: <T, U where T : P8a, U : P7b, T.[P8a]C == Int>
88+
func f1<T : P8a, U : P7b>(_: T, _: U) where T.C == U.B {}
89+
90+
// CHECK-LABEL: .f2@
91+
// CHECK-NEXT: <T, U where T : P7b, U : P8a, U.[P8a]C == Int>
92+
func f2<T : P7b, U : P8a>(_: T, _: U) where T.B == U.C {}

test/Generics/protocol_type_aliases.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
// FIXME: Once the Requirement Machine can emit diagnostics, run this test with
2-
// it enabled unconditionally.
3-
4-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=off
5-
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on > %t.dump 2>&1
6-
// RUN: %FileCheck %s < %t.dump
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify
2+
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify > %t.dump 2>&1
73

84

95
func sameType<T>(_: T.Type, _: T.Type) {}
@@ -107,9 +103,9 @@ protocol P7 {
107103
}
108104

109105
// CHECK-LABEL: .P7a@
110-
// CHECK: Requirement signature: <Self where Self : P7>
106+
// CHECK: Requirement signature: <Self where Self : P7, Self.[P7a]A == Int>
111107
protocol P7a : P7 {
112108
associatedtype A // expected-warning{{associated type 'A' is redundant with type 'A' declared in inherited protocol 'P7'}}
113109
}
114110

115-
func testP7A<T : P7a>(_: T, a: T.A) -> Int { return a }
111+
func testP7A<T : P7a>(_: T, a: T.A) -> Int { return a }

test/Generics/protocol_typealias_same_type_requirement.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify 2>&1 | %FileCheck %s
22

33
protocol P1 {
44
associatedtype A
@@ -41,7 +41,7 @@ protocol P7 {
4141
}
4242

4343
// CHECK-LABEL: protocol_typealias_same_type_requirement.(file).P8@
44-
// CHECK-LABEL: Requirement signature: <Self where Self : P6, Self : P7>
44+
// CHECK-LABEL: Requirement signature: <Self where Self : P6, Self : P7, Self.[P7]X == Int>
4545
protocol P8 : P6, P7 {}
4646

47-
func testP8<T : P8>(_: T, x: T.X) -> Int { return x }
47+
func testP8<T : P8>(_: T, x: T.X) -> Int { return x }

test/decl/protocol/req/associated_type_ambiguity.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,24 @@ protocol P2 {
99
associatedtype T
1010
}
1111

12+
// Note: the warnings should probably be emitted.
13+
1214
// CHECK: ExtensionDecl line={{.*}} base=P1
13-
// CHECK-NEXT: Generic signature: <Self where Self : P1, Self : P2>
15+
// CHECK-NEXT: Generic signature: <Self where Self : P1, Self : P2, Self.[P2]T == Int>
1416
extension P1 where Self : P2, T == Int { // expected-warning {{redundant same-type constraint 'Self.T' == 'Int'}}
1517
func takeT11(_: T) {}
1618
func takeT12(_: Self.T) {}
1719
}
1820

1921
// CHECK: ExtensionDecl line={{.*}} base=P1
20-
// CHECK-NEXT: Generic signature: <Self where Self : P1, Self : P2>
22+
// CHECK-NEXT: Generic signature: <Self where Self : P1, Self : P2, Self.[P2]T == Int>
2123
extension P1 where Self : P2, Self.T == Int { // expected-warning {{redundant same-type constraint 'Self.T' == 'Int'}}
2224
func takeT21(_: T) {}
2325
func takeT22(_: Self.T) {}
2426
}
2527

28+
// CHECK: ExtensionDecl line={{.*}} base=P1
29+
// CHECK-NEXT: Generic signature: <Self where Self : P1, Self : P2, Self.[P2]T == Int>
2630
extension P1 where Self : P2 {
2731
func takeT31(_: T) {}
2832
func takeT32(_: Self.T) {}

test/decl/typealias/protocol.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-inferred-signatures=verify
22

33
// Tests for typealias inside protocols
44

@@ -262,9 +262,9 @@ protocol P10 {
262262

263263
@available(*, deprecated, message: "just use Int, silly")
264264
typealias V = Int
265-
}
266265

267-
extension P10 {
266+
// FIXME: This used to be in a protocol extension, but the Requirement Machine does
267+
// not permit `where` clauses to reference typealiases in protocol extensions.
268268
typealias U = Float
269269
}
270270

0 commit comments

Comments
 (0)