// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -disable-availability-checking -enable-sil-opaque-values -Xllvm -sil-full-demangle -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime // Test SILGen -enable-sil-opaque-values with tests that depend on the stdlib. // CaptureKind // - Box // - opaque? // - canGuarantee? // - captureCanEscape? // - !isPack! -- assert(!isPack()) // opaque=true canGuarantee=true captureCanEscape=true [x] // captureBoxOpaqueGuaranteedEscaping // opaque=true canGuarantee=false captureCanEscape=true [x] // captureBoxOpaqueOwnedEscaping // opaque=true canGuarantee=false captureCanEscape=false [-] // captureBoxOpaqueOwnedNonescaping // rdar://114195999 // opaque=false canGuarantee=true captureCanEscape=true [x] // captureBoxNonopaqueGuaranteedEscaping // opaque=false canGuarantee=false captureCanEscape=true [x] // captureBoxNonopaqueOwnedEscaping // opaque=false canGuarantee=false captureCanEscape=false [x] // captureBoxNonopaqueOwnedNonescaping // - ImmutableBox // this has to be move-only, basically // - opaque? =true:unimplemented. noncopyable struct 'S' cannot conform to 'P', noncopyable type 'S' cannot be used with generics yet ( captureImmutableBoxOpaqueGuaranteedEscaping ) // - canGuarantee? // - captureCanEscape? // - !isPack! -- assert(!isPack()) // opaque=false canGuarantee=true captureCanEscape=true [x] // captureImmutableBoxNonopaqueGuaranteedEscaping // opaque=false canGuarantee=false captureCanEscape=true [x] // captureImmutableBoxNonopaqueOwnedEscaping // opaque=false canGuarantee=false captureCanEscape=false [-] // captureImmutableBoxNonopaqueOwnedNonescaping // rdar://114207460 // - StorageAddress [x] captureStorageAddress // - isMoveOnlyWrapped? =true:unimplemented. noncopyable struct 'MO' must be @frozen in library evolution mode; non-@frozen public and @usableFromInline noncopyable types are not supported // - isPack? // isPack=true [-] CRASH // isPack=false [x] captureStorageAddress // - Constant // REQUIRES NOT-ADDRESS-ONLY! // - Immutable // - canGuarantee? // - isPack? // canGuarantee=true isPack=true [ ] // captureImmutablePackGuaranteed // canGuarantee=true isPack=false [x] // captureImmutableGuaranteed // canGuarantee=false isPack=true [ ] // captureImmutableOwnedPack // canGuarantee=false isPack=false [x] // captureImmutableOwned protocol P {} struct PImpl : P {} class C {} struct G {} struct MOG : ~Copyable {} func getMOG(_ t: T.Type) -> MOG { return MOG() } func borrow(_ t: T) {} @propertyWrapper struct BoxWrapper { var wrappedValue: T } // CaptureKind::Immutable, canGuarantee=true, isPack=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures30captureImmutablePackGuaranteed1tyxxQp_tRvzlF6$deferL_yyRvzlF : {{.*}} { // CHECK: bb0(%0 : @closureCapture // CHECK-LABEL: } // end sil function '$s22opaque_values_closures30captureImmutablePackGuaranteed1tyxxQp_tRvzlF6$deferL_yyRvzlF' func captureImmutablePackGuaranteed(t: repeat each T) { defer { (repeat borrow(each t)) } } // CaptureKind::Immutable, canGuarantee=true, isPack=false // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures26captureImmutableGuaranteed1tyx_tlF : {{.*}} { // CHECK: bb0([[INSTANCE:%[^,]+]] : // CHECK: [[STACK:%[^,]+]] = alloc_stack [lexical] [var_decl] $T, let, name "x" // CHECK: [[VAR:%[^,]+]] = mark_uninitialized [var] [[STACK]] // CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]] // CHECK: assign [[COPY]] to [[VAR]] // CHECK: [[LOAD:%[^,]+]] = load_borrow [[VAR]] // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures26captureImmutableGuaranteed1tyx_tlF6$deferL_yylF // CHECK: apply [[CLOSURE]]([[LOAD]]) // CHECK: end_borrow [[LOAD]] // CHECK: destroy_addr [[VAR]] // CHECK: dealloc_stack [[STACK]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures26captureImmutableGuaranteed1tyx_tlF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures26captureImmutableGuaranteed1tyx_tlF6$deferL_yylF : {{.*}} { // CHECK: bb0([[INSTANCE:%[^,]+]] : @closureCapture @guaranteed $T): // CHECK: [[BORROW:%[^,]+]] = function_ref @$s22opaque_values_closures6borrowyyxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> () // CHECK: apply [[BORROW]]([[INSTANCE]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> () // CHECK-LABEL: } // end sil function '$s22opaque_values_closures26captureImmutableGuaranteed1tyx_tlF6$deferL_yylF' func captureImmutableGuaranteed(t: T) { let x: T defer { borrow(x) } x = t } // CaptureKind::Immutable, canGuarantee=false, isPack=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures25captureImmutableOwnedPackyyxxQpRvzlF : {{.*}} { // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures25captureImmutableOwnedPackyyxxQpRvzlFyyXEfU_ // CHECK: [[STACK_TUPLE:%[^,]+]] = alloc_stack $(repeat each T) // CHECK: [[CONTEXT:%[^,]+]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[STACK_TUPLE]]) // CHECK: [[NOESCAPE_CONTEXT:%[^,]+]] = convert_escape_to_noescape [not_guaranteed] [[CONTEXT]] // CHECK: [[CALLEE:%[^,]+]] = function_ref @$s22opaque_values_closures32captureImmutableOwnedPack_calleeyyyyXEF // CHECK: apply [[CALLEE]]([[NOESCAPE_CONTEXT]]) // CHECK: destroy_value [[NOESCAPE_CONTEXT]] // CHECK: destroy_value [[CONTEXT]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures25captureImmutableOwnedPackyyxxQpRvzlF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures25captureImmutableOwnedPackyyxxQpRvzlFyyXEfU_ : $@convention(thin) (@in_guaranteed (repeat each T)) -> () { // CHECK: bb0(%0 : @closureCapture $*(repeat each T)): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures25captureImmutableOwnedPackyyxxQpRvzlFyyXEfU_' func captureImmutableOwnedPack(_ ts: repeat each T) { captureImmutableOwnedPack_callee { _ = (repeat each ts) } } func captureImmutableOwnedPack_callee(_ cl: () -> ()) {} // CaptureKind::Immutable, canGuarantee=false, isPack=false // CHECK-LABEL: sil hidden [ossa] @$s22opaque_values_closures21captureImmutableOwnedyyxlF : $@convention(thin) (@in_guaranteed T) -> () { // CHECK: bb0([[INSTANCE:%[^,]+]] : // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures21captureImmutableOwnedyyxlFyyXEfU_ // CHECK: [[COPY:%[^,]+]] = copy_value [[INSTANCE]] // CHECK: [[CONTEXT:%[^,]+]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[COPY]]) // CHECK: [[NOESCAPE_CONTEXT:%[^,]+]] = convert_escape_to_noescape [not_guaranteed] [[CONTEXT]] // CHECK: [[CALLEE:%[^,]+]] = function_ref @$s22opaque_values_closures28captureImmutableOwned_calleeyyyyXEF // CHECK: apply [[CALLEE]]([[NOESCAPE_CONTEXT]]) // CHECK: destroy_value [[NOESCAPE_CONTEXT]] // CHECK: destroy_value [[CONTEXT]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures21captureImmutableOwnedyyxlF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures21captureImmutableOwnedyyxlFyyXEfU_ : {{.*}} { // CHECK: bb0(%0 : @closureCapture @guaranteed $T): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures21captureImmutableOwnedyyxlFyyXEfU_' func captureImmutableOwned(_ t: T) { captureImmutableOwned_callee { _ = t } } func captureImmutableOwned_callee(_ cl: () -> ()) {} // CaptureKind::StorageAddress, isMoveOnlyWrapped=false, isPack=false // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures21captureStorageAddressyyAA1GVyxGzlF : {{.*}} { // CHECK: bb0([[ADDR:%[^,]+]] : // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures21captureStorageAddressyyAA1GVyxGzlFyAEXEfU_ // CHECK: [[CONTEXT:%[^,]+]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[ADDR]]) // CHECK: [[CONVERTED_CONTEXT:%[^,]+]] = convert_function [[CONTEXT]] // CHECK: [[NOESCAPE_CONTEXT:%[^,]+]] = convert_escape_to_noescape [not_guaranteed] [[CONVERTED_CONTEXT]] // CHECK: [[CALLEE:%[^,]+]] = function_ref @$s22opaque_values_closures28captureStorageAddress_calleeyyyAA1GVyxGXElF // CHECK: apply [[CALLEE]]([[NOESCAPE_CONTEXT]]) // CHECK: destroy_value [[NOESCAPE_CONTEXT]] // CHECK: destroy_value [[CONVERTED_CONTEXT]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures21captureStorageAddressyyAA1GVyxGzlF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures21captureStorageAddressyyAA1GVyxGzlFyAEXEfU_ : {{.*}} { // CHECK: bb0(%0 : {{.*}}, // CHECK: %1 : @closureCapture $*G): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures21captureStorageAddressyyAA1GVyxGzlFyAEXEfU_' func captureStorageAddress(_ g: inout G) { captureStorageAddress_callee { o in g = o } } func captureStorageAddress_callee(_ t: (G) -> ()) {} // // Unimplemented: noncopyable struct 'S' cannot conform to 'P', noncopyable type 'S' cannot be used with generics yet ( captureImmutableBoxOpaqueGuaranteedEscaping ) // // CaptureKind::ImmutableBox, opaque, canGuarantee=true, captureCanEscape=true // struct MOS : ~Copyable {} // func captureImmutableBoxOpaqueGuaranteedEscaping_vend() -> some Any { return MOS() } // func captureImmutableBoxOpaqueGuaranteedEscaping() { // var instance = captureImmutableBoxOpaqueGuaranteedEscaping_vend() // func local(_ t: T) { // instance = captureImmutableBoxOpaqueGuaranteedEscaping_vend() // } // local(instance) // } // CaptureKind::ImmutableBox, non-opaque, canGuarantee=true, captureCanEscape=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures46captureImmutableBoxNonopaqueGuaranteedEscapingyyxmlF : {{.*}} { // CHECK: bb0([[T:%[^,]+]] : // CHECK: [[BOX:%[^,]+]] = alloc_box ${ var TakingMOG }, var // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [var_decl] [[BOX]] // CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX_LIFETIME]] // CHECK: mark_function_escape [[BOX_ADDR]] // CHECK: [[LOCAL:%[^,]+]] = function_ref @$s22opaque_values_closures46captureImmutableBoxNonopaqueGuaranteedEscapingyyxmlF5localL_yylF // CHECK: apply [[LOCAL]]([[BOX_LIFETIME]], [[T]]) // CHECK: end_borrow [[BOX_LIFETIME]] // CHECK: destroy_value [[BOX]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures46captureImmutableBoxNonopaqueGuaranteedEscapingyyxmlF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures46captureImmutableBoxNonopaqueGuaranteedEscapingyyxmlF5localL_yylF : {{.*}} { // CHECK: bb0(%0 : @closureCapture @guaranteed ${ var TakingMOG }, // CHECK-LABEL: } // end sil function '$s22opaque_values_closures46captureImmutableBoxNonopaqueGuaranteedEscapingyyxmlF5localL_yylF' func captureImmutableBoxNonopaqueGuaranteedEscaping(_ t: T.Type) { var us: TakingMOG = TakingMOG() func local() { us.takeMOG(getMOG(t)) } local() } struct TakingMOG { mutating func takeMOG(_ m: consuming MOG) {} } // CaptureKind::ImmutableBox, non-opaque, canGuarantee=false, captureCanEscape=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures41captureImmutableBoxNonopaqueOwnedEscapingyyxmlF : {{.*}} { // CHECK: [[IMMUTABLEBOX:%[^,]+]] = alloc_box $<τ_0_0> { let MOG<τ_0_0> } , let // CHECK: [[IMMUTABLEBOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [var_decl] [[IMMUTABLEBOX]] // CHECK: [[IMMUTABLEBOX_ADDR:%[^,]+]] = project_box [[IMMUTABLEBOX_LIFETIME]] // CHECK: store {{%[^,]+}} to [init] [[IMMUTABLEBOX_ADDR]] // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures41captureImmutableBoxNonopaqueOwnedEscapingyyxmlFyycfU_ : $@convention(thin) <τ_0_0> (@guaranteed <τ_0_0> { let MOG<τ_0_0> } <τ_0_0>) -> () // CHECK: [[IMMUTABLEBOX_COPY:%[^,]+]] = copy_value [[IMMUTABLEBOX_LIFETIME]] // CHECK: mark_function_escape [[IMMUTABLEBOX_ADDR]] // CHECK: [[CONTEXT:%[^,]+]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[IMMUTABLEBOX_COPY]]) // CHECK: [[CALLEE:%[^,]+]] = function_ref @$s22opaque_values_closures48captureImmutableBoxNonopaqueOwnedEscaping_calleeyyyycF // CHECK: apply [[CALLEE]]([[CONTEXT]]) // CHECK: destroy_value [[CONTEXT]] : $@callee_guaranteed () -> () // CHECK: end_borrow [[IMMUTABLEBOX_LIFETIME]] // CHECK: destroy_value [[IMMUTABLEBOX]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures41captureImmutableBoxNonopaqueOwnedEscapingyyxmlF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures41captureImmutableBoxNonopaqueOwnedEscapingyyxmlFyycfU_ : {{.*}} { // CHECK: bb0(%0 : @closureCapture @guaranteed $<τ_0_0> { let MOG<τ_0_0> } ): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures41captureImmutableBoxNonopaqueOwnedEscapingyyxmlFyycfU_' func captureImmutableBoxNonopaqueOwnedEscaping(_ t: T.Type) { let g = getMOG(t) captureImmutableBoxNonopaqueOwnedEscaping_callee { _ = g } } func captureImmutableBoxNonopaqueOwnedEscaping_callee(_ t: @escaping () -> ()) {} // // rdar://114207460 // // CaptureKind::ImmutableBox, non-opaque, canGuarantee=false, captureCanEscape=false // @propertyWrapper struct MOGWrapper : ~Copyable { var wrappedValue: MOG } // func captureImmutableBoxNonopaqueOwnedNonescaping(_ get: () -> MOG) { // @MOGWrapper var u: MOG // // func local() { // u = get() // } // local() // } // CaptureKind::Box, opaque, canGuarantee=true, captureCanEscape=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures34captureBoxOpaqueGuaranteedEscapingyyF : {{.*}} { // CHECK: [[BOX:%[^,]+]] = alloc_box ${ var @_opaqueReturnTypeOf("$s22opaque_values_closures39captureBoxOpaqueGuaranteedEscaping_vendQryF", 0) __ }, var // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [var_decl] [[BOX]] // CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX_LIFETIME]] // CHECK: [[BOX2:%[^,]+]] = alloc_box ${ var @_opaqueReturnTypeOf("$s22opaque_values_closures39captureBoxOpaqueGuaranteedEscaping_vendQryF", 0) __ } // CHECK: [[BOX2_ADDR:%[^,]+]] = project_box [[BOX2]] // CHECK: copy_addr [[BOX_ADDR]] to [init] [[BOX2_ADDR]] // CHECK: [[BOX2_LIFETIME:%[^,]+]] = begin_borrow [[BOX2]] // CHECK: [[BOX_ACCESS:%[^,]+]] = begin_access [read] [unknown] [[BOX_ADDR]] // CHECK: [[INITIAL_VALUE:%[^,]+]] = load [trivial] [[BOX_ACCESS]] // CHECK: end_access [[BOX_ACCESS]] // CHECK: [[LOCAL:%[^,]+]] = function_ref @$s22opaque_values_closures34captureBoxOpaqueGuaranteedEscapingyyF5localL_yyxAA1PRzlF // CHECK: apply [[LOCAL]]([[INITIAL_VALUE]], [[BOX2_LIFETIME]]) // CHECK: end_borrow [[BOX2_LIFETIME]] // CHECK: destroy_value [[BOX2]] // CHECK: destroy_value [[BOX]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures34captureBoxOpaqueGuaranteedEscapingyyF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures34captureBoxOpaqueGuaranteedEscapingyyF5localL_yyxAA1PRzlF : {{.*}} { // CHECK: bb0(%0 : @guaranteed $T, // CHECK-SAME: %1 : @closureCapture @guaranteed ${ var @_opaqueReturnTypeOf("$s22opaque_values_closures39captureBoxOpaqueGuaranteedEscaping_vendQryF", 0) __ }): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures34captureBoxOpaqueGuaranteedEscapingyyF5localL_yyxAA1PRzlF' func captureBoxOpaqueGuaranteedEscaping() { var instance = captureBoxOpaqueGuaranteedEscaping_vend() func local(_ t: T) { instance = captureBoxOpaqueGuaranteedEscaping_vend() } local(instance) } func captureBoxOpaqueGuaranteedEscaping_vend() -> some P { return PImpl() } // CaptureKind::Box, opaque, canGuarantee=false, captureCanEscape=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures29captureBoxOpaqueOwnedEscapingyyF : {{.*}} { // CHECK: [[BOX:%[^,]+]] = alloc_box ${ var @_opaqueReturnTypeOf("$s22opaque_values_closures34captureBoxOpaqueOwnedEscaping_vendQryF", 0) __ }, var // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [var_decl] [[BOX]] // CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX_LIFETIME]] // CHECK: [[BOX_ACCESS:%[^,]+]] = begin_access [read] [unknown] [[BOX_ADDR]] // CHECK: [[FIRST:%[^,]+]] = load [trivial] [[BOX_ACCESS]] // CHECK: end_access [[BOX_ACCESS]] // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures29captureBoxOpaqueOwnedEscapingyyFyAA0defgH5_vendQryFQOyQo_cfU_ // CHECK: [[BOX2:%[^,]+]] = alloc_box ${ var @_opaqueReturnTypeOf("$s22opaque_values_closures34captureBoxOpaqueOwnedEscaping_vendQryF", 0) __ } // CHECK: [[BOX2_ADDR:%[^,]+]] = project_box [[BOX2]] // CHECK: copy_addr [[BOX_ADDR]] to [init] [[BOX2_ADDR]] // CHECK: [[CONTEXT:%[^,]+]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX2]]) // CHECK: [[CALLEE:%[^,]+]] = function_ref @$s22opaque_values_closures36captureBoxOpaqueOwnedEscaping_calleeyyx_yxctAA1PRzlF // CHECK: apply [[CALLEE]]([[FIRST]], [[CONTEXT]]) // CHECK: destroy_value [[CONTEXT]] // CHECK: destroy_value [[BOX]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures29captureBoxOpaqueOwnedEscapingyyF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures29captureBoxOpaqueOwnedEscapingyyFyAA0defgH5_vendQryFQOyQo_cfU_ : {{.*}} { // CHECK: bb0(%0 : $PImpl, // CHECK-SAME: %1 : @closureCapture @guaranteed ${ var @_opaqueReturnTypeOf("$s22opaque_values_closures34captureBoxOpaqueOwnedEscaping_vendQryF", 0) __ }): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures29captureBoxOpaqueOwnedEscapingyyFyAA0defgH5_vendQryFQOyQo_cfU_' func captureBoxOpaqueOwnedEscaping() { var instance = captureBoxOpaqueOwnedEscaping_vend() captureBoxOpaqueOwnedEscaping_callee(instance) { new in instance = new } } func captureBoxOpaqueOwnedEscaping_vend() -> some P { return PImpl() } func captureBoxOpaqueOwnedEscaping_callee(_ t: T, _ c: @escaping (T) -> ()) {} // // rdar://114195999 // // CaptureKind::Box, opaque, canGuarantee=false, captureCanEscape=false // protocol Q { // associatedtype A // static func vend() -> A // } // struct PImpl : P {} // struct QI : Q { // static func vend() -> some P { return PImpl() } // } // @propertyWrapper struct BoxWrapper { var wrappedValue: T } // func captureBoxOpaqueOwnedNonescaping() { // @BoxWrapper var u: QI.A // // func local() { // u = QI.vend() // } // local() // } // CaptureKind::Box, non-opaque, canGuarantee=true, captureCanEscape=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures37captureBoxNonopaqueGuaranteedEscapingyyxyXElF : {{.*}} { // CHECK: bb0([[GET:%[^,]+]] : // CHECK: [[BOX:%[^,]+]] = alloc_box $<τ_0_0> { var Array<τ_0_0> } , var // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [var_decl] [[BOX]] // CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX_LIFETIME]] // CHECK: mark_function_escape [[BOX_ADDR]] // CHECK: [[LOCAL:%[^,]+]] = function_ref @$s22opaque_values_closures37captureBoxNonopaqueGuaranteedEscapingyyxyXElF5localL_yylF // CHECK: apply [[LOCAL]]([[BOX_LIFETIME]], [[GET]]) // CHECK: end_borrow [[BOX_LIFETIME]] // CHECK: destroy_value [[BOX]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures37captureBoxNonopaqueGuaranteedEscapingyyxyXElF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures37captureBoxNonopaqueGuaranteedEscapingyyxyXElF5localL_yylF : {{.*}} { // CHECK: bb0(%0 : @closureCapture @guaranteed $<τ_0_0> { var Array<τ_0_0> } , // CHECK: %1 : // CHECK-LABEL: } // end sil function '$s22opaque_values_closures37captureBoxNonopaqueGuaranteedEscapingyyxyXElF5localL_yylF' func captureBoxNonopaqueGuaranteedEscaping(_ get: () -> U) { var us: [U] = [] func local() { us.append(get()) } local() } // CaptureKind::Box, non-opaque, canGuarantee=false, captureCanEscape=true // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures32captureBoxNonopaqueOwnedEscapingyyF : {{.*}} { // CHECK: [[BOX:%[^,]+]] = alloc_box ${ var C }, var // CHECK: [[BOX_LIFETIME:%[^,]+]] = begin_borrow [lexical] [var_decl] [[BOX]] // CHECK: [[BOX_ADDR:%[^,]+]] = project_box [[BOX_LIFETIME]] // CHECK: [[BOX_ACCESS:%[^,]+]] = begin_access [read] [unknown] [[BOX_ADDR]] // CHECK: [[INITIAL_VALUE:%[^,]+]] = load [copy] [[BOX_ACCESS]] // CHECK: end_access [[BOX_ACCESS]] // CHECK: [[CLOSURE:%[^,]+]] = function_ref @$s22opaque_values_closures32captureBoxNonopaqueOwnedEscapingyyFyAA1CCcfU_ // CHECK: [[BOX_COPY:%[^,]+]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[BOX_ADDR]] // CHECK: [[CONTEXT:%[^,]+]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[CALLEE:%[^,]+]] = function_ref @$s22opaque_values_closures39captureBoxNonopaqueOwnedEscaping_calleeyyx_yxctlF // CHECK: apply [[CALLEE]]([[INITIAL_VALUE]], [[CONTEXT]]) // CHECK: destroy_value [[CONTEXT]] // CHECK: destroy_value [[INITIAL_VALUE]] // CHECK: end_borrow [[BOX_LIFETIME]] // CHECK: destroy_value [[BOX]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures32captureBoxNonopaqueOwnedEscapingyyF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures32captureBoxNonopaqueOwnedEscapingyyFyAA1CCcfU_ : {{.*}} { // CHECK: bb0(%0 : {{.*}}, // CHECK: %1 : @closureCapture @guaranteed ${ var C }): // CHECK-LABEL: } // end sil function '$s22opaque_values_closures32captureBoxNonopaqueOwnedEscapingyyFyAA1CCcfU_' func captureBoxNonopaqueOwnedEscaping() { var instance = captureBoxNonopaqueOwnedEscaping_vend() captureBoxNonopaqueOwnedEscaping_callee(instance) { new in instance = new } } func captureBoxNonopaqueOwnedEscaping_callee(_ t: T, _ c: @escaping (T) -> ()) {} func captureBoxNonopaqueOwnedEscaping_vend() -> C { return C() } // CaptureKind::Box, non-opaque, canGuarantee=false, captureCanEscape=false // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures35captureBoxNonopaqueOwnedNonescapingyyxyXElF : {{.*}} { // CHECK: bb0([[GET:%[^,]+]] : // CHECK: [[BOX:%[^,]+]] = alloc_box $<τ_0_0> { var BoxWrapper<τ_0_0> } , var // CHECK: [[VAR:%[^,]+]] = mark_uninitialized [var] [[BOX]] // CHECK: [[VAR_LIFETIME:%[^,]+]] = begin_borrow [lexical] [var_decl] [[VAR]] // CHECK: [[VAR_ADDR:%[^,]+]] = project_box [[VAR_LIFETIME]] // TODO: DETERMINE: Considering that captureCanEscape is false, should this mark_function_escape be emitted? // CHECK: mark_function_escape [[VAR_ADDR]] // CHECK: [[LOCAL:%[^,]+]] = function_ref @$s22opaque_values_closures35captureBoxNonopaqueOwnedNonescapingyyxyXElF5localL_yylF // CHECK: apply [[LOCAL]]([[VAR_LIFETIME]], [[GET]]) // CHECK: end_borrow [[VAR_LIFETIME]] // CHECK: destroy_value [[VAR]] // CHECK-LABEL: } // end sil function '$s22opaque_values_closures35captureBoxNonopaqueOwnedNonescapingyyxyXElF' // CHECK-LABEL: sil {{.*}}[ossa] @$s22opaque_values_closures35captureBoxNonopaqueOwnedNonescapingyyxyXElF5localL_yylF : {{.*}} // CHECK: bb0(%0 : @closureCapture @guaranteed $<τ_0_0> { var BoxWrapper<τ_0_0> } , // CHECK-SAME: %1 : // CHECK-LABEL: } // end sil function '$s22opaque_values_closures35captureBoxNonopaqueOwnedNonescapingyyxyXElF5localL_yylF' func captureBoxNonopaqueOwnedNonescaping(_ get: () -> U) { @BoxWrapper var u: U func local() { u = get() } local() }