Skip to content

Commit 2ef9f8a

Browse files
author
Karl Wagner
committed
Typechecking tests for protocol nesting
1 parent a02d9e9 commit 2ef9f8a

File tree

1 file changed

+261
-0
lines changed

1 file changed

+261
-0
lines changed
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
// RUN: %target-typecheck-verify-swift -parse-as-library -enable-experimental-feature NestedProtocols
2+
3+
// Protocols can be nested inside non-generic types.
4+
5+
protocol Delegate {}
6+
7+
enum Table {
8+
protocol Delegate {}
9+
}
10+
11+
enum Button {
12+
protocol Delegate {}
13+
}
14+
15+
struct PlainDelegateConformer: Delegate {}
16+
struct TableDelegateConformer: Table.Delegate {}
17+
struct ButtonDelegateConformer: Button.Delegate {}
18+
19+
func testDifferent() {
20+
let plain = PlainDelegateConformer()
21+
if plain is Delegate { print("ok (1)") } // expected-warning {{'is' test is always true}}
22+
if plain is Table.Delegate { print("bad (2)") }
23+
if plain is Button.Delegate { print("bad (3)") }
24+
25+
let tableDel = TableDelegateConformer()
26+
if tableDel is Delegate { print("bad (4)") }
27+
if tableDel is Table.Delegate { print("ok (5)") } // expected-warning {{'is' test is always true}}
28+
if tableDel is Button.Delegate { print("bad (6)") }
29+
30+
let buttonDel = ButtonDelegateConformer()
31+
if buttonDel is Delegate { print("bad (7)") }
32+
if buttonDel is Table.Delegate { print("bad (8)") }
33+
if buttonDel is Button.Delegate { print("ok (9)") } // expected-warning {{'is' test is always true}}
34+
}
35+
36+
enum OuterEnum {
37+
protocol C {}
38+
case C(C)
39+
// expected-error@-1{{invalid redeclaration of 'C'}}
40+
// expected-note@-3{{'C' previously declared here}}
41+
}
42+
43+
class OuterClass {
44+
protocol InnerProtocol : OuterClass { }
45+
}
46+
47+
// Deeply nested.
48+
49+
enum Level0 {
50+
struct Level1 {
51+
class Level2 {
52+
actor Level3 {
53+
struct Level4 {
54+
class Level5 {
55+
protocol DeeplyNested {
56+
func someRequirement()
57+
}
58+
func lookupTest(_ input: some DeeplyNested) {}
59+
}
60+
func lookupTest(_ input: some Level5.DeeplyNested) {}
61+
}
62+
func lookupTest(_ input: some Level4.Level5.DeeplyNested) {}
63+
}
64+
}
65+
}
66+
}
67+
68+
func useDeeplyNested(_ input: some Level0.Level1.Level2.Level3.Level4.Level5.DeeplyNested) {
69+
input.someRequirement()
70+
}
71+
72+
// Add a nested protocol in an extension.
73+
74+
extension Level0.Level1.Level2 {
75+
protocol ModeratelyNested {
76+
associatedtype ReturnValue
77+
func anotherRequirement() -> ReturnValue
78+
}
79+
80+
func lookupTest(_: some ModeratelyNested) { }
81+
}
82+
83+
func useModeratelyNested<Input>(
84+
_ input: Input
85+
) -> Input.ReturnValue where Input: Level0.Level1.Level2.ModeratelyNested {
86+
input.anotherRequirement()
87+
}
88+
89+
struct ModeratelyNestedConformer: Level0.Level1.Level2.ModeratelyNested {
90+
func anotherRequirement() -> Int {
91+
99
92+
}
93+
}
94+
95+
let _umn: Int = useModeratelyNested(ModeratelyNestedConformer())
96+
97+
// Extend a nested protocol.
98+
99+
extension Level0.Level1.Level2.ModeratelyNested {
100+
func extensionMethod() -> ReturnValue {
101+
anotherRequirement()
102+
}
103+
}
104+
105+
extension Level0.Level1.Level2.ModeratelyNested where ReturnValue == Int {
106+
func extensionMethod() -> Int {
107+
anotherRequirement() + 1
108+
}
109+
}
110+
111+
// Protocols may be nested inside non-generic functions.
112+
113+
func someFunction_0() {
114+
protocol Yes {}
115+
struct Foo: Yes {}
116+
struct Bar: Yes {}
117+
}
118+
119+
func someFunction_1() {
120+
121+
struct HowAboutThis {
122+
protocol AlsoYes {
123+
associatedtype SomeType
124+
func doSomething() -> SomeType
125+
}
126+
}
127+
128+
struct Conforms0: HowAboutThis.AlsoYes {
129+
typealias SomeType = Int
130+
func doSomething() -> SomeType { -99 }
131+
}
132+
133+
struct Conforms1: HowAboutThis.AlsoYes {
134+
typealias SomeType = String
135+
func doSomething() -> SomeType { "works" }
136+
}
137+
138+
func usesNested<T: HowAboutThis.AlsoYes>(_ input: T) -> T.SomeType {
139+
input.doSomething()
140+
}
141+
142+
let _: Int = usesNested(Conforms0())
143+
let _: String = usesNested(Conforms1())
144+
}
145+
146+
// Protocols cannot be nested in generic types or other protocols.
147+
148+
struct OuterGeneric<D> {
149+
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested inside a generic context}}
150+
associatedtype Rooster
151+
func flip(_ r: Rooster)
152+
func flop(_ t: D) // expected-error{{cannot find type 'D' in scope}}
153+
}
154+
}
155+
156+
class OuterGenericClass<T> {
157+
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested inside a generic context}}
158+
associatedtype Rooster
159+
func flip(_ r: Rooster)
160+
func flop(_ t: T) // expected-error{{cannot find type 'T' in scope}}
161+
}
162+
}
163+
164+
protocol OuterProtocol {
165+
associatedtype Hen
166+
protocol InnerProtocol { // expected-error{{protocol 'InnerProtocol' cannot be nested inside another protocol}}
167+
associatedtype Rooster
168+
func flip(_ r: Rooster)
169+
func flop(_ h: Hen) // expected-error{{cannot find type 'Hen' in scope}}
170+
}
171+
}
172+
173+
struct ConformsToOuterProtocol : OuterProtocol {
174+
typealias Hen = Int
175+
176+
func f() { let _ = InnerProtocol.self } // expected-error {{use of protocol 'OuterProtocol.InnerProtocol' as a type must be written 'any OuterProtocol.InnerProtocol'}}
177+
}
178+
179+
// 'InnerProtocol' does not inherit the generic parameters of
180+
// 'OtherGenericClass', so the occurrence of 'OtherGenericClass'
181+
// in 'InnerProtocol' is not "in context" with implicitly
182+
// inferred generic arguments <T, U>.
183+
class OtherGenericClass<T, U> { // expected-note {{generic type 'OtherGenericClass' declared here}}
184+
protocol InnerProtocol : OtherGenericClass { }
185+
// expected-error@-1{{protocol 'InnerProtocol' cannot be nested inside a generic context}}
186+
// expected-error@-2{{reference to generic type 'OtherGenericClass' requires arguments in <...>}}
187+
}
188+
189+
protocol SelfDotTest {
190+
func f(_: Self.Class)
191+
class Class {}
192+
// expected-error@-1{{type 'Class' cannot be nested in protocol 'SelfDotTest'}}
193+
}
194+
195+
struct Outer {
196+
typealias E = NestedValidation.T
197+
protocol NestedValidation {
198+
typealias T = A.B
199+
class A { // expected-error {{type 'A' cannot be nested in protocol 'NestedValidation'}}
200+
typealias B = Int
201+
}
202+
}
203+
}
204+
205+
struct OuterForUFI {
206+
@usableFromInline
207+
protocol Inner {
208+
func req()
209+
}
210+
}
211+
212+
extension OuterForUFI.Inner {
213+
public func extMethod() {} // The 'public' puts this in a special path.
214+
}
215+
216+
func testLookup(_ x: OuterForUFI.Inner) {
217+
x.req()
218+
x.extMethod()
219+
}
220+
221+
func testLookup<T: OuterForUFI.Inner>(_ x: T) {
222+
x.req()
223+
x.extMethod()
224+
}
225+
226+
// Protocols cannot be nested inside of generic functions.
227+
228+
func invalidProtocolInGeneric<T>(_: T) {
229+
protocol Test {} // expected-error{{protocol 'Test' cannot be nested inside a generic context}}
230+
}
231+
232+
struct NestedInGenericMethod<T> {
233+
func someMethod() {
234+
protocol AnotherTest {} // expected-error{{protocol 'AnotherTest' cannot be nested inside a generic context}}
235+
}
236+
}
237+
238+
// Types cannot be nested inside of protocols.
239+
240+
protocol Racoon {
241+
associatedtype Stripes
242+
class Claw<T> { // expected-error{{type 'Claw' cannot be nested in protocol 'Racoon'}}
243+
func mangle(_ s: Stripes) {}
244+
// expected-error@-1 {{cannot find type 'Stripes' in scope}}
245+
}
246+
struct Fang<T> { // expected-error{{type 'Fang' cannot be nested in protocol 'Racoon'}}
247+
func gnaw(_ s: Stripes) {}
248+
// expected-error@-1 {{cannot find type 'Stripes' in scope}}
249+
}
250+
enum Fur { // expected-error{{type 'Fur' cannot be nested in protocol 'Racoon'}}
251+
case Stripes
252+
}
253+
}
254+
255+
enum SillyRawEnum : SillyProtocol.InnerClass {} // expected-error {{an enum with no cases cannot declare a raw type}}
256+
// expected-error@-1 {{reference to generic type 'SillyProtocol.InnerClass' requires arguments in <...>}}
257+
258+
protocol SillyProtocol {
259+
class InnerClass<T> {} // expected-error {{type 'InnerClass' cannot be nested in protocol 'SillyProtocol'}}
260+
// expected-note@-1 {{generic type 'InnerClass' declared here}}
261+
}

0 commit comments

Comments
 (0)