Files
swift-mirror/test/SILGen/opaque_values_closures.swift
Kavon Farvardin 12a915ff6d OpaqueValues: resurrect closure test
This effectively reverts 8ca5c83c51
2025-10-21 17:46:28 -07:00

388 lines
24 KiB
Swift

// 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<T> {}
struct MOG<T> : ~Copyable {}
func getMOG<T>(_ t: T.Type) -> MOG<T> { return MOG<T>() }
func borrow<T>(_ t: T) {}
@propertyWrapper struct BoxWrapper<T> { 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<each T>(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]]<T>([[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]]<T>([[INSTANCE]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
// CHECK-LABEL: } // end sil function '$s22opaque_values_closures26captureImmutableGuaranteed1tyx_tlF6$deferL_yylF'
func captureImmutableGuaranteed<T>(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]]<Pack{repeat each T}>([[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) <each T> (@in_guaranteed (repeat each T)) -> () {
// CHECK: bb0(%0 : @closureCapture $*(repeat each T)):
// CHECK-LABEL: } // end sil function '$s22opaque_values_closures25captureImmutableOwnedPackyyxxQpRvzlFyyXEfU_'
func captureImmutableOwnedPack<each T>(_ 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) <T> (@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]]<T>([[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: 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]]<T>([[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]]<T>([[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<T>):
// CHECK-LABEL: } // end sil function '$s22opaque_values_closures21captureStorageAddressyyAA1GVyxGzlFyAEXEfU_'
func captureStorageAddress<T>(_ g: inout G<T>) {
captureStorageAddress_callee { o in
g = o
}
}
func captureStorageAddress_callee<T>(_ t: (G<T>) -> ()) {}
// // 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: 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]]<T>([[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: T.Type) {
var us: TakingMOG = TakingMOG()
func local() {
us.takeMOG(getMOG(t))
}
local()
}
struct TakingMOG {
mutating func takeMOG<T>(_ m: consuming MOG<T>) {}
}
// 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> } <T>, 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]]<T>([[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> } <T>):
// CHECK-LABEL: } // end sil function '$s22opaque_values_closures41captureImmutableBoxNonopaqueOwnedEscapingyyxmlFyycfU_'
func captureImmutableBoxNonopaqueOwnedEscaping<T>(_ 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<T> : ~Copyable { var wrappedValue: MOG<T> }
// func captureImmutableBoxNonopaqueOwnedNonescaping<U>(_ get: () -> MOG<U>) {
// @MOGWrapper<U> var u: MOG<U>
//
// 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]]<PImpl>([[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 : P>(_ 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]]<PImpl>([[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 : P>(_ 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<T> { 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> } <U>, 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]]<U>([[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> } <U>,
// CHECK: %1 :
// CHECK-LABEL: } // end sil function '$s22opaque_values_closures37captureBoxNonopaqueGuaranteedEscapingyyxyXElF5localL_yylF'
func captureBoxNonopaqueGuaranteedEscaping<U>(_ 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]]<C>([[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: 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> } <U>, 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]]<U>([[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> } <U>,
// CHECK-SAME: %1 :
// CHECK-LABEL: } // end sil function '$s22opaque_values_closures35captureBoxNonopaqueOwnedNonescapingyyxyXElF5localL_yylF'
func captureBoxNonopaqueOwnedNonescaping<U>(_ get: () -> U) {
@BoxWrapper var u: U
func local() {
u = get()
}
local()
}