Hi everyone,
I'd like to propose a way to exclude individual stored properties from a struct's synthesized memberwise initializer. I'll use @Init(.ignore) as a placeholder spelling.
Consider a session that exposes its retry count for reading, but updates it through a method:
struct Session {
var userID: String
private(set) var retryCount = 0
mutating func recordRetry() {
retryCount += 1
}
}
For this type, I want new sessions to start with zero retries. However, the memberwise initializer allows this:
Session(userID: "user1", retryCount: 100)
That's consistent with the current rules: private(set) restricts mutation, not whether a property participates in memberwise initialization. SE-0502 also deliberately leaves setter visibility out of that decision.
I can get the API I want by writing an initializer:
init(userID: String) {
self.userID = userID
}
That's easy here. With more caller-supplied properties, though, excluding one piece of internal state means repeating all the other parameters and assignments.
I'd like to be able to write:
struct Session {
var userID: String
@Init(.ignore)
private(set) var retryCount = 0
mutating func recordRetry() {
retryCount += 1
}
}
// Synthesized: init(userID: String)
I propose that an excluded property use its declared initial value during synthesized initialization. The attribute would affect only memberwise synthesis; it would not change access control or the rules for manually written initializers.
For this pitch, I’d limit support to ordinary stored instance var properties in structs with explicit initial values. Property wrappers and lazy properties would be outside that scope. Stored let properties with declaration-site initial values are already excluded from memberwise initialization.
Exclusion would be opt-in. A type that supports restoring a saved session, for example, might reasonably allow callers to supply an initial retry count.
SE-0502 considered an exclusion attribute, but left it for future exploration as part of broader memberwise-initializer customization. This pitch takes a narrower approach: allowing individual properties to opt out while retaining synthesis for the rest.
I’d like to discuss whether that smaller feature stands on its own, and hear about cases where it would help compared with writing an initializer or using a macro.