// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -enable-sil-ownership %s | %FileCheck %s import Swift var zero: Int // CHECK-LABEL: sil hidden @_T016generic_closures0A21_nondependent_context{{[_0-9a-zA-Z]*}}F func generic_nondependent_context(_ x: T, y: Int) -> Int { func foo() -> Int { return y } func bar() -> Int { return y } // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]](%1) // CHECK: destroy_value [[FOO_CLOSURE]] let _ = foo // CHECK: [[BAR:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int // CHECK: [[BAR_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[BAR]](%1) // CHECK: destroy_value [[BAR_CLOSURE]] let _ = bar // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]] _ = foo() // CHECK: [[BAR:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int // CHECK: [[BAR_CLOSURE:%.*]] = apply [[BAR]] // CHECK: [[BAR_CLOSURE]] return bar() } // CHECK-LABEL: sil hidden @_T016generic_closures0A8_capture{{[_0-9a-zA-Z]*}}F func generic_capture(_ x: T) -> Any.Type { func foo() -> Any.Type { return T.self } // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]() // CHECK: destroy_value [[FOO_CLOSURE]] let _ = foo // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]() // CHECK: return [[FOO_CLOSURE]] return foo() } // CHECK-LABEL: sil hidden @_T016generic_closures0A13_capture_cast{{[_0-9a-zA-Z]*}}F func generic_capture_cast(_ x: T, y: Any) -> Bool { func foo(_ a: Any) -> Bool { return a is T } // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A13_capture_cast{{.*}} : $@convention(thin) <τ_0_0> (@in Any) -> Bool // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]() // CHECK: destroy_value [[FOO_CLOSURE]] let _ = foo // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A13_capture_cast{{.*}} : $@convention(thin) <τ_0_0> (@in Any) -> Bool // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]([[ARG:%.*]]) // CHECK: return [[FOO_CLOSURE]] return foo(y) } protocol Concept { var sensical: Bool { get } } // CHECK-LABEL: sil hidden @_T016generic_closures0A22_nocapture_existential{{[_0-9a-zA-Z]*}}F func generic_nocapture_existential(_ x: T, y: Concept) -> Bool { func foo(_ a: Concept) -> Bool { return a.sensical } // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in Concept) -> Bool // CHECK: [[FOO_CLOSURE:%.*]] = thin_to_thick_function [[FOO]] // CHECK: destroy_value [[FOO_CLOSURE]] let _ = foo // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in Concept) -> Bool // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]([[ARG:%.*]]) // CHECK: return [[FOO_CLOSURE]] return foo(y) } // CHECK-LABEL: sil hidden @_T016generic_closures0A18_dependent_context{{[_0-9a-zA-Z]*}}F func generic_dependent_context(_ x: T, y: Int) -> T { func foo() -> T { return x } // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A18_dependent_context{{.*}} : $@convention(thin) <τ_0_0> (@guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]([[BOX:%.*]]) // CHECK: destroy_value [[FOO_CLOSURE]] let _ = foo // CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A18_dependent_context{{.*}} : $@convention(thin) <τ_0_0> (@guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]] // CHECK: return return foo() } enum Optionable { case none case some(Wrapped) } class NestedGeneric { class func generic_nondependent_context(_ x: T, y: Int, z: U) -> Int { func foo() -> Int { return y } let _ = foo return foo() } class func generic_dependent_inner_context(_ x: T, y: Int, z: U) -> T { func foo() -> T { return x } let _ = foo return foo() } class func generic_dependent_outer_context(_ x: T, y: Int, z: U) -> U { func foo() -> U { return z } let _ = foo return foo() } class func generic_dependent_both_contexts(_ x: T, y: Int, z: U) -> (T, U) { func foo() -> (T, U) { return (x, z) } let _ = foo return foo() } // CHECK-LABEL: sil hidden @_T016generic_closures13NestedGenericC20nested_reabstraction{{[_0-9a-zA-Z]*}}F // CHECK: [[REABSTRACT:%.*]] = function_ref @_T0Ieg_ytytIegir_TR // CHECK: partial_apply [callee_guaranteed] [[REABSTRACT]] func nested_reabstraction(_ x: T) -> Optionable<() -> ()> { return .some({}) } } // // Ensure that nested closures capture the generic parameters of their nested // context. // CHECK: sil hidden @_T016generic_closures018nested_closure_in_A0yxxlF : $@convention(thin) (@in T) -> @out T // CHECK: function_ref [[OUTER_CLOSURE:@_T016generic_closures018nested_closure_in_A0yxxlFxycfU_]] // CHECK: sil private [[OUTER_CLOSURE]] : $@convention(thin) (@inout_aliasable T) -> @out T // CHECK: function_ref [[INNER_CLOSURE:@_T016generic_closures018nested_closure_in_A0yxxlFxycfU_xycfU_]] // CHECK: sil private [[INNER_CLOSURE]] : $@convention(thin) (@inout_aliasable T) -> @out T { func nested_closure_in_generic(_ x:T) -> T { return { { x }() }() } // CHECK-LABEL: sil hidden @_T016generic_closures16local_properties{{[_0-9a-zA-Z]*}}F func local_properties(_ t: inout T) { var prop: T { get { return t } set { t = newValue } } // CHECK: [[GETTER_REF:%[0-9]+]] = function_ref [[GETTER_CLOSURE:@_T016generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@inout_aliasable τ_0_0) -> @out τ_0_0 // CHECK: apply [[GETTER_REF]] t = prop // CHECK: [[SETTER_REF:%[0-9]+]] = function_ref [[SETTER_CLOSURE:@_T016generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @inout_aliasable τ_0_0) -> () // CHECK: apply [[SETTER_REF]] prop = t var prop2: T { get { return t } set { // doesn't capture anything } } // CHECK: [[GETTER2_REF:%[0-9]+]] = function_ref [[GETTER2_CLOSURE:@_T016generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@inout_aliasable τ_0_0) -> @out τ_0_0 // CHECK: apply [[GETTER2_REF]] t = prop2 // CHECK: [[SETTER2_REF:%[0-9]+]] = function_ref [[SETTER2_CLOSURE:@_T016generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () // CHECK: apply [[SETTER2_REF]] prop2 = t } protocol Fooable { static func foo() -> Bool } // func shmassert(_ f: @autoclosure () -> Bool) {} // CHECK-LABEL: sil hidden @_T016generic_closures08capture_A6_param{{[_0-9a-zA-Z]*}}F func capture_generic_param(_ x: A) { shmassert(A.foo()) } // Make sure we use the correct convention when capturing class-constrained // member types: class Class {} protocol HasClassAssoc { associatedtype Assoc : Class } // CHECK-LABEL: sil hidden @_T016generic_closures027captures_class_constrained_A0_1fyx_5AssocQzAEctAA08HasClassF0RzlF // CHECK: bb0([[ARG1:%.*]] : @trivial $*T, [[ARG2:%.*]] : @owned $@callee_guaranteed (@owned T.Assoc) -> @owned T.Assoc): // CHECK: [[GENERIC_FN:%.*]] = function_ref @_T016generic_closures027captures_class_constrained_A0_1fyx_5AssocQzAEctAA08HasClassF0RzlFA2EcycfU_ // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] // CHECK: [[CONCRETE_FN:%.*]] = partial_apply [callee_guaranteed] [[GENERIC_FN]]([[ARG2_COPY]]) func captures_class_constrained_generic(_ x: T, f: @escaping (T.Assoc) -> T.Assoc) { let _: () -> (T.Assoc) -> T.Assoc = { f } } // Make sure local generic functions can have captures // CHECK-LABEL: sil hidden @_T016generic_closures06outer_A01t1iyx_SitlF : $@convention(thin) (@in T, Int) -> () func outer_generic(t: T, i: Int) { func inner_generic_nocapture(u: U) -> U { return u } func inner_generic1(u: U) -> Int { return i } func inner_generic2(u: U) -> T { return t } let _: () -> () = inner_generic_nocapture // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures06outer_A01t1iyx_SitlF06inner_A10_nocaptureL_1uqd__qd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0) -> @out τ_1_0 // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]() : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0) -> @out τ_1_0 // CHECK: [[THUNK:%.*]] = function_ref @_T0ytytIegir_Ieg_TR // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]]) // CHECK: destroy_value [[THUNK_CLOSURE]] // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures06outer_A01t1iyx_SitlF06inner_A10_nocaptureL_1uqd__qd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0) -> @out τ_1_0 // CHECK: [[RESULT:%.*]] = apply [[FN]]({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0) -> @out τ_1_0 _ = inner_generic_nocapture(u: t) // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures06outer_A01t1iyx_SitlF14inner_generic1L_1uSiqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, Int) -> Int // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]](%1) : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, Int) -> Int // CHECK: [[THUNK:%.*]] = function_ref @_T0ytSiIegid_SiIegd_TR // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]]) // CHECK: destroy_value [[THUNK_CLOSURE]] let _: () -> Int = inner_generic1 // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures06outer_A01t1iyx_SitlF14inner_generic1L_1uSiqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, Int) -> Int // CHECK: [[RESULT:%.*]] = apply [[FN]]({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, Int) -> Int _ = inner_generic1(u: t) // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures06outer_A01t1iyx_SitlF14inner_generic2L_1uxqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]([[ARG:%.*]]) : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK: [[THUNK:%.*]] = function_ref @_T0ytxIegir_xIegr_lTR // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]]) // CHECK: destroy_value [[THUNK_CLOSURE]] let _: () -> T = inner_generic2 // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures06outer_A01t1iyx_SitlF14inner_generic2L_1uxqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // CHECK: [[RESULT:%.*]] = apply [[FN]]({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0> (@in τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 _ = inner_generic2(u: t) } // CHECK-LABEL: sil hidden @_T016generic_closures14outer_concrete1iySi_tF : $@convention(thin) (Int) -> () func outer_concrete(i: Int) { func inner_generic_nocapture(u: U) -> U { return u } func inner_generic(u: U) -> Int { return i } // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures14outer_concrete1iySi_tF06inner_A10_nocaptureL_1uxx_tlF : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0 // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<()>() : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0 // CHECK: [[THUNK:%.*]] = function_ref @_T0ytytIegir_Ieg_TR // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]]) // CHECK: destroy_value [[THUNK_CLOSURE]] let _: () -> () = inner_generic_nocapture // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures14outer_concrete1iySi_tF06inner_A10_nocaptureL_1uxx_tlF : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0 // CHECK: [[RESULT:%.*]] = apply [[FN]]({{.*}}) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0 _ = inner_generic_nocapture(u: i) // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures14outer_concrete1iySi_tF06inner_A0L_1uSix_tlF : $@convention(thin) <τ_0_0> (@in τ_0_0, Int) -> Int // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<()>(%0) : $@convention(thin) <τ_0_0> (@in τ_0_0, Int) -> Int // CHECK: [[THUNK:%.*]] = function_ref @_T0ytSiIegid_SiIegd_TR // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]]) // CHECK: destroy_value [[THUNK_CLOSURE]] let _: () -> Int = inner_generic // CHECK: [[FN:%.*]] = function_ref @_T016generic_closures14outer_concrete1iySi_tF06inner_A0L_1uSix_tlF : $@convention(thin) <τ_0_0> (@in τ_0_0, Int) -> Int // CHECK: [[RESULT:%.*]] = apply [[FN]]({{.*}}) : $@convention(thin) <τ_0_0> (@in τ_0_0, Int) -> Int _ = inner_generic(u: i) } // CHECK-LABEL: sil hidden @_T016generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF : $@convention(thin) (@in T) -> () func mixed_generic_nongeneric_nesting(t: T) { func outer() { func middle(u: U) { func inner() -> U { return u } inner() } middle(u: 11) } outer() } // CHECK-LABEL: sil private @_T016generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF5outerL_yylF : $@convention(thin) () -> () // CHECK-LABEL: sil private @_T016generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF5outerL_yylF6middleL_1uyqd___tr__lF : $@convention(thin) (@in U) -> () // CHECK-LABEL: sil private @_T016generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF5outerL_yylF6middleL_1uyqd___tr__lF5innerL_qd__yr__lF : $@convention(thin) (@guaranteed <τ_0_0><τ_1_0> { var τ_1_0 } ) -> @out U protocol Doge { associatedtype Nose : NoseProtocol } protocol NoseProtocol { associatedtype Squeegee } protocol Doggo {} struct DogSnacks {} func capture_same_type_representative(slobber: Roo, daisy: Daisy) where Roo == Daisy.Nose.Squeegee { var s = DogSnacks() _ = { _ = s } }