|
| 1 | +// RUN: %target-swift-emit-silgen -module-name parameterized -enable-parameterized-protocol-types %s | %FileCheck %s |
| 2 | + |
| 3 | +protocol P<T, U, V> {} |
| 4 | + |
| 5 | +protocol Q<X, Y, Z> : P {} |
| 6 | + |
| 7 | +struct S: Q { |
| 8 | + typealias T = Int |
| 9 | + typealias U = String |
| 10 | + typealias V = Float |
| 11 | + |
| 12 | + typealias X = Int |
| 13 | + typealias Y = String |
| 14 | + typealias Z = Float |
| 15 | +} |
| 16 | + |
| 17 | +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized6upcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out P { |
| 18 | +func upcast(_ x: S) -> any P { |
| 19 | + // CHECK: bb0([[RESULT_PARAM:%.*]] : $*P, [[CONCRETE_VAL:%.*]] : $S): |
| 20 | + // CHECK: [[Q_INT_STRING_FLOAT:%.*]] = alloc_stack $Q<Int, String, Float> |
| 21 | + // CHECK: [[INIT_Q_INT_STRING_FLOAT:%.*]] = init_existential_addr [[Q_INT_STRING_FLOAT]] : $*Q<Int, String, Float>, $S |
| 22 | + // CHECK: store [[CONCRETE_VAL]] to [trivial] [[INIT_Q_INT_STRING_FLOAT]] : $*S |
| 23 | + // CHECK: [[OPEN_Q_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access [[Q_INT_STRING_FLOAT]] : $*Q<Int, String, Float> to $*[[OPENED_Q_INT_STRING_FLOAT:@opened(.*) Q<Int, String, Float>]] |
| 24 | + // CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*P, $[[OPENED_Q_INT_STRING_FLOAT]] |
| 25 | + // CHECK: copy_addr [[OPEN_Q_INT_STRING_FLOAT]] to [initialization] [[RESULT_INIT]] : $*[[OPENED_Q_INT_STRING_FLOAT]] |
| 26 | + |
| 27 | + return x as any Q<Int, String, Float> as any P |
| 28 | +} |
| 29 | + |
| 30 | +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized12upupupupcastyAA1P_pAA1SVF : $@convention(thin) (S) -> @out P { |
| 31 | +func upupupupcast(_ x: S) -> any P { |
| 32 | + // CHECK: bb0([[RESULT_PARAM:%.*]] : $*P, [[CONCRETE_VAL:%.*]] : $S): |
| 33 | + |
| 34 | + // CHECK: [[P_INT_STRING_FLOAT:%.*]] = alloc_stack $P<Int, String, Float> |
| 35 | + // CHECK: [[INIT_INT_STRING_FLOAT:%.*]] = init_existential_addr [[P_INT_STRING_FLOAT]] : $*P<Int, String, Float>, $S |
| 36 | + // CHECK: store [[CONCRETE_VAL]] to [trivial] [[INIT_INT_STRING_FLOAT]] : $*S |
| 37 | + // CHECK: [[OPEN_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access %3 : $*P<Int, String, Float> to $*[[OPENED_P_INT_STRING_FLOAT:@opened(.*) P<Int, String, Float>]] |
| 38 | + |
| 39 | + // CHECK: [[P_INT_STRING:%.*]] = alloc_stack $P<Int, String> |
| 40 | + // CHECK: [[INIT_INT_STRING:%.*]] = init_existential_addr [[P_INT_STRING]] : $*P<Int, String>, $[[OPENED_P_INT_STRING_FLOAT]] |
| 41 | + // CHECK: copy_addr [[OPEN_INT_STRING_FLOAT]] to [initialization] [[INIT_INT_STRING]] : $*[[OPENED_P_INT_STRING_FLOAT]] |
| 42 | + // CHECK: [[OPEN_INT_STRING:%.*]] = open_existential_addr immutable_access [[P_INT_STRING]] : $*P<Int, String> to $*[[OPENED_P_INT_STRING:@opened(.*) P<Int, String>]] |
| 43 | + |
| 44 | + // CHECK: [[P_INT:%.*]] = alloc_stack $P<Int> |
| 45 | + // CHECK: [[INIT_INT:%.*]] = init_existential_addr [[P_INT]] : $*P<Int>, $[[OPENED_P_INT_STRING]] |
| 46 | + // CHECK: copy_addr [[OPEN_INT_STRING]] to [initialization] [[INIT_INT]] : $*[[OPENED_P_INT_STRING]] |
| 47 | + // CHECK: [[OPEN_INT:%.*]] = open_existential_addr immutable_access [[P_INT]] : $*P<Int> to $*[[OPENED_P_INT:@opened(.*) P<Int>]] |
| 48 | + |
| 49 | + // CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*P, $[[OPENED_P_INT]] |
| 50 | + // CHECK: copy_addr [[OPEN_INT]] to [initialization] [[RESULT_INIT]] : $*[[OPENED_P_INT]] |
| 51 | + return x as any P<Int, String, Float> as any P<Int, String> as any P<Int> as any P |
| 52 | +} |
| 53 | + |
| 54 | +func use(_ k: (S) -> Void) {} |
| 55 | + |
| 56 | +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized11upcastInputyyF : $@convention(thin) () -> () { |
| 57 | +func upcastInput() { |
| 58 | + // CHECK: [[INT_STRING_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pySiSSXPXEfU_ : $@convention(thin) (@in_guaranteed P<Int, String>) -> () |
| 59 | + // CHECK: [[NOESCAPE_INT_STRING_FN:%.*]] = convert_function [[INT_STRING_FN]] : $@convention(thin) (@in_guaranteed P<Int, String>) -> () to $@convention(thin) @noescape (@in_guaranteed P<Int, String>) -> () |
| 60 | + // CHECK: [[THICK_INT_STRING_FN:%.*]] = thin_to_thick_function [[NOESCAPE_INT_STRING_FN]] : $@convention(thin) @noescape (@in_guaranteed P<Int, String>) -> () to $@noescape @callee_guaranteed (@in_guaranteed P<Int, String>) -> () |
| 61 | + // CHECK: [[S_TO_INT_STRING_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pySiSSXPIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int, String>) -> ()) -> () |
| 62 | + // CHECK: [[PARTIAL_INT_STRING_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_INT_STRING_THUNK_FN]]([[THICK_INT_STRING_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int, String>) -> ()) -> () |
| 63 | + // CHECK: [[NOESCAPE_INT_STRING_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_INT_STRING_THUNK_FN]] : $@callee_guaranteed (S) -> () to $@noescape @callee_guaranteed (S) -> () |
| 64 | + // CHECK: [[USE_FN:%.*]] = function_ref @$s13parameterized3useyyyAA1SVXEF : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () |
| 65 | + // CHECK: {{%.*}} = apply [[USE_FN]]([[NOESCAPE_INT_STRING_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () |
| 66 | + |
| 67 | + use({ (p: any P<Int, String>) -> Void in }) |
| 68 | + |
| 69 | + // CHECK: [[INT_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pySiXPXEfU0_ : $@convention(thin) (@in_guaranteed P<Int>) -> () |
| 70 | + // CHECK: [[NOESCAPE_INT_FN:%.*]] = convert_function [[INT_FN]] : $@convention(thin) (@in_guaranteed P<Int>) -> () to $@convention(thin) @noescape (@in_guaranteed P<Int>) -> () |
| 71 | + // CHECK: [[THICK_INT_FN:%.*]] = thin_to_thick_function [[NOESCAPE_INT_FN]] : $@convention(thin) @noescape (@in_guaranteed P<Int>) -> () to $@noescape @callee_guaranteed (@in_guaranteed P<Int>) -> () |
| 72 | + // CHECK: [[S_TO_INT_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pySiXPIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int>) -> ()) -> () |
| 73 | + // CHECK: [[PARTIAL_INT_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_INT_THUNK_FN]]([[THICK_INT_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int>) -> ()) -> () |
| 74 | + // CHECK: [[NOESCAPE_INT_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_INT_THUNK_FN]] : $@callee_guaranteed (S) -> () to $@noescape @callee_guaranteed (S) -> () |
| 75 | + // CHECK: [[USE_FN:%.*]] = function_ref @$s13parameterized3useyyyAA1SVXEF : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () |
| 76 | + // CHECK: {{%.*}} = apply [[USE_FN]]([[NOESCAPE_INT_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () |
| 77 | + |
| 78 | + use({ (p: any P<Int>) -> Void in }) |
| 79 | + |
| 80 | + // CHECK: [[P_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pXEfU1_ : $@convention(thin) (@in_guaranteed P) -> () |
| 81 | + // CHECK: [[NOESCAPE_P_FN:%.*]] = convert_function [[P_FN]] : $@convention(thin) (@in_guaranteed P) -> () to $@convention(thin) @noescape (@in_guaranteed P) -> () |
| 82 | + // CHECK: [[THICK_P_FN:%.*]] = thin_to_thick_function [[NOESCAPE_P_FN]] : $@convention(thin) @noescape (@in_guaranteed P) -> () to $@noescape @callee_guaranteed (@in_guaranteed P) -> () |
| 83 | + // CHECK: [[S_TO_P_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> () |
| 84 | + // CHECK: [[PARTIAL_INT_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_P_THUNK_FN]]([[THICK_P_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> () |
| 85 | + // CHECK: [[NOESCAPE_P_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_INT_THUNK_FN]] : $@callee_guaranteed (S) -> () to $@noescape @callee_guaranteed (S) -> () |
| 86 | + // CHECK: [[USE_FN:%.*]] = function_ref @$s13parameterized3useyyyAA1SVXEF : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () |
| 87 | + // CHECK: {{%.*}} = apply [[USE_FN]]([[NOESCAPE_P_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> () |
| 88 | + |
| 89 | + use({ (p: any P) -> Void in }) |
| 90 | +} |
| 91 | + |
| 92 | +func reuse(_ k: () -> any P<Int, String, Float>) {} |
| 93 | + |
| 94 | +// CHECK-LABEL: sil hidden [ossa] @$s13parameterized12upcastResultyyF : $@convention(thin) () -> () { |
| 95 | +func upcastResult() { |
| 96 | + // CHECK: [[RES_FN:%.*]] = function_ref @$s13parameterized12upcastResultyyFAA1SVyXEfU_ : $@convention(thin) () -> S |
| 97 | + // CHECK: [[NOESCAPE_RES_FN:%.*]] = convert_function [[RES_FN]] : $@convention(thin) () -> S to $@convention(thin) @noescape () -> S |
| 98 | + // CHECK: [[THICK_RES_FN:%.*]] = thin_to_thick_function [[NOESCAPE_RES_FN]] : $@convention(thin) @noescape () -> S to $@noescape @callee_guaranteed () -> S |
| 99 | + // CHECK: [[S_TO_P_RES_THUNK_FN:%.*]] = function_ref @$s13parameterized1SVIgd_AA1P_pySiSSSfXPIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> S) -> @out P<Int, String, Float> |
| 100 | + // CHECK: [[PARTIAL_RES_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_P_RES_THUNK_FN]]([[THICK_RES_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> S) -> @out P<Int, String, Float> |
| 101 | + // CHECK: [[NOESCAPE_RES_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_RES_THUNK_FN]] : $@callee_guaranteed () -> @out P<Int, String, Float> to $@noescape @callee_guaranteed () -> @out P<Int, String, Float> |
| 102 | + // CHECK: [[REUSE_FN:%.*]] = function_ref @$s13parameterized5reuseyyAA1P_pySiSSSfXPyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> @out P<Int, String, Float>) -> () |
| 103 | + // CHECK: {{%.*}} = apply [[REUSE_FN]]([[NOESCAPE_RES_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out P<Int, String, Float>) -> () |
| 104 | + |
| 105 | + reuse({ () -> S in S() }) |
| 106 | + |
| 107 | + // CHECK: [[RES_Q_FN:%.*]] = function_ref @$s13parameterized12upcastResultyyFAA1Q_pySiSSSfXPyXEfU0_ : $@convention(thin) () -> @out Q<Int, String, Float> |
| 108 | + // CHECK: [[NOESCAPE_RES_Q_FN:%.*]] = convert_function [[RES_Q_FN]] : $@convention(thin) () -> @out Q<Int, String, Float> to $@convention(thin) @noescape () -> @out Q<Int, String, Float> |
| 109 | + // CHECK: [[THICK_NOESCAPE_RES_Q_FN:%.*]] = thin_to_thick_function [[NOESCAPE_RES_Q_FN]] : $@convention(thin) @noescape () -> @out Q<Int, String, Float> to $@noescape @callee_guaranteed () -> @out Q<Int, String, Float> |
| 110 | + // CHECK: [[P_TO_Q_RES_THUNK_FN:%.*]] = function_ref @$s13parameterized1Q_pySiSSSfXPIgr_AA1P_pySiSSSfXPIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> @out Q<Int, String, Float>) -> @out P<Int, String, Float> |
| 111 | + // CHECK: [[PARTIAL_P_TO_Q_RES_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[P_TO_Q_RES_THUNK_FN]]([[THICK_NOESCAPE_RES_Q_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out Q<Int, String, Float>) -> @out P<Int, String, Float> |
| 112 | + // CHECK: [[NOESCAPE_PARTIAL_P_TO_Q_RES_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_P_TO_Q_RES_THUNK_FN]] : $@callee_guaranteed () -> @out P<Int, String, Float> to $@noescape @callee_guaranteed () -> @out P<Int, String, Float> |
| 113 | + // CHECK: [[REUSE_FN:%.*]] = function_ref @$s13parameterized5reuseyyAA1P_pySiSSSfXPyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> @out P<Int, String, Float>) -> () |
| 114 | + // CHECK: {{%.*}} = apply [[REUSE_FN]]([[NOESCAPE_PARTIAL_P_TO_Q_RES_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @out P<Int, String, Float>) -> () |
| 115 | + |
| 116 | + reuse({ () -> any Q<Int, String, Float> in S() }) |
| 117 | +} |
0 commit comments