@@ -67,6 +67,26 @@ struct Holder {
6767@_addressableForDependencies
6868struct AddressableForDeps {}
6969
70+ public struct MutableView : ~Copyable, ~Escapable {
71+ @_hasStorage var ptr: UnsafeMutableRawBufferPointer { get set }
72+ init(ptr: UnsafeMutableRawBufferPointer)
73+ }
74+
75+ public struct Container : ~Escapable, ~Copyable {
76+ @_hasStorage var somethings: UnsafeMutableRawBufferPointer { get set }
77+ init(somethings: UnsafeMutableRawBufferPointer)
78+ }
79+
80+ public struct AThing : ~Copyable {
81+ @_hasStorage var somethings: UnsafeMutableRawBufferPointer { get set }
82+ init(somethings: UnsafeMutableRawBufferPointer)
83+ }
84+
85+ sil @getContainer : $@convention(thin) (@inout AThing) -> @lifetime(borrow address_for_deps 0) @out Container
86+ sil @getMutableView : $@convention(thin) (@in_guaranteed Container) -> @lifetime(copy 0) @out Optional<MutableView>
87+ sil @modAThing : $@convention(thin) (@inout AThing) -> ()
88+ sil @getSpan : $@convention(thin) (@inout MutableView) -> @lifetime(borrow address_for_deps 0) @owned MutableRawSpan
89+
7090sil @getNEPointerToA : $@convention(thin) (@guaranteed NE) -> UnsafePointer<A>
7191sil @useA : $@convention(thin) (A) -> ()
7292
@@ -679,3 +699,95 @@ bb2(%25 : @guaranteed $NCWrapper):
679699 %37 = tuple ()
680700 return %37
681701}
702+
703+ // rdar://151231236 ([~Escapable] Missing 'overlapping acceses' error when called from client code, but exact same code
704+ // produces error in same module)
705+ //
706+ // Test access scope expansion over a switch_enum_addr
707+ // CHECK-LABEL: sil hidden [ossa] @testSwitchEnumAddr : $@convention(thin) @async (@inout AThing) -> @error any Error {
708+ // CHECK: bb0(%0 : $*AThing):
709+ // CHECK: [[ATHING:%[0-9]+]] = mark_unresolved_non_copyable_value [consumable_and_assignable] %0
710+ // CHECK: [[ACCESS:%[0-9]+]] = begin_access [modify] [unknown] [[ATHING]]
711+ // CHECK: apply {{.*}}(%{{.*}}, [[ACCESS]]) : $@convention(thin) (@inout AThing) -> @lifetime(borrow address_for_deps 0) @out Container
712+ // CHECK: mark_dependence_addr [unresolved] %{{.*}} on [[ACCESS]]
713+ // CHECK: [[VIEW:%[0-9]+]] = project_box
714+ // CHECK: [[TMP:%[0-9]+]] = alloc_stack $Optional<MutableView>
715+ // CHECK: [[TMP_NC:%[0-9]+]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TMP]]
716+ // CHECK: apply %{{.*}} : $@convention(thin) (@in_guaranteed Container) -> @lifetime(copy 0) @out Optional<MutableView>
717+ // CHECK: switch_enum_addr [[TMP_NC]], case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
718+ // CHECK: bb1:
719+ // CHECK: bb2:
720+ // CHECK: [[DATA:%[0-9]+]] = unchecked_take_enum_data_addr [[TMP_NC]], #Optional.some!enumelt
721+ // CHECK: copy_addr [take] [[DATA]] to [init] [[VIEW]]
722+ // CHECK: begin_access [modify] [unknown] [[ATHING]]
723+ // CHECK: apply %{{.*}} : $@convention(thin) (@inout AThing) -> ()
724+ // CHECK: [[ACCESS_VIEW:%[0-9]+]] = begin_access [modify] [unknown] [[VIEW]]
725+ // CHECK: apply {{.*}} : $@convention(thin) (@inout MutableView) -> @lifetime(borrow address_for_deps 0) @owned MutableRawSpan
726+ // CHECK: mark_dependence [unresolved]
727+ // CHECK: end_access [[ACCESS_VIEW]]
728+ // CHECK: end_access [[ACCESS]]
729+ // CHECK: store
730+ // CHECK-LABEL: } // end sil function 'testSwitchEnumAddr'
731+ sil hidden [ossa] @testSwitchEnumAddr : $@convention(thin) @async (@inout AThing) -> @error any Error {
732+ bb0(%0 : $*AThing):
733+ %1 = mark_unresolved_non_copyable_value [consumable_and_assignable] %0
734+ %2 = alloc_box ${ var Container }, var, name "container"
735+ %3 = begin_borrow [lexical] [var_decl] %2
736+ %4 = project_box %3, 0
737+ %5 = begin_access [modify] [unknown] %1
738+
739+ %6 = function_ref @getContainer : $@convention(thin) (@inout AThing) -> @lifetime(borrow address_for_deps 0) @out Container
740+ %7 = apply %6(%4, %5) : $@convention(thin) (@inout AThing) -> @lifetime(borrow address_for_deps 0) @out Container
741+ mark_dependence_addr [unresolved] %4 on %5
742+ end_access %5
743+ %10 = alloc_box ${ var MutableView }, var, name "view"
744+ %11 = begin_borrow [lexical] [var_decl] %10
745+ %12 = project_box %11, 0
746+
747+ %13 = alloc_stack $Optional<MutableView>
748+ %14 = mark_unresolved_non_copyable_value [consumable_and_assignable] %13
749+ %15 = begin_access [read] [unknown] %4
750+ %16 = mark_unresolved_non_copyable_value [no_consume_or_assign] %15
751+
752+ %17 = function_ref @getMutableView : $@convention(thin) (@in_guaranteed Container) -> @lifetime(copy 0) @out Optional<MutableView>
753+ %18 = apply %17(%14, %16) : $@convention(thin) (@in_guaranteed Container) -> @lifetime(copy 0) @out Optional<MutableView>
754+ end_access %15
755+
756+ switch_enum_addr %14, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
757+
758+ bb1:
759+ end_borrow %11
760+ dealloc_box [dead_end] %10
761+ end_borrow %3
762+ dealloc_box [dead_end] %2
763+ unreachable
764+
765+ bb2:
766+ %44 = unchecked_take_enum_data_addr %14, #Optional.some!enumelt
767+ copy_addr [take] %44 to [init] %12
768+ dealloc_stack %13
769+
770+ %22 = begin_access [modify] [unknown] %1
771+ %23 = function_ref @modAThing : $@convention(thin) (@inout AThing) -> ()
772+ %24 = apply %23(%22) : $@convention(thin) (@inout AThing) -> ()
773+ end_access %22
774+ %26 = alloc_box ${ var MutableRawSpan }, var, name "span"
775+ %27 = begin_borrow [lexical] [var_decl] %26
776+ %28 = project_box %27, 0
777+ %29 = begin_access [modify] [unknown] %12
778+ %30 = mark_unresolved_non_copyable_value [assignable_but_not_consumable] %29
779+
780+ %31 = function_ref @getSpan : $@convention(thin) (@inout MutableView) -> @lifetime(borrow address_for_deps 0) @owned MutableRawSpan
781+ %32 = apply %31(%30) : $@convention(thin) (@inout MutableView) -> @lifetime(borrow address_for_deps 0) @owned MutableRawSpan
782+ %33 = mark_dependence [unresolved] %32 on %30
783+ end_access %29
784+ store %33 to [init] %28
785+ end_borrow %27
786+ destroy_value %26
787+ end_borrow %11
788+ destroy_value %10
789+ end_borrow %3
790+ destroy_value %2
791+ %42 = tuple ()
792+ return %42
793+ }
0 commit comments