1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
// RUN: %target-swift-frontend -enable-copy-propagation=requested-passes-only -enable-lexical-lifetimes=false -emit-sil %s -swift-version 5 -verify | %FileCheck %s
// Ensure that convenience initializers on concrete types can
// delegate to factory initializers defined in protocol
// extensions.
protocol TriviallyConstructible {
init(lower: Int)
}
extension TriviallyConstructible {
init(middle: Int) {
self.init(lower: middle)
}
init?(failingMiddle: Int) {
self.init(lower: failingMiddle)
}
init(throwingMiddle: Int) throws {
self.init(lower: throwingMiddle)
}
}
class TrivialClass : TriviallyConstructible {
required init(lower: Int) {}
// CHECK-LABEL: sil hidden @$s023definite_init_protocol_B012TrivialClassC5upperACSi_tcfC
// CHECK: bb0(%0 : $Int, [[SELF_META:%.*]] : $@thick TrivialClass.Type):
// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack [var_decl] $TrivialClass
// CHECK-NEXT: debug_value
// CHECK-NEXT: [[METATYPE:%.*]] = unchecked_trivial_bit_cast [[SELF_META]] {{.*}} to $@thick @dynamic_self TrivialClass.Type
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $TrivialClass
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s023definite_init_protocol_B022TriviallyConstructiblePAAE6middlexSi_tcfC
// CHECK-NEXT: apply [[FN]]<@dynamic_self TrivialClass>([[RESULT]], %0, [[METATYPE]])
// CHECK-NEXT: [[NEW_SELF:%.*]] = load [[RESULT]]
// TODO: Once we restore arbitrary takes, the strong_retain/destroy_addr pair below will go away.
// CHECK-NEXT: strong_retain [[NEW_SELF]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[RESULT]]
// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
convenience init(upper: Int) {
self.init(middle: upper)
}
convenience init?(failingUpper: Int) {
self.init(failingMiddle: failingUpper)
}
convenience init(throwingUpper: Int) throws {
try self.init(throwingMiddle: throwingUpper)
}
}
struct TrivialStruct : TriviallyConstructible {
let x: Int
init(lower: Int) { self.x = lower }
// CHECK-LABEL: sil hidden @$s023definite_init_protocol_B013TrivialStructV5upperACSi_tcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin TrivialStruct.Type):
// CHECK-NEXT: [[SELF:%.*]] = alloc_stack [var_decl] $TrivialStruct
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $TrivialStruct
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick TrivialStruct.Type
// CHECK: [[FN:%.*]] = function_ref @$s023definite_init_protocol_B022TriviallyConstructiblePAAE6middlexSi_tcfC
// CHECK-NEXT: apply [[FN]]<TrivialStruct>([[SELF_BOX]], %0, [[METATYPE]])
// CHECK-NEXT: [[NEW_SELF:%.*]] = load [[SELF_BOX]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF]]
// CHECK-NEXT: return [[NEW_SELF]]
init(upper: Int) {
self.init(middle: upper)
}
init?(failingUpper: Int) {
self.init(failingMiddle: failingUpper)
}
init(throwingUpper: Int) throws {
try self.init(throwingMiddle: throwingUpper)
}
}
struct AddressOnlyStruct : TriviallyConstructible {
let x: Any
init(lower: Int) { self.x = lower }
// CHECK-LABEL: sil hidden @$s023definite_init_protocol_B017AddressOnlyStructV5upperACSi_tcfC
// CHECK: bb0(%0 : $*AddressOnlyStruct, %1 : $Int, %2 : $@thin AddressOnlyStruct.Type):
// CHECK-NEXT: [[SELF:%.*]] = alloc_stack [var_decl] $AddressOnlyStruct
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $AddressOnlyStruct
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick AddressOnlyStruct.Type
// CHECK: [[FN:%.*]] = function_ref @$s023definite_init_protocol_B022TriviallyConstructiblePAAE6middlexSi_tcfC
// CHECK-NEXT: apply [[FN]]<AddressOnlyStruct>([[SELF_BOX]], %1, [[METATYPE]])
// CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [init] [[SELF]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: copy_addr [take] [[SELF]] to [init] %0
// CHECK-NEXT: dealloc_stack [[SELF]]
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
// CHECK-NEXT: return [[RESULT]]
init(upper: Int) {
self.init(middle: upper)
}
init?(failingUpper: Int) {
self.init(failingMiddle: failingUpper)
}
init(throwingUpper: Int) throws {
try self.init(throwingMiddle: throwingUpper)
}
}
enum TrivialEnum : TriviallyConstructible {
case NotSoTrivial
init(lower: Int) {
self = .NotSoTrivial
}
// CHECK-LABEL: sil hidden @$s023definite_init_protocol_B011TrivialEnumO5upperACSi_tcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin TrivialEnum.Type):
// CHECK-NEXT: [[SELF:%.*]] = alloc_stack [var_decl] $TrivialEnum
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $TrivialEnum
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick TrivialEnum.Type
// CHECK: [[FN:%.*]] = function_ref @$s023definite_init_protocol_B022TriviallyConstructiblePAAE6middlexSi_tcfC
// CHECK-NEXT: apply [[FN]]<TrivialEnum>([[SELF_BOX]], %0, [[METATYPE]])
// CHECK-NEXT: [[NEW_SELF:%.*]] = load [[SELF_BOX]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF]]
// CHECK-NEXT: return [[NEW_SELF]]
init(upper: Int) {
self.init(middle: upper)
}
init?(failingUpper: Int) {
self.init(failingMiddle: failingUpper)
}
init(throwingUpper: Int) throws {
try self.init(throwingMiddle: throwingUpper)
}
}
|