|
| 1 | +// RUN: %target-swift-emit-silgen %s -verify | %FileCheck %s |
| 2 | + |
| 3 | +class User { |
| 4 | + @preconcurrency var dict: [String : any Sendable] = [:] |
| 5 | + @preconcurrency var arr: [any Sendable] = [] |
| 6 | + // Note: No Set because `any Sendable` is not Hashable |
| 7 | +} |
| 8 | + |
| 9 | +extension Dictionary where Key == String, Value == Any { |
| 10 | + func onlyWhenValueAny() {} |
| 11 | +} |
| 12 | + |
| 13 | +extension Array where Element == Any { |
| 14 | + func onlyWhenValueAny() {} |
| 15 | +} |
| 16 | + |
| 17 | +// CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments31test_conditional_on_collections1uyAA4UserC_tF |
| 18 | +// CHECK: unchecked_bitwise_cast {{.*}} to $Dictionary<String, Any> |
| 19 | +// CHECK: unchecked_bitwise_cast {{.*}} to $Array<Any> |
| 20 | +func test_conditional_on_collections(u: User) { |
| 21 | + u.dict.onlyWhenValueAny() |
| 22 | + u.arr.onlyWhenValueAny() |
| 23 | +} |
| 24 | + |
| 25 | +// Check that `any Sendable` extension is preferred. |
| 26 | + |
| 27 | +extension Dictionary where Key == String, Value == Any { |
| 28 | + func noAmbiguity() {} |
| 29 | +} |
| 30 | + |
| 31 | +extension Array where Element == Any { |
| 32 | + func noAmbiguity() {} |
| 33 | +} |
| 34 | + |
| 35 | +extension Dictionary where Key == String, Value == any Sendable { |
| 36 | + func noAmbiguity() {} |
| 37 | +} |
| 38 | + |
| 39 | +extension Array where Element == any Sendable { |
| 40 | + func noAmbiguity() {} |
| 41 | +} |
| 42 | + |
| 43 | +// CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments41test_no_ambiguity_with_Sendable_extension1uyAA4UserC_tF |
| 44 | +// CHECK-NOT: unchecked_bitwise_cast {{.*}} |
| 45 | +// CHECK: [[DICT_METHOD_REF:%.*]] = function_ref @$sSD37sendable_to_any_for_generic_argumentsSSRszs8Sendable_pRs_rlE11noAmbiguityyyF : $@convention(method) (@guaranteed Dictionary<String, any Sendable>) -> () |
| 46 | +// CHECK-NEXT: {{.*}} = apply [[DICT_METHOD_REF]]({{.*}}) : $@convention(method) (@guaranteed Dictionary<String, any Sendable>) -> () |
| 47 | +// CHECK-NOT: unchecked_bitwise_cast {{.*}} |
| 48 | +// CHECK: [[ARR_METHOD_REF:%.*]] = function_ref @$sSa37sendable_to_any_for_generic_argumentss8Sendable_pRszlE11noAmbiguityyyF : $@convention(method) (@guaranteed Array<any Sendable>) -> () |
| 49 | +// CHECK-NEXT: {{.*}} = apply [[ARR_METHOD_REF]]({{.*}}) : $@convention(method) (@guaranteed Array<any Sendable>) -> () |
| 50 | +func test_no_ambiguity_with_Sendable_extension(u: User) { |
| 51 | + u.dict.noAmbiguity() |
| 52 | + u.arr.noAmbiguity() |
| 53 | +} |
| 54 | + |
| 55 | +struct S<T> { |
| 56 | +} |
| 57 | + |
| 58 | +extension S where T == Any { |
| 59 | + func anyOnly() {} |
| 60 | +} |
| 61 | + |
| 62 | +struct TestGeneral { |
| 63 | + @preconcurrency var v: S<any Sendable> |
| 64 | + @preconcurrency var optV: S<[(any Sendable)?]> |
| 65 | + |
| 66 | + func accepts_any(_: S<Any>) {} |
| 67 | + func accepts_opt_any(_: S<[Any?]>) {} |
| 68 | + func sameType<T>(_: S<T>, _: T.Type) {} |
| 69 | + |
| 70 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV15test_contextualAA1SVyypGyF |
| 71 | + // CHECK: [[V_REF:%.*]] = struct_extract %0, #TestGeneral.v |
| 72 | + // CHECK-NEXT: {{.*}} = unchecked_trivial_bit_cast [[V_REF]] to $S<Any> |
| 73 | + func test_contextual() -> S<Any> { |
| 74 | + v |
| 75 | + } |
| 76 | + |
| 77 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV15test_member_refyyF |
| 78 | + // CHECK: [[V_REF:%.*]] = struct_extract %0, #TestGeneral.v |
| 79 | + // CHECK-NEXT: [[V_WITH_ANY:%.*]] = unchecked_trivial_bit_cast [[V_REF:%.*]] to $S<Any> |
| 80 | + // CHECK: [[MEMBER_REF:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments1SVAAypRszlE0C4OnlyyyF : $@convention(method) (S<Any>) -> () |
| 81 | + // CHECK-NEXT: {{.*}} = apply [[MEMBER_REF]]([[V_WITH_ANY:%.*]]) : $@convention(method) (S<Any>) -> () |
| 82 | + func test_member_ref() { |
| 83 | + v.anyOnly() |
| 84 | + } |
| 85 | + |
| 86 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV24test_passing_as_argumentyyF |
| 87 | + // CHECK: [[V_REF:%.*]] = struct_extract %0, #TestGeneral.v |
| 88 | + // CHECK-NEXT: [[V_ANY:%.*]] = unchecked_trivial_bit_cast [[V_REF]] to $S<Any> |
| 89 | + // CHECK: [[MEMBER_REF:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments11TestGeneralV08accepts_C0yyAA1SVyypGF : $@convention(method) (S<Any>, TestGeneral) -> () |
| 90 | + // CHECK-NEXT: {{.*}} = apply [[MEMBER_REF]]([[V_ANY]], %0) : $@convention(method) (S<Any>, TestGeneral) -> () |
| 91 | + func test_passing_as_argument() { |
| 92 | + accepts_any(v) |
| 93 | + } |
| 94 | + |
| 95 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV39test_passing_as_argument_through_member1tyAC_tF |
| 96 | + // CHECK: [[V_REF:%.*]] = struct_extract %0, #TestGeneral.v |
| 97 | + // CHECK-NEXT: [[V_ANY:%.*]] = unchecked_trivial_bit_cast [[V_REF]] to $S<Any> |
| 98 | + // CHECK: [[MEMBER_REF:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments11TestGeneralV08accepts_C0yyAA1SVyypGF : $@convention(method) (S<Any>, TestGeneral) -> () |
| 99 | + // CHECK-NEXT: {{.*}} = apply [[MEMBER_REF]]([[V_ANY]], %1) : $@convention(method) (S<Any>, TestGeneral) -> () |
| 100 | + func test_passing_as_argument_through_member(t: TestGeneral) { |
| 101 | + accepts_any(t.v) |
| 102 | + } |
| 103 | + |
| 104 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV23test_complex_contextualAA1SVySayypSgGGyF |
| 105 | + // CHECK: [[V_REF:%.*]] = struct_extract %0, #TestGeneral.optV |
| 106 | + // CHECK-NEXT: {{.*}} = unchecked_trivial_bit_cast [[V_REF]] to $S<Array<Optional<Any>>> |
| 107 | + func test_complex_contextual() -> S<[Any?]> { |
| 108 | + optV |
| 109 | + } |
| 110 | + |
| 111 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV26test_complex_with_argument1tyAC_tF |
| 112 | + // CHECK: [[SELF_V_REF:%.*]] = struct_extract %1, #TestGeneral.optV |
| 113 | + // CHECK-NEXT: [[SELF_V_ANY:%.*]] = unchecked_trivial_bit_cast [[SELF_V_REF]] to $S<Array<Optional<Any>>> |
| 114 | + // CHECK: [[MEMBER_REF_1:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments11TestGeneralV012accepts_opt_C0yyAA1SVySayypSgGGF : $@convention(method) (S<Array<Optional<Any>>>, TestGeneral) -> () |
| 115 | + // CHECK-NEXT: {{.*}} = apply [[MEMBER_REF_1]]([[SELF_V_ANY]], %1) : $@convention(method) (S<Array<Optional<Any>>>, TestGeneral) -> () |
| 116 | + // CHECK: [[V_REF_ON_T:%.*]] = struct_extract %0, #TestGeneral.optV |
| 117 | + // CHECK-NEXT: [[V_ANY_ON_T:%.]] = unchecked_trivial_bit_cast [[V_REF_ON_T]] to $S<Array<Optional<Any>>> |
| 118 | + // CHECK: [[MEMBER_REF_2:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments11TestGeneralV012accepts_opt_C0yyAA1SVySayypSgGGF : $@convention(method) (S<Array<Optional<Any>>>, TestGeneral) -> () |
| 119 | + // CHECK-NEXT: {{.*}} = apply [[MEMBER_REF_2]]([[V_ANY_ON_T]], %1) : $@convention(method) (S<Array<Optional<Any>>>, TestGeneral) -> () |
| 120 | + func test_complex_with_argument(t: TestGeneral) { |
| 121 | + accepts_opt_any(optV) |
| 122 | + accepts_opt_any(t.optV) |
| 123 | + } |
| 124 | + |
| 125 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV14test_same_typeyyF |
| 126 | + // CHECK: [[V_REF:%.*]] = struct_extract %0, #TestGeneral.v |
| 127 | + // CHECK-NEXT: [[V_ANY:%.*]] = unchecked_trivial_bit_cast [[V_REF]] to $S<Any> |
| 128 | + // CHECK: [[ANY_METATYPE:%.*]] = metatype $@thick (any Any).Type |
| 129 | + // CHECK: [[SAME_TYPE_FN:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments11TestGeneralV8sameTypeyyAA1SVyxG_xmtlF : $@convention(method) <τ_0_0> (S<τ_0_0>, @thick τ_0_0.Type, TestGeneral) -> () |
| 130 | + // CHECK-NEXT: %7 = apply %6<Any>([[V_ANY]], [[ANY_METATYPE]], %0) |
| 131 | + func test_same_type() { |
| 132 | + sameType(v, Any.self) |
| 133 | + } |
| 134 | + |
| 135 | + // CHECK-LABEL: sil hidden [ossa] @$s37sendable_to_any_for_generic_arguments11TestGeneralV18test_address_castsyyF |
| 136 | + // CHECK: [[DATA_REF:%.*]] = struct_element_addr %2, #<abstract function>Test.data |
| 137 | + // CHECK-NEXT: [[DATA_COPY:%.*]] = alloc_stack $V<any Sendable> |
| 138 | + // CHECK-NEXT: copy_addr [[DATA_REF]] to [init] [[DATA_COPY]] |
| 139 | + // CHECK-NEXT: [[DATA_ANY:%.*]] = unchecked_addr_cast [[DATA_COPY]] to $*V<Any> |
| 140 | + // CHECK: [[ACCEPTS_ANY:%.*]] = function_ref @$s37sendable_to_any_for_generic_arguments11TestGeneralV18test_address_castsyyF08accepts_C0L_yyAcDyyF1VL_VyypGF : $@convention(thin) (@in_guaranteed V<Any>) -> () |
| 141 | + // CHECK-NEXT: {{.*}} = apply [[ACCEPTS_ANY]]([[DATA_ANY]]) : $@convention(thin) (@in_guaranteed V<Any>) -> () |
| 142 | + func test_address_casts() { |
| 143 | + struct V<T> { |
| 144 | + let v: T |
| 145 | + } |
| 146 | + |
| 147 | + struct Test { |
| 148 | + @preconcurrency var data: V<any Sendable> |
| 149 | + } |
| 150 | + |
| 151 | + |
| 152 | + func accepts_any(_: V<Any>) {} |
| 153 | + |
| 154 | + let test = Test(data: V(v: 42)) |
| 155 | + accepts_any(test.data) |
| 156 | + } |
| 157 | +} |
0 commit comments