Property Wrapper initialization question

I've been digging into Property Wrapper initialization trying to understand what's happening under the hood. I ran across this initialization ordering issue that's confusing me. This is kinda a follow up to a question I asked earlier.

@propertyWrapper
struct Untagged<Value> {
    var wrappedValue: Value
}

@propertyWrapper
struct Tagged<Value> {
    init(name: String) {}
    var wrappedValue: Value { get { fatalError() } set {} }
}

// NOT OK
struct Foo1 {
    @Tagged(name: "A") var a: Int
    @Untagged var b: Int

    init(a: Int, b: Int) {
        self.a = a // 'self' used before all stored properties are initialized
        self.b = b
    }
}

// OK
struct Foo2 {
    @Tagged(name: "A") var a: Int
    @Untagged var b: Int
    
    init(a: Int, b: Int) {
        self._a.wrappedValue = a
        self._b = Untagged(wrappedValue: b)
    }
}

// OK
struct Foo3 {
    @Tagged(name: "A") var a: Int
    @Untagged var b: Int
    
    init(a: Int, b: Int) {
        self.b = b
        self.a = a
    }
}

// OK
struct Foo4 {
    @Tagged(name: "A") var a: Int
    @Untagged var b: Int
    
    init(a: Int, b: Int) {
        self._b = Untagged(wrappedValue: b)
        self._a.wrappedValue = a
    }
}

Why isn't Foo1.init equivalent to Foo2.init? Both access _a first, which should be an initialized Tagged(name: "A").

The error will disappear if you add init(wrappedValue: Value) {} to Tagged. Please read this thread for more information:

Here is a partly related discussion:

while the (optional) init(wrappedValue:) enables initialization of the storage from a value of the property's type

Wow, there's so much compiler magic around the existence certain property wrapper inits.

It seems a little unfortunate that it's required for this example, since you might want to require a name value and don't have a good fallback. It'd be nice if somehow init(wrapperValue:name) could satisfy that requirement.

@DevAndArtist thanks for the quick response!

Terms of Service

Privacy Policy

Cookie Policy