forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrequirement_inference.swift
391 lines (312 loc) · 11.7 KB
/
requirement_inference.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
// RUN: %target-typecheck-verify-swift -typecheck %s -verify
// RUN: %target-typecheck-verify-swift -typecheck -debug-generic-signatures %s > %t.dump 2>&1
// RUN: %FileCheck %s < %t.dump
protocol P1 {
func p1()
}
protocol P2 : P1 { }
struct X1<T : P1> {
func getT() -> T { }
}
class X2<T : P1> {
func getT() -> T { }
}
class X3 { }
struct X4<T : X3> {
func getT() -> T { }
}
struct X5<T : P2> { }
// Infer protocol requirements from the parameter type of a generic function.
func inferFromParameterType<T>(_ x: X1<T>) {
x.getT().p1()
}
// Infer protocol requirements from the return type of a generic function.
func inferFromReturnType<T>(_ x: T) -> X1<T> {
x.p1()
}
// Infer protocol requirements from the superclass of a generic parameter.
func inferFromSuperclass<T, U : X2<T>>(_ t: T, u: U) -> T {
t.p1()
}
// Infer protocol requirements from the parameter type of a constructor.
struct InferFromConstructor {
init<T> (x : X1<T>) {
x.getT().p1()
}
}
// Don't infer requirements for outer generic parameters.
class Fox : P1 {
func p1() {}
}
class Box<T : Fox> {
// CHECK-LABEL: .unpack@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : Fox [τ_0_0: Explicit]
func unpack(_ x: X1<T>) {}
}
// ----------------------------------------------------------------------------
// Superclass requirements
// ----------------------------------------------------------------------------
// Compute meet of two superclass requirements correctly.
class Carnivora {}
class Canidae : Carnivora {}
struct U<T : Carnivora> {}
struct V<T : Canidae> {}
// CHECK-LABEL: .inferSuperclassRequirement1@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement1<T : Carnivora>(
_ v: V<T>) {}
// expected-warning@-2{{redundant superclass constraint 'T' : 'Carnivora'}}
// expected-note@-2{{superclass constraint 'T' : 'Canidae' inferred from type here}}
// CHECK-LABEL: .inferSuperclassRequirement2@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {}
// ----------------------------------------------------------------------------
// Same-type requirements
// ----------------------------------------------------------------------------
protocol P3 {
associatedtype P3Assoc : P2
}
protocol P4 {
associatedtype P4Assoc : P1
}
protocol PCommonAssoc1 {
associatedtype CommonAssoc
}
protocol PCommonAssoc2 {
associatedtype CommonAssoc
}
protocol PAssoc {
associatedtype Assoc
}
struct Model_P3_P4_Eq<T : P3, U : P4> where T.P3Assoc == U.P4Assoc {}
// CHECK-LABEL: .inferSameType1@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Inferred @ {{.*}}:32]
// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Inferred @ {{.*}}:32]
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P4Assoc in P4)
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P3Assoc in P3)]
// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0: Inferred]
func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
// CHECK-LABEL: .inferSameType2@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:25]
// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Explicit @ {{.*}}:33]
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Explicit @ {{.*}}:33 -> Protocol requirement (via Self.P4Assoc in P4)
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)]
// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
// expected-warning@-1{{redundant conformance constraint 'T.P3Assoc': 'P2'}}
// expected-note@-2{{conformance constraint 'T.P3Assoc': 'P2' implied here}}
// CHECK-LABEL: .inferSameType3@
// CHECK-NEXT: Requirements:
// CHECK-NEXT: τ_0_0 : PCommonAssoc1 [τ_0_0: Explicit @ {{.*}}:25]
// CHECK-NEXT: τ_0_0 : PCommonAssoc2 [τ_0_0: Explicit @ {{.*}}:74]
// CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [τ_0_0[.PCommonAssoc1].CommonAssoc: Explicit @ {{.*}}:66]
// CHECK-NEXT: Potential archetypes
func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
protocol P5 {
associatedtype Element
}
protocol P6 {
associatedtype AssocP6 : P5
}
protocol P7 : P6 {
associatedtype AssocP7: P6
}
// CHECK-LABEL: P7.nestedSameType1()@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P7, τ_0_0.AssocP6.Element : P6, τ_0_0.AssocP6.Element == τ_0_0.AssocP7.AssocP6.Element>
extension P7 where AssocP6.Element : P6, // expected-note{{conformance constraint 'Self.AssocP6.Element': 'P6' written here}}
AssocP7.AssocP6.Element : P6, // expected-warning{{redundant conformance constraint 'Self.AssocP6.Element': 'P6'}}
AssocP6.Element == AssocP7.AssocP6.Element {
func nestedSameType1() { }
}
protocol P8 {
associatedtype A
associatedtype B
}
protocol P9 : P8 {
associatedtype A
associatedtype B
}
protocol P10 {
associatedtype A
associatedtype C
}
// CHECK-LABEL: sameTypeConcrete1@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.A == X3, τ_0_0.B == Int, τ_0_0.C == Int>
func sameTypeConcrete1<T : P9 & P10>(_: T) where T.A == X3, T.C == T.B, T.C == Int { }
// CHECK-LABEL: sameTypeConcrete2@
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.B == X3, τ_0_0.C == X3>
func sameTypeConcrete2<T : P9 & P10>(_: T) where T.B : X3, T.C == T.B, T.C == X3 { }
// expected-warning@-1{{redundant superclass constraint 'T.B' : 'X3'}}
// expected-note@-2{{same-type constraint 'T.C' == 'X3' written here}}
// Note: a standard-library-based stress test to make sure we don't inject
// any additional requirements.
// CHECK-LABEL: RangeReplaceableCollection.f()@
// CHECK: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == MutableRangeReplaceableSlice<τ_0_0>>
extension RangeReplaceableCollection where
Self: MutableCollection,
Self.SubSequence == MutableRangeReplaceableSlice<Self>
{
func f() { }
}
// CHECK-LABEL: X14.recursiveConcreteSameType
// CHECK: Generic signature: <T, V where T == CountableRange<Int>>
// CHECK-NEXT: Canonical generic signature: <τ_0_0, τ_1_0 where τ_0_0 == CountableRange<Int>>
struct X14<T: Collection> where T.Iterator == IndexingIterator<T> {
func recursiveConcreteSameType<V>(_: V) where T == CountableRange<Int> { }
}
// rdar://problem/30478915
protocol P11 {
associatedtype A
}
protocol P12 {
associatedtype B: P11
}
struct X6 { }
struct X7 : P11 {
typealias A = X6
}
struct X8 : P12 {
typealias B = X7
}
struct X9<T: P12, U: P12> where T.B == U.B {
// CHECK-LABEL: X9.upperSameTypeConstraint
// CHECK: Generic signature: <T, U, V where U : P12, T == X8, U.B == X8.B>
// CHECK: Canonical generic signature: <τ_0_0, τ_0_1, τ_1_0 where τ_0_1 : P12, τ_0_0 == X8, τ_0_1.B == X7>
func upperSameTypeConstraint<V>(_: V) where T == X8 { }
}
protocol P13 {
associatedtype C: P11
}
struct X10: P11, P12 {
typealias A = X10
typealias B = X10
}
struct X11<T: P12, U: P12> where T.B == U.B.A {
// CHECK-LABEL: X11.upperSameTypeConstraint
// CHECK: Generic signature: <T, U, V where T : P12, U == X10, T.B == X10.A>
// CHECK: Canonical generic signature: <τ_0_0, τ_0_1, τ_1_0 where τ_0_0 : P12, τ_0_1 == X10, τ_0_0.B == X10>
func upperSameTypeConstraint<V>(_: V) where U == X10 { }
}
#if _runtime(_ObjC)
// rdar://problem/30610428
@objc protocol P14 { }
class X12<S: AnyObject> {
func bar<V>(v: V) where S == P14 {
}
}
@objc protocol P15: P14 { }
class X13<S: P14> {
func bar<V>(v: V) where S == P15 {
}
}
#endif
protocol P16 {
associatedtype A
}
struct X15 { }
struct X16<X, Y> : P16 {
typealias A = (X, Y)
}
// CHECK-LABEL: .X17.bar@
// CHECK: Generic signature: <S, T, U, V where S == X16<X3, X15>, T == X3, U == X15>
struct X17<S: P16, T, U> where S.A == (T, U) {
func bar<V>(_: V) where S == X16<X3, X15> { }
}
// Same-type constraints that are self-derived via a parent need to be
// supressed in the resulting signature.
protocol P17 { }
protocol P18 {
associatedtype A: P17
}
struct X18: P18, P17 {
typealias A = X18
}
// CHECK-LABEL: .X19.foo@
// CHECK: Generic signature: <T, U where T == X18>
struct X19<T: P18> where T == T.A {
func foo<U>(_: U) where T == X18 { }
}
// rdar://problem/31520386
protocol P20 { }
struct X20<T: P20> { }
// CHECK-LABEL: .X21.f@
// CHECK: Generic signature: <T, U, V where T : P20, U == X20<T>>
// CHECK: Canonical generic signature: <τ_0_0, τ_0_1, τ_1_0 where τ_0_0 : P20, τ_0_1 == X20<τ_0_0>>
struct X21<T, U> {
func f<V>(_: V) where U == X20<T> { }
}
struct X22<T, U> {
func g<V>(_: V) where T: P20, // expected-warning{{redundant conformance constraint 'T': 'P20'}}
U == X20<T> { } // expected-note{{conformance constraint 'T': 'P20' inferred from type here}}
}
// CHECK: Generic signature: <Self where Self : P22>
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P22>
// CHECK: Protocol requirement signature:
// CHECK: .P22@
// CHECK-NEXT: Requirement signature: <Self where Self.B : P20, Self.A == X20<Self.B>>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : P20, τ_0_0.A == X20<τ_0_0.B>>
protocol P22 {
associatedtype A
associatedtype B where A == X20<B>
}
// CHECK: Generic signature: <Self where Self : P23>
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P23>
// CHECK: Protocol requirement signature:
// CHECK: .P23@
// CHECK-NEXT: Requirement signature: <Self where Self.B : P20, Self.A == X20<Self.B>>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : P20, τ_0_0.A == X20<τ_0_0.B>>
protocol P23 {
associatedtype A
associatedtype B: P20 // expected-warning{{redundant conformance constraint 'Self.B': 'P20'}}
where A == X20<B> // expected-note{{conformance constraint 'Self.B': 'P20' inferred from type here}}
}
protocol P24 {
associatedtype C: P20
}
struct X24<T: P20> : P24 {
typealias C = T
}
// CHECK-LABEL: .P25a@
// CHECK-NEXT: Requirement signature: <Self where Self.B : P20, Self.A == X24<Self.B>>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : P20, τ_0_0.A == X24<τ_0_0.B>>
protocol P25a {
associatedtype A: P24 // expected-warning{{redundant conformance constraint 'Self.A': 'P24'}}
associatedtype B where A == X24<B> // expected-note{{conformance constraint 'Self.A': 'P24' implied here}}
}
// CHECK-LABEL: .P25b@
// CHECK-NEXT: Requirement signature: <Self where Self.B : P20, Self.A == X24<Self.B>>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : P20, τ_0_0.A == X24<τ_0_0.B>>
protocol P25b {
associatedtype A
associatedtype B where A == X24<B>
}
protocol P25c {
associatedtype A: P24
associatedtype B where A == X<B> // expected-error{{use of undeclared type 'X'}}
}
// Similar to the above, but with superclass constraints.
protocol P26 {
associatedtype C: X3
}
struct X26<T: X3> : P26 {
typealias C = T
}
// CHECK-LABEL: .P27a@
// CHECK-NEXT: Requirement signature: <Self where Self.B : X3, Self.A == X26<Self.B>>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : X3, τ_0_0.A == X26<τ_0_0.B>>
protocol P27a {
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'Self.A': 'P26'}}
associatedtype B where A == X26<B> // expected-note{{conformance constraint 'Self.A': 'P26' implied here}}
}
// CHECK-LABEL: .P27b@
// CHECK-NEXT: Requirement signature: <Self where Self.B : X3, Self.A == X26<Self.B>>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : X3, τ_0_0.A == X26<τ_0_0.B>>
protocol P27b {
associatedtype A
associatedtype B where A == X26<B>
}