// RUN: %empty-directory(%t) // RUN: %build-silgen-test-overlays // RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -enable-sil-ownership -emit-silgen %s | %FileCheck %s // REQUIRES: objc_interop import Foundation import gizmo func curry_pod(_ x: CurryTest) -> (Int) -> Int { return x.pod } // CHECK-LABEL: sil hidden @_T013objc_currying9curry_podyS2icSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed (Int) -> Int // CHECK: bb0([[ARG1:%.*]] : @owned $CurryTest): // CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]] // CHECK: [[COPIED_ARG1:%.*]] = copy_value [[BORROWED_ARG1]] // CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_FOO_1:_T0So9CurryTestC3podyS2iFTcTO]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed (Int) -> Int // CHECK: [[FN:%.*]] = apply [[THUNK]]([[COPIED_ARG1]]) // CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]] // CHECK: destroy_value [[ARG1]] // CHECK: return [[FN]] // CHECK: } // end sil function '_T013objc_currying9curry_podyS2icSo9CurryTestCF' // CHECK: sil shared [serializable] [thunk] @[[THUNK_FOO_1]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed (Int) -> Int // CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_FOO_2:_T0So9CurryTestC3podyS2iFTO]] // CHECK: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]](%0) // CHECK: return [[FN]] // CHECK: } // end sil function '[[THUNK_FOO_1]]' // CHECK: sil shared [serializable] [thunk] @[[THUNK_FOO_2]] : $@convention(method) (Int, @guaranteed CurryTest) -> Int // CHECK: bb0([[ARG1:%.*]] : @trivial $Int, [[ARG2:%.*]] : @guaranteed $CurryTest): // CHECK: [[COPIED_ARG2:%.*]] = copy_value [[ARG2]] // CHECK: [[METHOD:%.*]] = objc_method [[COPIED_ARG2]] : $CurryTest, #CurryTest.pod!1.foreign // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[ARG1]], [[COPIED_ARG2]]) // CHECK: destroy_value [[COPIED_ARG2]] // CHECK: return [[RESULT]] // CHECK: } // end sil function '[[THUNK_FOO_2]]' func curry_bridged(_ x: CurryTest) -> (String?) -> String? { return x.bridged } // CHECK-LABEL: sil hidden @_T013objc_currying13curry_bridgedySSSgACcSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed (@owned Optional) -> @owned Optional // CHECK: bb0([[ARG1:%.*]] : @owned $CurryTest): // CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]] // CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]] // CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_BAR_1:_T0So9CurryTestC7bridgedySQySSGADFTcTO]] // CHECK: [[FN:%.*]] = apply [[THUNK]]([[ARG1_COPY]]) // CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]] // CHECK: destroy_value [[ARG1]] // CHECK: return [[FN]] // CHECK: } // end sil function '_T013objc_currying13curry_bridgedySSSgACcSo9CurryTestCF' // CHECK: sil shared [serializable] [thunk] @[[THUNK_BAR_1]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed (@owned Optional) -> @owned Optional // CHECK: bb0([[ARG1:%.*]] : @owned $CurryTest): // CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_BAR_2:_T0So9CurryTestC7bridgedySQySSGADFTO]] // CHECK: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG1]]) // CHECK: return [[FN]] // CHECK: } // end sil function '[[THUNK_BAR_1]]' // CHECK: sil shared [serializable] [thunk] @[[THUNK_BAR_2]] : $@convention(method) (@owned Optional, @guaranteed CurryTest) -> @owned Optional // CHECK: bb0([[OPT_STRING:%.*]] : @owned $Optional, [[SELF:%.*]] : @guaranteed $CurryTest): // CHECK: switch_enum [[OPT_STRING]] : $Optional, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], // // CHECK: [[SOME_BB]]([[STRING:%.*]] : @owned $String): // CHECK: [[BRIDGING_FUNC:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF // CHECK: [[BORROWED_STRING:%.*]] = begin_borrow [[STRING]] // CHECK: [[NSSTRING:%.*]] = apply [[BRIDGING_FUNC]]([[BORROWED_STRING]]) // CHECK: [[OPT_NSSTRING:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[NSSTRING]] : $NSString // CHECK: end_borrow [[BORROWED_STRING]] from [[STRING]] // CHECK: destroy_value [[STRING]] // CHECK: br bb3([[OPT_NSSTRING]] : $Optional) // CHECK: bb2: // CHECK: [[OPT_NONE:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK: br bb3([[OPT_NONE]] : $Optional) // CHECK: bb3([[OPT_NSSTRING:%.*]] : @owned $Optional): // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] // CHECK: [[METHOD:%.*]] = objc_method [[SELF_COPY]] : $CurryTest, #CurryTest.bridged!1.foreign // CHECK: [[RESULT_OPT_NSSTRING:%.*]] = apply [[METHOD]]([[OPT_NSSTRING]], [[SELF_COPY]]) : $@convention(objc_method) (Optional, CurryTest) -> @autoreleased Optional // CHECK: switch_enum [[RESULT_OPT_NSSTRING]] : $Optional, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], // CHECK: [[SOME_BB]]([[RESULT_NSSTRING:%.*]] : @owned $NSString): // CHECK: [[BRIDGE_FUNC:%.*]] = function_ref @_T0SS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ // CHECK: [[REWRAP_RESULT_NSSTRING:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[RESULT_NSSTRING]] // CHECK: [[RESULT_STRING:%.*]] = apply [[BRIDGE_FUNC]]([[REWRAP_RESULT_NSSTRING]] // CHECK: [[WRAPPED_RESULT_STRING:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[RESULT_STRING]] // CHECK: br bb6([[WRAPPED_RESULT_STRING]] : $Optional) // CHECK: bb5: // CHECK: [[OPT_NONE:%.*]] = enum $Optional, #Optional.none!enumelt // CHECK: br bb6([[OPT_NONE]] : $Optional) // CHECK: bb6([[FINAL_RESULT:%.*]] : @owned $Optional): // CHECK: destroy_value [[SELF_COPY]] // CHECK: destroy_value [[OPT_NSSTRING]] // CHECK: return [[FINAL_RESULT]] : $Optional // CHECK: } // end sil function '[[THUNK_BAR_2]]' func curry_returnsInnerPointer(_ x: CurryTest) -> () -> UnsafeMutableRawPointer? { return x.returnsInnerPointer } // CHECK-LABEL: sil hidden @_T013objc_currying25curry_returnsInnerPointerySvSgycSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed () -> Optional { // CHECK: bb0([[SELF:%.*]] : @owned $CurryTest): // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]] // CHECK: [[SELF_COPY:%.*]] = copy_value [[BORROWED_SELF]] // CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER:_T0So9CurryTestC19returnsInnerPointerSQySvGyFTcTO]] // CHECK: [[FN:%.*]] = apply [[THUNK]]([[SELF_COPY]]) // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]] // CHECK: destroy_value [[SELF]] // CHECK: return [[FN]] // CHECK: } // end sil function '_T013objc_currying25curry_returnsInnerPointerySvSgycSo9CurryTestCF' // CHECK: sil shared [serializable] [thunk] @[[THUNK_RETURNSINNERPOINTER]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_guaranteed () -> Optional // CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER_2:_T0So9CurryTestC19returnsInnerPointerSQySvGyFTO]] // CHECK: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]](%0) // CHECK: return [[FN]] // CHECK: } // end sil function '[[THUNK_RETURNSINNERPOINTER]]' // CHECK: sil shared [serializable] [thunk] @[[THUNK_RETURNSINNERPOINTER_2]] : $@convention(method) (@guaranteed CurryTest) -> Optional // CHECK: bb0([[ARG1:%.*]] : @guaranteed $CurryTest): // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] // CHECK: [[METHOD:%.*]] = objc_method [[ARG1_COPY]] : $CurryTest, #CurryTest.returnsInnerPointer!1.foreign // CHECK: [[RES:%.*]] = apply [[METHOD]]([[ARG1_COPY]]) : $@convention(objc_method) (CurryTest) -> @unowned_inner_pointer Optional // CHECK: autorelease_value // CHECK: return [[RES]] // CHECK: } // end sil function '[[THUNK_RETURNSINNERPOINTER_2]]' // CHECK-LABEL: sil hidden @_T013objc_currying19curry_pod_AnyObjectyS2icyXlF : $@convention(thin) (@owned AnyObject) -> @owned @callee_guaranteed (Int) -> Int // CHECK: bb0([[ANY:%.*]] : @owned $AnyObject): // CHECK: [[BORROWED_ANY:%.*]] = begin_borrow [[ANY]] // CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[BORROWED_ANY]] // CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]] // CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.pod!1.foreign, [[HAS_METHOD:bb[0-9]+]] // CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int): // CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]] // CHECK: partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]]) // CHECK: } // end sil function '_T013objc_currying19curry_pod_AnyObjectyS2icyXlF' func curry_pod_AnyObject(_ x: AnyObject) -> (Int) -> Int { return x.pod! } // normalOwnership requires a thunk to bring the method to Swift conventions // CHECK-LABEL: sil hidden @_T013objc_currying31curry_normalOwnership_AnyObjectySo9CurryTestCSgAEcyXlF : $@convention(thin) (@owned AnyObject) -> @owned @callee_guaranteed (@owned Optional) -> @owned Optional { // CHECK: bb0([[ANY:%.*]] : @owned $AnyObject): // CHECK: [[BORROWED_ANY:%.*]] = begin_borrow [[ANY]] // CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[BORROWED_ANY]] // CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]] // CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.normalOwnership!1.foreign, [[HAS_METHOD:bb[0-9]+]] // CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (Optional, @opened({{.*}}) AnyObject) -> @autoreleased Optional): // CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]] // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]]) // CHECK: [[THUNK:%.*]] = function_ref @_T0So9CurryTestCSgACIegyo_A2CIegxo_TR // CHECK: partial_apply [callee_guaranteed] [[THUNK]]([[PA]]) // CHECK: } // end sil function '_T013objc_currying31curry_normalOwnership_AnyObjectySo9CurryTestCSgAEcyXlF' func curry_normalOwnership_AnyObject(_ x: AnyObject) -> (CurryTest?) -> CurryTest? { return x.normalOwnership! } // weirdOwnership is NS_RETURNS_RETAINED and NS_CONSUMES_SELF so already // follows Swift conventions // CHECK-LABEL: sil hidden @_T013objc_currying30curry_weirdOwnership_AnyObjectySo9CurryTestCSgAEcyXlF : $@convention(thin) (@owned AnyObject) -> @owned @callee_guaranteed (@owned Optional) -> @owned Optional // CHECK: bb0([[ANY:%.*]] : @owned $AnyObject): // CHECK: [[BORROWED_ANY:%.*]] = begin_borrow [[ANY]] // CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[BORROWED_ANY]] // CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]] // CHECK: dynamic_method_br [[SELF:%.*]] : $@opened({{.*}}) AnyObject, #CurryTest.weirdOwnership!1.foreign, [[HAS_METHOD:bb[0-9]+]] // CHECK: bb1([[METHOD:%.*]] : @trivial $@convention(objc_method) (@owned Optional, @owned @opened({{.*}}) AnyObject) -> @owned Optional): // CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]] // CHECK: partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]]) // CHECK: } // end sil function '_T013objc_currying30curry_weirdOwnership_AnyObjectySo9CurryTestCSgAEcyXlF' func curry_weirdOwnership_AnyObject(_ x: AnyObject) -> (CurryTest?) -> CurryTest? { return x.weirdOwnership! } // bridged requires a thunk to handle bridging conversions // CHECK-LABEL: sil hidden @_T013objc_currying23curry_bridged_AnyObjectySSSgACcyXlF : $@convention(thin) (@owned AnyObject) -> @owned @callee_guaranteed (@owned Optional) -> @owned Optional // CHECK: bb0([[ANY:%.*]] : @owned $AnyObject): // CHECK: [[BORROWED_ANY:%.*]] = begin_borrow [[ANY]] // CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[BORROWED_ANY]] // CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]] // CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.bridged!1.foreign, [[HAS_METHOD:bb[0-9]+]] // CHECK: } // end sil function '_T013objc_currying23curry_bridged_AnyObjectySSSgACcyXlF' func curry_bridged_AnyObject(_ x: AnyObject) -> (String?) -> String? { return x.bridged! } // check that we substitute Self = AnyObject correctly for Self-returning // methods // CHECK-LABEL: sil hidden @_T013objc_currying27curry_returnsSelf_AnyObjectyyXlSgycyXlF : $@convention(thin) (@owned AnyObject) -> @owned @callee_guaranteed () -> @owned Optional { // CHECK: bb0([[ANY:%.*]] : @owned $AnyObject): // CHECK: [[BORROWED_ANY:%.*]] = begin_borrow [[ANY]] // CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[BORROWED_ANY]] // CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]] // CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.returnsSelf!1.foreign, [[HAS_METHOD:bb[0-9]+]] // CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (@opened({{.*}}) AnyObject) -> @autoreleased Optional): // CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]] // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]]) // CHECK: } // end sil function '_T013objc_currying27curry_returnsSelf_AnyObjectyyXlSgycyXlF' func curry_returnsSelf_AnyObject(_ x: AnyObject) -> () -> AnyObject? { return x.returnsSelf! } // CHECK-LABEL: sil hidden @_T013objc_currying35curry_returnsInnerPointer_AnyObjectySvSgycyXlF : $@convention(thin) (@owned AnyObject) -> @owned @callee_guaranteed () -> Optional { // CHECK: bb0([[ANY:%.*]] : @owned $AnyObject): // CHECK: [[BORROWED_ANY:%.*]] = begin_borrow [[ANY]] // CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[BORROWED_ANY]] // CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]] // CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.returnsInnerPointer!1.foreign, [[HAS_METHOD:bb[0-9]+]] // CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (@opened({{.*}}) AnyObject) -> @unowned_inner_pointer Optional): // CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]] // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]]) // CHECK: } // end sil function '_T013objc_currying35curry_returnsInnerPointer_AnyObjectySvSgycyXlF' func curry_returnsInnerPointer_AnyObject(_ x: AnyObject) -> () -> UnsafeMutableRawPointer? { return x.returnsInnerPointer! }