@@ -12,12 +12,15 @@ protocol P {
12
12
func foo(f: (Int32)->Int32, _ j: Int32) -> Int32
13
13
}
14
14
15
+ protocol Q {
16
+ }
17
+
15
18
public class C {
16
19
@sil_stored var c: C? { get set }
17
20
init()
18
21
}
19
22
20
- public struct S {
23
+ public struct S: Q {
21
24
@sil_stored var c: C? { get set }
22
25
init(c: C?)
23
26
init()
@@ -244,14 +247,90 @@ bb0(%0 : $Int32):
244
247
%2 = alloc_stack $Int32, var, name "xx"
245
248
store %0 to %2 : $*Int32
246
249
%4 = function_ref @address_closure_user : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
247
- %5 = function_ref @address_closure_trivial_mutating : $@convention(thin) (@inout_aliasable Int32) -> () // user: %6
248
- %6 = partial_apply %5(%2) : $@convention(thin) (@inout_aliasable Int32) -> () // user: %7
250
+ %5 = function_ref @address_closure_trivial_mutating : $@convention(thin) (@inout_aliasable Int32) -> ()
251
+ %6 = partial_apply %5(%2) : $@convention(thin) (@inout_aliasable Int32) -> ()
249
252
%7 = apply %4(%6) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
250
253
%8 = load %2 : $*Int32
251
254
dealloc_stack %2 : $*Int32
252
255
return %8 : $Int32
253
256
}
254
257
258
+ sil @S_init : $@convention(method) (@thin S.Type) -> @owned S
259
+
260
+ sil hidden @address_closure_body_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q {
261
+ bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q):
262
+ %5 = init_existential_addr %0 : $*Q, $S
263
+ // function_ref S.init()
264
+ %6 = function_ref @S_init : $@convention(method) (@thin S.Type) -> @owned S
265
+ %7 = metatype $@thin S.Type
266
+ %8 = apply %6(%7) : $@convention(method) (@thin S.Type) -> @owned S
267
+ store %8 to %5 : $*S
268
+ destroy_addr %2 : $*Q
269
+ destroy_addr %1 : $*Q
270
+ %12 = tuple ()
271
+ return %12 : $()
272
+ }
273
+
274
+ sil @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q {
275
+ bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q, %3 : $*Q):
276
+ %7 = function_ref @address_closure_body_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q
277
+ %8 = alloc_stack $Q
278
+ copy_addr %2 to [initialization] %8 : $*Q
279
+ %10 = alloc_stack $Q
280
+ copy_addr %3 to [initialization] %10 : $*Q
281
+ %12 = apply %7(%0, %8, %10) : $@convention(thin) (@in Q, @in Q) -> @out Q
282
+ dealloc_stack %10 : $*Q
283
+ dealloc_stack %8 : $*Q
284
+ destroy_addr %1 : $*Q
285
+ %16 = tuple ()
286
+ return %16 : $()
287
+ }
288
+
289
+ // Check that a specialization of address_closure_user_out_result was generated which does not
290
+ // take a closure as a parameter anymore.
291
+ // CHECK-LABEL: sil shared @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable Q, @inout_aliasable Q) -> @out Q
292
+ // CHECK: function_ref @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
293
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply %{{.*}} : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
294
+ // CHECK: apply [[PARTIAL_APPLY]]
295
+ // CHECK: return
296
+
297
+ sil @address_closure_user_out_result : $@convention(thin) (@owned @callee_owned (@in Q) -> @out Q) -> @out Q {
298
+ bb0(%0 : $*Q, %1 : $@callee_owned (@in Q) -> @out Q):
299
+ %4 = alloc_stack $Q
300
+ %5 = init_existential_addr %4 : $*Q, $S
301
+ %6 = function_ref @S_init : $@convention(method) (@thin S.Type) -> @owned S
302
+ %7 = metatype $@thin S.Type
303
+ %8 = apply %6(%7) : $@convention(method) (@thin S.Type) -> @owned S
304
+ store %8 to %5 : $*S
305
+ %10 = apply %1(%0, %4) : $@callee_owned (@in Q) -> @out Q
306
+ dealloc_stack %4 : $*Q
307
+ strong_release %1 : $@callee_owned (@in Q) -> @out Q
308
+ %13 = tuple ()
309
+ return %13 : $()
310
+ }
311
+
312
+ // Check that closure specialization can handle cases where the full closure type may have
313
+ // unsupported address type arguments (e.g. @in or @out), but the partial_apply has only
314
+ // supported address type arguments, i.e. @inout or @inout_aliasable.
315
+ //
316
+ // CHECK-LABEL: sil @address_caller_out_result : $@convention(thin) (@in Q, @in Q) -> @out Q
317
+ // CHECK-NOT: partial_apply
318
+ // CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_user_out_result{{.*}} : $@convention(thin) (@inout_aliasable Q, @inout_aliasable Q) -> @out Q
319
+ // CHECK: apply [[SPECIALIZED_FN1]]{{.*}}
320
+ // CHECK-NOT: partial_apply
321
+ // CHECK: return
322
+ sil @address_caller_out_result: $@convention(thin) (@in Q, @in Q) -> @out Q {
323
+ bb0(%0 : $*Q, %1 : $*Q, %2 : $*Q):
324
+ %5 = function_ref @address_closure_user_out_result : $@convention(thin) (@owned @callee_owned (@in Q) -> @out Q) -> @out Q
325
+ %6 = function_ref @address_closure_out_result : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
326
+ %7 = partial_apply %6(%1, %2) : $@convention(thin) (@in Q, @inout_aliasable Q, @inout_aliasable Q) -> @out Q
327
+ %8 = apply %5(%0, %7) : $@convention(thin) (@owned @callee_owned (@in Q) -> @out Q) -> @out Q
328
+ destroy_addr %2 : $*Q
329
+ destroy_addr %1 : $*Q
330
+ %11 = tuple ()
331
+ return %11 : $()
332
+ }
333
+
255
334
// CHECK-LABEL: sil @address_caller_existential
256
335
// CHECK-NOT: partial_apply
257
336
// CHECK: [[SPECIALIZED_FN1:%.*]] = function_ref @{{.*}}address_closure_user{{.*}} : $@convention(thin) (@inout_aliasable P) -> ()
299
378
300
379
sil shared @address_closure_existential : $@convention(thin) (@inout_aliasable P) -> () {
301
380
bb0(%0 : $*P):
302
- %7 = tuple () // user: %8
303
- return %7 : $() // id: %8
381
+ %7 = tuple ()
382
+ return %7 : $()
304
383
}
305
384
306
385
sil @address_closure_struct1 : $@convention(thin) (@inout_aliasable S, @owned S) -> () {
0 commit comments