blob: 0454de60a815c2c798874b4264e3e77760eadfb6 [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t -enable-library-evolution %S/Inputs/property_wrapper_defs.swift
// RUN: %target-swift-emit-silgen -primary-file %s -I %t | %FileCheck %s
import property_wrapper_defs
@propertyWrapper
struct Wrapper<T> {
var wrappedValue: T
init(value: T) {
wrappedValue = value
}
}
@propertyWrapper
struct WrapperWithInitialValue<T> {
var wrappedValue: T
}
protocol DefaultInit {
init()
}
extension Int: DefaultInit { }
struct HasMemberwiseInit<T: DefaultInit> {
@Wrapper(value: false)
var x: Bool
@WrapperWithInitialValue
var y: T = T()
@WrapperWithInitialValue(wrappedValue: 17)
var z: Int
@WrapperWithInitialValue
private var p: Bool = true
}
func forceHasMemberwiseInit() {
_ = HasMemberwiseInit(x: Wrapper(value: true), y: 17, z: WrapperWithInitialValue(wrappedValue: 42))
_ = HasMemberwiseInit<Int>(x: Wrapper(value: true))
_ = HasMemberwiseInit(y: 17)
_ = HasMemberwiseInit<Int>(z: WrapperWithInitialValue(wrappedValue: 42))
_ = HasMemberwiseInit<Int>()
}
// CHECK: sil_global private @$s17property_wrappers9UseStaticV13_staticWibble33_{{.*}}AA4LazyOySaySiGGvpZ : $Lazy<Array<Int>>
// HasMemberwiseInit.x.setter
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers17HasMemberwiseInitV1xSbvs : $@convention(method) <T where T : DefaultInit> (Bool, @inout HasMemberwiseInit<T>) -> () {
// CHECK: bb0(%0 : $Bool, %1 : $*HasMemberwiseInit<T>):
// CHECK: [[MODIFY_SELF:%.*]] = begin_access [modify] [unknown] %1 : $*HasMemberwiseInit<T>
// CHECK: [[X_BACKING:%.*]] = struct_element_addr [[MODIFY_SELF]] : $*HasMemberwiseInit<T>, #HasMemberwiseInit._x
// CHECK: [[X_BACKING_VALUE:%.*]] = struct_element_addr [[X_BACKING]] : $*Wrapper<Bool>, #Wrapper.wrappedValue
// CHECK: assign %0 to [[X_BACKING_VALUE]] : $*Bool
// CHECK: end_access [[MODIFY_SELF]] : $*HasMemberwiseInit<T>
// variable initialization expression of HasMemberwiseInit._x
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_x33_{{.*}}AA7WrapperVySbGvpfi : $@convention(thin) <T where T : DefaultInit> () -> Wrapper<Bool> {
// CHECK: integer_literal $Builtin.Int1, 0
// CHECK-NOT: return
// CHECK: function_ref @$sSb22_builtinBooleanLiteralSbBi1__tcfC : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers7WrapperV5valueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0> // user: %9
// CHECK: return {{%.*}} : $Wrapper<Bool>
// variable initialization expression of HasMemberwiseInit.$y
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_y33_{{.*}}23WrapperWithInitialValueVyxGvpfi : $@convention(thin) <T where T : DefaultInit> () -> @out
// CHECK: bb0(%0 : $*T):
// CHECK-NOT: return
// CHECK: witness_method $T, #DefaultInit.init!allocator : <Self where Self : DefaultInit> (Self.Type) -> () -> Self : $@convention(witness_method: DefaultInit) <τ_0_0 where τ_0_0 : DefaultInit> (@thick τ_0_0.Type) -> @out τ_0_0
// variable initialization expression of HasMemberwiseInit._z
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_z33_{{.*}}23WrapperWithInitialValueVySiGvpfi : $@convention(thin) <T where T : DefaultInit> () -> WrapperWithInitialValue<Int> {
// CHECK: bb0:
// CHECK-NOT: return
// CHECK: integer_literal $Builtin.IntLiteral, 17
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers23WrapperWithInitialValueV07wrappedF0ACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin WrapperWithInitialValue<τ_0_0>.Type) -> @out WrapperWithInitialValue<τ_0_0>
// variable initialization expression of HasMemberwiseInit._p
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_p33_{{.*}}23WrapperWithInitialValueVySbGvpfi : $@convention(thin) <T where T : DefaultInit> () -> Bool {
// CHECK: function_ref @$sSb22_builtinBooleanLiteralSbBi1__tcfC : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool
// CHECK: return {{%.*}} : $Bool
// default argument 0 of HasMemberwiseInit.init(x:y:z:)
// CHECK: sil hidden [ossa] @$s17property_wrappers17HasMemberwiseInitV1x1y1zACyxGAA7WrapperVySbG_xAA0F16WithInitialValueVySiGtcfcfA_ : $@convention(thin) <T where T : DefaultInit> () -> Wrapper<Bool>
// default argument 1 of HasMemberwiseInit.init(x:y:z:)
// CHECK: sil hidden [ossa] @$s17property_wrappers17HasMemberwiseInitV1x1y1zACyxGAA7WrapperVySbG_xAA0F16WithInitialValueVySiGtcfcfA0_ : $@convention(thin) <T where T : DefaultInit> () -> @out T {
// default argument 2 of HasMemberwiseInit.init(x:y:z:)
// CHECK: sil hidden [ossa] @$s17property_wrappers17HasMemberwiseInitV1x1y1zACyxGAA7WrapperVySbG_xAA0F16WithInitialValueVySiGtcfcfA1_ : $@convention(thin) <T where T : DefaultInit> () -> WrapperWithInitialValue<Int> {
// HasMemberwiseInit.init()
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers17HasMemberwiseInitVACyxGycfC : $@convention(method) <T where T : DefaultInit> (@thin HasMemberwiseInit<T>.Type) -> @out HasMemberwiseInit<T> {
// Initialization of x
// CHECK-NOT: return %
// CHECK: function_ref @$s17property_wrappers17HasMemberwiseInitV2_x33_{{.*}}7WrapperVySbGvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> () -> Wrapper<Bool>
// Initialization of y
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers17HasMemberwiseInitV2_y33_{{.*}}23WrapperWithInitialValueVyxGvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> () -> @out τ_0_0
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers17HasMemberwiseInitV1yxvpfP : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> (@in τ_0_0) -> @out WrapperWithInitialValue<τ_0_0>
// Initialization of z
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers17HasMemberwiseInitV2_z33_{{.*}}23WrapperWithInitialValueVySiGvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> () -> WrapperWithInitialValue<Int>
// Initialization of p
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers17HasMemberwiseInitV2_p33_{{.*}}23WrapperWithInitialValueVySbGvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> () -> Bool
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers17HasMemberwiseInitV1p33_{{.*}} : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> (Bool) -> WrapperWithInitialValue<Bool>
// CHECK: return
// Non-generic struct with private property wrapper
struct HasMemberwiseInitWithPrivateWrapper {
@WrapperWithInitialValue
var z: Int = 17
@WrapperWithInitialValue
private var p: Bool = true
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers35HasMemberwiseInitWithPrivateWrapperV1zACSi_tcfC : $@convention(method) (Int, @thin HasMemberwiseInitWithPrivateWrapper.Type) -> HasMemberwiseInitWithPrivateWrapper {
// CHECK: function_ref @$s17property_wrappers35HasMemberwiseInitWithPrivateWrapperV1zSivpfP : $@convention(thin) (Int) -> WrapperWithInitialValue<Int>
// CHECK: function_ref @$s17property_wrappers35HasMemberwiseInitWithPrivateWrapperV1p33_{{.*}} : $@convention(thin) (Bool) -> WrapperWithInitialValue<Bool>
// CHECK: return {{%.*}} : $HasMemberwiseInitWithPrivateWrapper
}
func forceHasMemberwiseInitWithPrivateWrapper() {
_ = HasMemberwiseInitWithPrivateWrapper(z: 42)
}
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers9HasNestedV2_y33_{{.*}}14PrivateWrapperAELLVyx_SayxGGvpfi : $@convention(thin) <T> () -> @owned Array<T> {
// CHECK: bb0:
// CHECK: function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF
struct HasNested<T> {
@propertyWrapper
private struct PrivateWrapper<U> {
var wrappedValue: U
}
@PrivateWrapper
private var y: [T] = []
static func blah(y: [T]) -> HasNested<T> {
return HasNested<T>()
}
}
// FIXME: For now, we are only checking that we don't crash.
struct HasDefaultInit {
@Wrapper(value: true)
var x
@WrapperWithInitialValue
var y = 25
static func defaultInit() -> HasDefaultInit {
return HasDefaultInit()
}
static func memberwiseInit(x: Bool, y: Int) -> HasDefaultInit {
return HasDefaultInit(x: Wrapper(value: x), y: y)
}
}
struct WrapperWithAccessors {
@Wrapper
var x: Int
// Synthesized setter
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers20WrapperWithAccessorsV1xSivs : $@convention(method) (Int, @inout WrapperWithAccessors) -> ()
// CHECK-NOT: return
// CHECK: struct_element_addr {{%.*}} : $*WrapperWithAccessors, #WrapperWithAccessors._x
mutating func test() {
x = 17
}
}
func consumeOldValue(_: Int) { }
func consumeNewValue(_: Int) { }
struct WrapperWithDidSetWillSet {
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers021WrapperWithDidSetWillF0V1xSivs
// CHECK: function_ref @$s17property_wrappers021WrapperWithDidSetWillF0V1xSivw
// CHECK: struct_element_addr {{%.*}} : $*WrapperWithDidSetWillSet, #WrapperWithDidSetWillSet._x
// CHECK-NEXT: struct_element_addr {{%.*}} : $*Wrapper<Int>, #Wrapper.wrappedValue
// CHECK-NEXT: assign %0 to {{%.*}} : $*Int
// CHECK: function_ref @$s17property_wrappers021WrapperWithDidSetWillF0V1xSivW
@Wrapper
var x: Int {
didSet {
consumeNewValue(oldValue)
}
willSet {
consumeOldValue(newValue)
}
}
mutating func test(x: Int) {
self.x = x
}
}
@propertyWrapper
struct WrapperWithStorageValue<T> {
var wrappedValue: T
var projectedValue: Wrapper<T> {
return Wrapper(value: wrappedValue)
}
}
struct UseWrapperWithStorageValue {
// UseWrapperWithStorageValue._x.getter
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers26UseWrapperWithStorageValueV2$xAA0D0VySiGvg : $@convention(method) (UseWrapperWithStorageValue) -> Wrapper<Int>
// CHECK-NOT: return
// CHECK: function_ref @$s17property_wrappers23WrapperWithStorageValueV09projectedF0AA0C0VyxGvg
@WrapperWithStorageValue(wrappedValue: 17) var x: Int
}
@propertyWrapper
enum Lazy<Value> {
case uninitialized(() -> Value)
case initialized(Value)
init(wrappedValue initialValue: @autoclosure @escaping () -> Value) {
self = .uninitialized(initialValue)
}
var wrappedValue: Value {
mutating get {
switch self {
case .uninitialized(let initializer):
let value = initializer()
self = .initialized(value)
return value
case .initialized(let value):
return value
}
}
set {
self = .initialized(newValue)
}
}
}
struct UseLazy<T: DefaultInit> {
@Lazy var foo = 17
@Lazy var bar = T()
@Lazy var wibble = [1, 2, 3]
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers7UseLazyV3foo3bar6wibbleACyxGSiyXA_xyXASaySiGyXAtcfC : $@convention(method) <T where T : DefaultInit> (@owned @callee_guaranteed () -> Int, @owned @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <T>, @owned @callee_guaranteed () -> @owned Array<Int>, @thin UseLazy<T>.Type) -> @out UseLazy<T> {
// CHECK: function_ref @$s17property_wrappers7UseLazyV3fooSivpfP : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> (@owned @callee_guaranteed () -> Int) -> @owned Lazy<Int>
// CHECK: function_ref @$s17property_wrappers7UseLazyV3barxvpfP : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> (@owned @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0>) -> @out Lazy<τ_0_0>
// CHECK: function_ref @$s17property_wrappers7UseLazyV6wibbleSaySiGvpfP : $@convention(thin) <τ_0_0 where τ_0_0 : DefaultInit> (@owned @callee_guaranteed () -> @owned Array<Int>) -> @owned Lazy<Array<Int>>
}
struct X { }
func triggerUseLazy() {
_ = UseLazy<Int>()
_ = UseLazy<Int>(foo: 17)
_ = UseLazy(bar: 17)
_ = UseLazy<Int>(wibble: [1, 2, 3])
}
func computeInt() -> Int {
return 42
}
func triggerUseLazyTestAutoclosure() {
_ = UseLazy(bar: computeInt())
// triggerUseLazyTestAutoclosure()
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers29triggerUseLazyTestAutoclosureyyF
// computeInt() must not get called here
// CHECK-NOT: // function_ref computeInt()
// CHECK-NOT: function_ref @$s17property_wrappers10computeIntSiyF : $@convention(thin) () -> Int
// Rather, an implicit closure is referenced
// CHECK: // function_ref implicit closure #1 in triggerUseLazyTestAutoclosure()
// CHECK: function_ref @$s17property_wrappers29triggerUseLazyTestAutoclosureyyFSiycfu_ : $@convention(thin) () -> Int
// And the implicit closure calls computeInt()
// CHECK: sil private [transparent] [ossa] @$s17property_wrappers29triggerUseLazyTestAutoclosureyyFSiycfu_ : $@convention(thin) () -> Int
// CHECK: // function_ref computeInt()
// CHECK: function_ref @$s17property_wrappers10computeIntSiyF : $@convention(thin) () -> Int
}
@propertyWrapper
struct WrapperWithNonEscapingAutoclosure<V> {
var wrappedValue: V
init(wrappedValue: @autoclosure () -> V) {
self.wrappedValue = wrappedValue()
}
}
struct UseWrapperWithNonEscapingAutoclosure {
@WrapperWithNonEscapingAutoclosure var p1: Int
@WrapperWithNonEscapingAutoclosure var p2: UInt = 10
// property wrapper backing initializer of UseWrapperWithNonEscapingAutoclosure.p1
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p1SivpfP : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> WrapperWithNonEscapingAutoclosure<Int>
// property wrapper backing initializer of UseWrapperWithNonEscapingAutoclosure.p2
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p2SuvpfP : $@convention(thin) (@noescape @callee_guaranteed () -> UInt) -> WrapperWithNonEscapingAutoclosure<UInt>
// variable initialization expression of UseWrapperWithNonEscapingAutoclosure._p2
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV3_p233_F728088E0028E14D18C6A10CF68512E8LLAA0defgH0VySuGvpfi : $@convention(thin) () -> @owned @callee_guaranteed () -> UInt
// CHECK: return %1 : $@callee_guaranteed () -> UInt
// default argument 1 of UseWrapperWithNonEscapingAutoclosure.init(p1:p2:)
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p12p2ACSiyXK_SuyXKtcfcfA0_ : $@convention(thin) () -> @owned @callee_guaranteed () -> UInt
// CHECK: return %1 : $@callee_guaranteed () -> UInt
// UseWrapperWithNonEscapingAutoclosure.init(p1:p2:)
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p12p2ACSiyXK_SuyXKtcfC : $@convention(method) (@noescape @callee_guaranteed () -> Int, @noescape @callee_guaranteed () -> UInt, @thin UseWrapperWithNonEscapingAutoclosure.Type) -> UseWrapperWithNonEscapingAutoclosure
}
struct UseStatic {
// CHECK: sil hidden [ossa] @$s17property_wrappers9UseStaticV12staticWibbleSaySiGvgZ
// CHECK: sil private [global_init] [ossa] @$s17property_wrappers9UseStaticV13_staticWibble33_{{.*}}4LazyOySaySiGGvau
// CHECK: sil hidden [ossa] @$s17property_wrappers9UseStaticV12staticWibbleSaySiGvsZ
@Lazy static var staticWibble = [1, 2, 3]
}
extension WrapperWithInitialValue {
func test() { }
}
class ClassUsingWrapper {
@WrapperWithInitialValue var x = 0
}
extension ClassUsingWrapper {
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers17ClassUsingWrapperC04testcdE01cyAC_tF : $@convention(method) (@guaranteed ClassUsingWrapper, @guaranteed ClassUsingWrapper) -> () {
func testClassUsingWrapper(c: ClassUsingWrapper) {
// CHECK: ref_element_addr %1 : $ClassUsingWrapper, #ClassUsingWrapper._x
self._x.test()
}
}
//
@propertyWrapper
struct WrapperWithDefaultInit<T> {
private var storage: T?
init() {
self.storage = nil
}
init(wrappedValue initialValue: T) {
self.storage = initialValue
}
var wrappedValue: T {
get { return storage! }
set { storage = newValue }
}
}
class UseWrapperWithDefaultInit {
@WrapperWithDefaultInit var name: String
}
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers25UseWrapperWithDefaultInitC5_name33_F728088E0028E14D18C6A10CF68512E8LLAA0defG0VySSGvpfi : $@convention(thin) () -> @owned WrapperWithDefaultInit<String>
// CHECK: function_ref @$s17property_wrappers22WrapperWithDefaultInitVACyxGycfC
// CHECK: return {{%.*}} : $WrapperWithDefaultInit<String>
// Property wrapper composition.
@propertyWrapper
struct WrapperA<Value> {
var wrappedValue: Value
}
@propertyWrapper
struct WrapperB<Value> {
var wrappedValue: Value
}
@propertyWrapper
struct WrapperC<Value> {
var wrappedValue: Value?
}
struct CompositionMembers {
// CompositionMembers.p1.getter
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers18CompositionMembersV2p1SiSgvg : $@convention(method) (@guaranteed CompositionMembers) -> Optional<Int>
// CHECK: bb0([[SELF:%.*]] : @guaranteed $CompositionMembers):
// CHECK: [[P1:%.*]] = struct_extract [[SELF]] : $CompositionMembers, #CompositionMembers._p1
// CHECK: [[P1_VALUE:%.*]] = struct_extract [[P1]] : $WrapperA<WrapperB<WrapperC<Int>>>, #WrapperA.wrappedValue
// CHECK: [[P1_VALUE2:%.*]] = struct_extract [[P1_VALUE]] : $WrapperB<WrapperC<Int>>, #WrapperB.wrappedValue
// CHECK: [[P1_VALUE3:%.*]] = struct_extract [[P1_VALUE2]] : $WrapperC<Int>, #WrapperC.wrappedValue
// CHECK: return [[P1_VALUE3]] : $Optional<Int>
@WrapperA @WrapperB @WrapperC var p1: Int?
@WrapperA @WrapperB @WrapperC var p2 = "Hello"
// variable initialization expression of CompositionMembers.$p2
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers18CompositionMembersV3_p233_{{.*}}8WrapperAVyAA0N1BVyAA0N1CVySSGGGvpfi : $@convention(thin) () -> @owned Optional<String> {
// CHECK: %0 = string_literal utf8 "Hello"
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers18CompositionMembersV2p12p2ACSiSg_SSSgtcfC : $@convention(method) (Optional<Int>, @owned Optional<String>, @thin CompositionMembers.Type) -> @owned CompositionMembers
// CHECK: s17property_wrappers18CompositionMembersV3_p233_{{.*}}8WrapperAVyAA0N1BVyAA0N1CVySSGGGvpfi
}
func testComposition() {
_ = CompositionMembers(p1: nil)
}
@propertyWrapper
struct WrapperWithAutoclosure<V> {
var wrappedValue: V
init(wrappedValue: @autoclosure @escaping () -> V) {
self.wrappedValue = wrappedValue()
}
}
struct CompositionWithAutoclosure {
@WrapperA @WrapperB @WrapperWithAutoclosure var p1: Int
@WrapperA @WrapperWithAutoclosure @WrapperB var p2: Int
@WrapperWithAutoclosure @WrapperA @WrapperB var p3: Int
// In the memberwise init, only p1 should be a closure - p2 and p3 should be just Int
// CompositionWithAutoclosure.init(p1:p2:p3:)
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers26CompositionWithAutoclosureV2p12p22p3ACSiyXA_S2itcfC : $@convention(method) (@owned @callee_guaranteed () -> Int, Int, Int, @thin CompositionWithAutoclosure.Type) -> CompositionWithAutoclosure
}
@propertyWrapper
struct WrapperWithAutoclosureAndExtraArgs<V> {
var wrappedValue: V
init(wrappedValue: @autoclosure @escaping () -> V, key: String) {
self.wrappedValue = wrappedValue()
}
}
struct UseAutoclosureWrapperWithExtraArgs {
@WrapperWithAutoclosureAndExtraArgs(key: "")
var value = 10
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers34UseAutoclosureWrapperWithExtraArgsV5valueSivpfP : $@convention(thin) (@owned @callee_guaranteed () -> Int) -> WrapperWithAutoclosureAndExtraArgs<Int>
}
// Observers with non-default mutatingness.
@propertyWrapper
struct NonMutatingSet<T> {
private var fixed: T
var wrappedValue: T {
get { fixed }
nonmutating set { }
}
init(wrappedValue initialValue: T) {
fixed = initialValue
}
}
@propertyWrapper
struct MutatingGet<T> {
private var fixed: T
var wrappedValue: T {
mutating get { fixed }
set { }
}
init(wrappedValue initialValue: T) {
fixed = initialValue
}
}
@propertyWrapper
struct MutatingGetNonMutatingSet<T> {
private var fixed: T
var wrappedValue: T {
mutating get { fixed }
nonmutating set { }
}
init(wrappedValue initialValue: T) {
fixed = initialValue
}
}
struct ObservingTest {
// ObservingTest.text.setter
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers13ObservingTestV4textSSvs : $@convention(method) (@owned String, @guaranteed ObservingTest) -> ()
// CHECK: function_ref @$s17property_wrappers14NonMutatingSetV12wrappedValuexvg
@NonMutatingSet var text: String = "" {
didSet { }
}
@NonMutatingSet var integer: Int = 17 {
willSet { }
}
@MutatingGet var text2: String = "" {
didSet { }
}
@MutatingGet var integer2: Int = 17 {
willSet { }
}
@MutatingGetNonMutatingSet var text3: String = "" {
didSet { }
}
@MutatingGetNonMutatingSet var integer3: Int = 17 {
willSet { }
}
}
struct NonObservingTest {
@NonMutatingSet var text: String = ""
@MutatingGet var text2: String = ""
@MutatingGetNonMutatingSet var text3: String = ""
}
class NonObservingClassTest {
@NonMutatingSet var text: String = ""
@MutatingGet var text2: String = ""
@MutatingGetNonMutatingSet var text3: String = ""
}
// Projected value with non-default mutatingness
struct Projection<T> {
var value: T
init(of value: T) {
self.value = value
}
}
@propertyWrapper
struct WrapperWithStorage<T> {
private var fixed: T
var wrappedValue: T {
get { fixed }
set { }
}
var projectedValue: Projection<T> {
get { Projection(of: fixed) }
set { }
}
init(wrappedValue: T) {
fixed = wrappedValue
}
}
@propertyWrapper
struct MutatingGetWithStorage<T> {
private var fixed: T
var wrappedValue: T {
mutating get { fixed }
set { }
}
var projectedValue: Projection<T> {
mutating get { Projection(of: fixed) }
set { }
}
init(wrappedValue: T) {
fixed = wrappedValue
}
}
@propertyWrapper
struct NonMutatingSetWithStorage<T> {
private var fixed: T
var wrappedValue: T {
get { fixed }
nonmutating set { }
}
var projectedValue: Projection<T> {
get { Projection(of: fixed) }
nonmutating set { }
}
init(wrappedValue: T) {
fixed = wrappedValue
}
}
@propertyWrapper
struct MutatingGetNonMutatingSetWithStorage<T> {
private var fixed: T
var wrappedValue: T {
mutating get { fixed }
nonmutating set { }
}
var projectedValue: Projection<T> {
mutating get { Projection(of: fixed) }
nonmutating set { }
}
init(wrappedValue: T) {
fixed = wrappedValue
}
}
struct ProjectedValueWithNonDefaultMutatingnessTest {
@WrapperWithStorage var n1: Int = 0
@NonMutatingSetWithStorage var n2: Int = 0
@MutatingGetWithStorage var n3: Int = 0
@MutatingGetNonMutatingSetWithStorage var n4: Int = 0
}
class ProjectedValueWithNonDefaultMutatingnessClassTest {
@WrapperWithStorage var n1: Int = 0
@NonMutatingSetWithStorage var n2: Int = 0
@MutatingGetWithStorage var n3: Int = 0
@MutatingGetNonMutatingSetWithStorage var n4: Int = 0
}
// Composition with non-default mutatingness
struct CompositionWithNonDefaultMutatingnessTest {
// Two wrappers, all combinations
@WrapperA @WrapperB var n1: Int
@WrapperA @MutatingGet var n2: Int
@WrapperA @NonMutatingSet var n3: Int
@WrapperA @MutatingGetNonMutatingSet var n4: Int
@MutatingGetWithStorage @WrapperB var n5: Int
@MutatingGetWithStorage @MutatingGet var n6: Int
@MutatingGetWithStorage @NonMutatingSet var n7: Int
@MutatingGetWithStorage @MutatingGetNonMutatingSet var n8: Int
@NonMutatingSetWithStorage @WrapperB var n9: Int
@NonMutatingSetWithStorage @MutatingGet var n10: Int
@NonMutatingSetWithStorage @NonMutatingSet var n11: Int
@NonMutatingSetWithStorage @MutatingGetNonMutatingSet var n12: Int
@MutatingGetNonMutatingSetWithStorage @WrapperB var n13: Int
@MutatingGetNonMutatingSetWithStorage @MutatingGet var n14: Int
@MutatingGetNonMutatingSetWithStorage @NonMutatingSet var n15: Int
@MutatingGetNonMutatingSetWithStorage @MutatingGetNonMutatingSet var n16: Int
// Three wrappers, non-standard mutability in the middle
@WrapperA @MutatingGet @WrapperB var m1: Int
@WrapperA @NonMutatingSet @WrapperB var m2: Int
@WrapperA @MutatingGetNonMutatingSet @WrapperB var m3: Int
}
// Tuple initial values.
struct WithTuples {
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers10WithTuplesVACycfC : $@convention(method) (@thin WithTuples.Type) -> WithTuples {
// CHECK: function_ref @$s17property_wrappers10WithTuplesV10_fractions33_F728088E0028E14D18C6A10CF68512E8LLAA07WrapperC12InitialValueVySd_S2dtGvpfi : $@convention(thin) () -> (Double, Double, Double)
// CHECK: function_ref @$s17property_wrappers10WithTuplesV9fractionsSd_S2dtvpfP : $@convention(thin) (Double, Double, Double) -> WrapperWithInitialValue<(Double, Double, Double)>
@WrapperWithInitialValue var fractions = (1.3, 0.7, 0.3)
static func getDefault() -> WithTuples {
return .init()
}
}
// Resilience with DI of wrapperValue assignments.
// rdar://problem/52467175
class TestResilientDI {
@MyPublished var data: Int? = nil
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers15TestResilientDIC11doSomethingyyF : $@convention(method) (@guaranteed TestResilientDI) -> () {
// CHECK: class_method %0 : $TestResilientDI, #TestResilientDI.data!setter : (TestResilientDI) -> (Int?) -> (), $@convention(method) (Optional<Int>, @guaranteed TestResilientDI) -> ()
func doSomething() {
self.data = Int()
}
}
@propertyWrapper
public struct PublicWrapper<T> {
public var wrappedValue: T
public init(value: T) {
wrappedValue = value
}
}
@propertyWrapper
public struct PublicWrapperWithStorageValue<T> {
public var wrappedValue: T
public init(wrappedValue: T) {
self.wrappedValue = wrappedValue
}
public var projectedValue: PublicWrapper<T> {
return PublicWrapper(value: wrappedValue)
}
}
public class Container {
public init() {
}
// The accessor cannot be serializable/transparent because it accesses an
// internal var.
// CHECK-LABEL: sil [ossa] @$s17property_wrappers9ContainerC10$dontCrashAA13PublicWrapperVySiGvg : $@convention(method) (@guaranteed Container) -> PublicWrapper<Int> {
// CHECK: bb0(%0 : @guaranteed $Container):
// CHECK: ref_element_addr %0 : $Container, #Container._dontCrash
@PublicWrapperWithStorageValue(wrappedValue: 0) public var dontCrash : Int {
willSet {
}
didSet {
}
}
}
// SR-11303 / rdar://problem/54311335 - crash due to wrong archetype used in generated SIL
public protocol TestProtocol {}
public class TestClass<T> {
@WrapperWithInitialValue var value: T
// CHECK-LABEL: sil [ossa] @$s17property_wrappers9TestClassC5valuexvpfP : $@convention(thin) <T> (@in T) -> @out WrapperWithInitialValue<T>
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers9TestClassC5value8protocolACyxGx_qd__tcAA0C8ProtocolRd__lufc
// CHECK: [[BACKING_INIT:%.*]] = function_ref @$s17property_wrappers9TestClassC5valuexvpfP : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out WrapperWithInitialValue<τ_0_0>
// CHECK-NEXT: partial_apply [callee_guaranteed] [[BACKING_INIT]]<T>()
init<U: TestProtocol>(value: T, protocol: U) {
self.value = value
}
}
// Composition with wrappedValue initializers that have default values.
@propertyWrapper
struct Outer<Value> {
var wrappedValue: Value
init(a: Int = 17, wrappedValue: Value, s: String = "hello") {
self.wrappedValue = wrappedValue
}
}
@propertyWrapper
struct Inner<Value> {
var wrappedValue: Value
init(wrappedValue: @autoclosure @escaping () -> Value, d: Double = 3.14159) {
self.wrappedValue = wrappedValue()
}
}
struct ComposedInit {
@Outer @Inner var value: Int
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers12ComposedInitV5valueSivpfP : $@convention(thin) (@owned @callee_guaranteed () -> Int) -> Outer<Inner<Int>> {
// CHECK: function_ref @$s17property_wrappers5InnerV12wrappedValue1dACyxGxyXA_SdtcfcfA0_
// CHECK: function_ref @$s17property_wrappers5InnerV12wrappedValue1dACyxGxyXA_SdtcfC
// CHECK: function_ref @$s17property_wrappers5OuterV1a12wrappedValue1sACyxGSi_xSStcfcfA_
// CHECK: function_ref @$s17property_wrappers5OuterV1a12wrappedValue1sACyxGSi_xSStcfcfA1_
// CHECK: function_ref @$s17property_wrappers5OuterV1a12wrappedValue1sACyxGSi_xSStcfC
init() {
self.value = 17
}
}
// rdar://problem/55982409 - crash due to improperly inferred 'final'
@propertyWrapper
public struct MyWrapper<T> {
public var wrappedValue: T
public var projectedValue: Self { self }
public init(wrappedValue: T) { self.wrappedValue = wrappedValue }
}
open class TestMyWrapper {
public init() {}
@MyWrapper open var useMyWrapper: Int? = nil
}
// rdar://problem/54352235 - crash due to reference to private backing var
extension UsesMyPublished {
// CHECK-LABEL: sil hidden [ossa] @$s21property_wrapper_defs15UsesMyPublishedC0A9_wrappersE6setFooyySiF : $@convention(method) (Int, @guaranteed UsesMyPublished) -> ()
// CHECK: class_method %1 : $UsesMyPublished, #UsesMyPublished.foo!setter
// CHECK-NOT: assign_by_wrapper
// CHECK: return
func setFoo(_ x: Int) {
foo = x
}
}
// SR-11603 - crash due to incorrect lvalue computation
@propertyWrapper
struct StructWrapper<T> {
var wrappedValue: T
}
@propertyWrapper
class ClassWrapper<T> {
var wrappedValue: T
init(wrappedValue: T) {
self.wrappedValue = wrappedValue
}
}
struct SR_11603 {
@StructWrapper @ClassWrapper var prop: Int
func foo() {
prop = 1234
}
}
// rdar://problem/57545381 - crash due to inconsistent decision about whether
// to initialize a wrapper property with an instance of the wrapper type vs.
// the wrapped type.
@propertyWrapper
class WrappedInt {
var intValue: Int?
var wrappedValue: Int? {
get {
return intValue
}
set {
intValue = newValue
}
}
init() { }
init(wrappedValue: Int?) {
self.wrappedValue = wrappedValue
}
}
struct WrappedIntContainer {
// CHECK: sil hidden [ossa] @$s17property_wrappers19WrappedIntContainerV3intAcA0cD0C_tcfcfA_ : $@convention(thin) () -> @owned WrappedInt
@WrappedInt var int: Int?
}
// rdar://problem/59117087 - crash due to incorrectly taking the "self access"
// path for a static property with a wrapper
struct HasStaticWrapper {
@StructWrapper static var staticWrapper: Int = 0
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers16HasStaticWrapperV08assignToD4SelfyyFZ : $@convention(method) (@thin HasStaticWrapper.Type) -> () {
static func assignToStaticSelf() {
// Make sure we call the setter instead of attempting a direct access,
// like we would if the property was not static:
// CHECK: function_ref @$s17property_wrappers16HasStaticWrapperV06staticE0SivsZ : $@convention(method) (Int, @thin HasStaticWrapper.Type) -> ()
staticWrapper = 1
}
}
@propertyWrapper
struct ObservedObject<ObjectType : AnyObject > {
var wrappedValue: ObjectType
init(defaulted: Int = 17, wrappedValue: ObjectType) {
self.wrappedValue = wrappedValue
}
}
// rdar://problem/60600911
// Ensure assign_by_wrapper is emitted for initialization
// of a property wrapper with a nonmutating set. Even though such setters
// take `self` by-value.
@propertyWrapper
struct NonMutatingSetterWrapper<Value> {
var value: Value
init(wrappedValue: Value) {
value = wrappedValue
}
var wrappedValue: Value {
get { value }
nonmutating set {
print(" .. nonmutatingSet \(newValue)")
}
}
}
struct NonMutatingWrapperTestStruct {
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers28NonMutatingWrapperTestStructV3valACSi_tcfC : $@convention(method) (Int, @thin NonMutatingWrapperTestStruct.Type) -> NonMutatingWrapperTestStruct {
// CHECK: %[[LOAD:[0-9]+]] = load [trivial] %[[SRC:[0-9]+]] : $*NonMutatingWrapperTestStruct
// CHECK-NEXT: %[[SET_PA:[0-9]+]] = partial_apply [callee_guaranteed] %[[PW_SETTER:[0-9]+]](%[[LOAD]]) : $@convention(method) (Int, NonMutatingWrapperTestStruct) -> ()
// CHECK-NEXT: assign_by_wrapper %[[SETVAL:[0-9]+]] : $Int to %[[ADDR:[0-9]+]] : $*NonMutatingSetterWrapper<Int>, init %[[INIT_PA:[0-9]+]] : $@callee_guaranteed (Int) -> NonMutatingSetterWrapper<Int>, set %[[SET_PA]] : $@callee_guaranteed (Int) -> ()
@NonMutatingSetterWrapper var SomeProp: Int
init(val: Int) {
SomeProp = val
}
}
// SR-12443: Crash on property with wrapper override that adds observer.
@propertyWrapper
struct BasicIntWrapper {
var wrappedValue: Int
}
class Someclass {
@BasicIntWrapper var property: Int = 0
}
class Somesubclass : Someclass {
override var property: Int {
// Make sure we don't interact with the property wrapper, we just delegate
// to the superclass' accessors.
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers12SomesubclassC0A0Sivs : $@convention(method) (Int, @guaranteed Somesubclass) -> ()
// CHECK: bb0([[NEW:%.+]] : $Int, {{%.+}} : @guaranteed $Somesubclass):
// CHECK: [[SETTER:%.+]] = function_ref @$s17property_wrappers9SomeclassC0A0Sivs : $@convention(method) (Int, @guaranteed Someclass) -> ()
// CHECK: apply [[SETTER]]([[NEW]], {{%.+}}) : $@convention(method) (Int, @guaranteed Someclass) -> ()
// CHECK: [[DIDSET:%.+]] = function_ref @$s17property_wrappers12SomesubclassC0A0SivW : $@convention(method) (@guaranteed Somesubclass) -> ()
// CHECK: apply [[DIDSET]]({{%.+}}) : $@convention(method) (@guaranteed Somesubclass) -> ()
didSet {
print("Subclass")
}
}
}
// rdar://problem/58986940 - composition of wrappers with autoclosure
@propertyWrapper
struct Once<Value> {
enum Storage {
case initialValue(() -> Value)
case value(Value)
}
var storage: Storage
init(defaulted: Int = 0, wrappedValue value: @escaping @autoclosure () -> Value) {
storage = .initialValue(value)
}
var wrappedValue: Value { fatalError() }
}
class Model {}
struct TestAutoclosureComposition {
@Once @ObservedObject var model = Model()
}
// CHECK-LABEL: sil_vtable ClassUsingWrapper {
// CHECK-NEXT: #ClassUsingWrapper.x!getter: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter
// CHECK-NEXT: #ClassUsingWrapper.x!setter: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter
// CHECK-NEXT: #ClassUsingWrapper.x!modify: (ClassUsingWrapper) -> () -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivM // ClassUsingWrapper.x.modify
// CHECK-NEXT: #ClassUsingWrapper.init!allocator: (ClassUsingWrapper.Type) -> () -> ClassUsingWrapper : @$s17property_wrappers17ClassUsingWrapperCACycfC
// CHECK-NEXT: #ClassUsingWrapper.deinit!deallocator: @$s17property_wrappers17ClassUsingWrapperCfD
// CHECK-NEXT: }
// CHECK-LABEL: sil_vtable [serialized] TestMyWrapper
// CHECK: #TestMyWrapper.$useMyWrapper!getter