Skip to content

value semantics of init with defaulted private let fields does not make sense #88619

@tayloraswift

Description

@tayloraswift

Description

reproduced from https://forums.swift.org/t/value-semantics-of-init-with-defaulted-private-let-fields-does-not-make-sense/86193


one popular way to manually insert padding into a Swift struct is by doing the following

struct S {
    let x: Int
    private let padding: Int = 0

    init(x: Int) {
        self.x = x
    }
}

now it’s not quite right - the struct isn’t @frozen and so the layout isn’t correctly specified, so this code doesn’t formally do what the library author probably thinks it does. nevertheless, it’s a very popular pattern, it is used, for example, by Google flatc.

if you’re handed an API like this, you run into some really inconsistent compiler policies surrounding definite initialization. you can’t, for example, do this:

extension S {
    init() {
        self = .init(x: 0)
        // Immutable value 'self.padding' may only be initialized once
        // Initial value already provided in 'let' declaration
        // Change 'let' to 'var' to make it mutable
    }
}

this is a rather useless guardrail, because self = new is something that should always be semantically valid for value types, regardless of field mutability, and it’s trivial (but awkward) to circumvent the restriction:

protocol P {
    static func create(x: Int) -> Self
}
extension P {
    init() {
        self = .create(x: 0)
    }
}

extension S: P {
    static func create(x: Int) -> Self {
        .init(x: 0)
    }
}

let s: S = .init()

Reproduction

see above

Expected behavior

self = .init(x: 0) should compile

Environment

swift --version
Swift version 6.3.1 (swift-6.3.1-RELEASE)
Target: x86_64-unknown-linux-gnu

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage neededThis issue needs more specific labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions