@@ -11,6 +11,10 @@ public struct Wrapper<S> {
11
11
self . underlying = memberwise
12
12
}
13
13
14
+ public subscript< V> ( storageKeyPath path: KeyPath < S , V > ) -> V {
15
+ get { underlying [ keyPath: path] }
16
+ }
17
+
14
18
public subscript< V> ( storageKeyPath path: WritableKeyPath < S , V > ) -> V {
15
19
get { underlying [ keyPath: path] }
16
20
set { underlying [ keyPath: path] = newValue }
@@ -332,3 +336,81 @@ class ClassWithConvenienceInit<T> {
332
336
}
333
337
}
334
338
}
339
+
340
+ @Wrapper
341
+ struct TypeWithLetProperties < T> {
342
+ let a : T
343
+ let b : Int
344
+
345
+ // CHECK-LABEL: sil hidden [ossa] @$s4test21TypeWithLetPropertiesV1a1b5onSetACyxGx_SiSgyycSgtcfC
346
+ // CHECK: [[LOCAL_STORAGE:%.*]] = alloc_stack [lexical] $(a: T, b: Int), var, name "_storage", implicit
347
+ public init ( a: T , b: Int ? = nil , onSet: ( ( ) -> Void ) ? = nil ) {
348
+ // CHECK: [[LOCAL_STORAGE_ACCESS:%.*]] = begin_access [modify] [static] [[LOCAL_STORAGE]] : $*(a: T, b: Int)
349
+ // CHECK-NEXT: [[A_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 0
350
+ // CHECK-NEXT: copy_addr [take] %11 to [initialization] [[A_REF]] : $*T
351
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
352
+ // CHECK-NEXT: end_access [[LOCAL_STORAGE_ACCESS]]
353
+ self . a = a
354
+ if let b {
355
+ // CHECK: [[LOCAL_STORAGE_ACCESS:%.*]] = begin_access [modify] [static] [[LOCAL_STORAGE]] : $*(a: T, b: Int)
356
+ // CHECK-NEXT: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 1
357
+ // CHECK-NEXT: assign {{.*}} to [init] [[B_REF]] : $*Int
358
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
359
+ // CHECK-NEXT: end_access [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int)
360
+
361
+ // CHECK: [[STORAGE:%.*]] = alloc_stack $TypeWithLetProperties<T>.$Storage
362
+ // CHECK: [[STORAGE_INIT_REF:%.*]] = function_ref @$s4test21TypeWithLetPropertiesV8$StorageV1a1bAEyx_Gx_SitcfC
363
+
364
+ // CHECK: [[LOCAL_STORAGE_ACCESS:%.*]] = begin_access [read] [unsafe] [[LOCAL_STORAGE]] : $*(a: T, b: Int)
365
+ // CHECK-NEXT: [[A_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 0
366
+ // CHECK-NEXT: [[T:%.*]] = alloc_stack $T
367
+ // CHECK-NEXT: copy_addr [[A_REF]] to [initialization] [[T]] : $*T
368
+ // CHECK-NEXT: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 1
369
+ // CHECK-NEXT: [[B_VAL:%.*]] = load [trivial] [[B_REF]] : $*Int
370
+ // CHECK-NEXT: end_access [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int)
371
+
372
+ // CHECK-NEXT: [[STORAGE_METATYPE:%.*]] = metatype $@thin TypeWithLetProperties<T>.$Storage.Type
373
+ // CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT_REF]]<T>([[STORAGE]], [[T]], [[B_VAL]], [[STORAGE_METATYPE]])
374
+
375
+ // CHECK: [[WRAPPER_INIT_REF:%.*]] = function_ref @$s4test7WrapperV10memberwiseACyxGx_tcfC
376
+ // CHECK: [[STORAGE_PROP:%.*]] = struct_element_addr [[SELF_ACCESS:%.*]] : $*TypeWithLetProperties<T>, #TypeWithLetProperties.$_storage
377
+ // CHECK: [[WRAPPER_INST:%.*]] = alloc_stack $Wrapper<TypeWithLetProperties<T>.$Storage>
378
+ // CHECK-NEXT: {{.*}} = apply [[WRAPPER_INIT_REF]]<TypeWithLetProperties<T>.$Storage>([[WRAPPER_INST]], [[STORAGE]], [[WRAPPER_METATYPE:%.*]])
379
+
380
+ // CHECK: [[STORAGE_PROP_ACCESS:%.*]] = begin_access [modify] [dynamic] [[STORAGE_PROP]] : $*Wrapper<TypeWithLetProperties<T>.$Storage>
381
+ // CHECK-NEXT: copy_addr [take] [[WRAPPER_INST]] to [initialization] [[STORAGE_PROP_ACCESS]] : $*Wrapper<TypeWithLetProperties<T>.$Storage>
382
+ // CHECK-NEXT: end_access [[STORAGE_PROP_ACCESS]]
383
+ self . b = b
384
+ } else {
385
+ // CHECK: [[LOCAL_STORAGE_ACCESS:%.*]] = begin_access [modify] [static] [[LOCAL_STORAGE]] : $*(a: T, b: Int)
386
+ // CHECK-NEXT: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 1
387
+ // CHECK-NEXT: assign {{.*}} to [init] [[B_REF]] : $*Int
388
+ // CHECK-NOT: {{.*}} = assign_by_wrapper {{.*}}
389
+ // CHECK-NEXT: end_access [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int)
390
+
391
+ // CHECK: [[STORAGE:%.*]] = alloc_stack $TypeWithLetProperties<T>.$Storage
392
+ // CHECK: [[STORAGE_INIT_REF:%.*]] = function_ref @$s4test21TypeWithLetPropertiesV8$StorageV1a1bAEyx_Gx_SitcfC
393
+
394
+ // CHECK: [[LOCAL_STORAGE_ACCESS:%.*]] = begin_access [read] [unsafe] [[LOCAL_STORAGE]] : $*(a: T, b: Int)
395
+ // CHECK-NEXT: [[A_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 0
396
+ // CHECK-NEXT: [[T:%.*]] = alloc_stack $T
397
+ // CHECK-NEXT: copy_addr [[A_REF]] to [initialization] [[T]] : $*T
398
+ // CHECK-NEXT: [[B_REF:%.*]] = tuple_element_addr [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int), 1
399
+ // CHECK-NEXT: [[B_VAL:%.*]] = load [trivial] [[B_REF]] : $*Int
400
+ // CHECK-NEXT: end_access [[LOCAL_STORAGE_ACCESS]] : $*(a: T, b: Int)
401
+
402
+ // CHECK-NEXT: [[STORAGE_METATYPE:%.*]] = metatype $@thin TypeWithLetProperties<T>.$Storage.Type
403
+ // CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT_REF]]<T>([[STORAGE]], [[T]], [[B_VAL]], [[STORAGE_METATYPE]])
404
+
405
+ // CHECK: [[WRAPPER_INIT_REF:%.*]] = function_ref @$s4test7WrapperV10memberwiseACyxGx_tcfC
406
+ // CHECK: [[STORAGE_PROP:%.*]] = struct_element_addr [[SELF_ACCESS:%.*]] : $*TypeWithLetProperties<T>, #TypeWithLetProperties.$_storage
407
+ // CHECK: [[WRAPPER_INST:%.*]] = alloc_stack $Wrapper<TypeWithLetProperties<T>.$Storage>
408
+ // CHECK-NEXT: {{.*}} = apply [[WRAPPER_INIT_REF]]<TypeWithLetProperties<T>.$Storage>([[WRAPPER_INST]], [[STORAGE]], [[WRAPPER_METATYPE:%.*]])
409
+
410
+ // CHECK: [[STORAGE_PROP_ACCESS:%.*]] = begin_access [modify] [dynamic] [[STORAGE_PROP]] : $*Wrapper<TypeWithLetProperties<T>.$Storage>
411
+ // CHECK-NEXT: copy_addr [take] [[WRAPPER_INST]] to [initialization] [[STORAGE_PROP_ACCESS]] : $*Wrapper<TypeWithLetProperties<T>.$Storage>
412
+ // CHECK-NEXT: end_access [[STORAGE_PROP_ACCESS]]
413
+ self . b = 0
414
+ }
415
+ }
416
+ }
0 commit comments