-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Diagnostics] Emit a warning when an immutable decodable property has an initial value #30218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
How would that work though? If the user really wants to leave the property as transient, the only other |
I think it’s going to be rare in practice - most of the examples I’ve across on S/O, Twitter, etc is when someone just assigned it directly whereas they meant to pass it via the initializer. Explicitly specifying the properties via CodingKeys is the alternative to this - I felt it was a bit too much for the common case but I’m totally happy to suggest that instead in the warning (or as a note in addition to making the property mutable). |
There has to be both a "did you mean" fixit and a silencing one (which does not change behaviour or semantics). But I agree the common case should go first. There is one case that definitely should be warned about though: when the intention to decode such a property is explicit: struct Foo: Decodable {
private enum CodingKeys: CodingKey {
case foo1
}
let foo1 = 0
} |
The main problem here is that explicitly implementing But yeah, for those rare cases where you just want to ignore the property, explicitly specifying which properties to decode in a CodingKeys enum seems reasonable to me (my only concern was that suggesting it as the primary option might be overkill for the common case). What I propose is that we suggest the initialiser approach as the first choice, coding keys as second choice and making the property mutable as the third choice. Your example where you’ve explicitly specified the property in the CodingKeys enum but made it a let with initial value is a good example which should also be diagnosed as a warning. |
… an initial value
Ping. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Left a small comment about diagnose
inline.
@swift-ci please smoke test |
@swift-ci please smoke test |
This PR fixes the warnings mentioned in launchdarkly#220, which were added to the Swift compiler [somewhat recently](swiftlang/swift#30218). The cause of the warning is setting default values for a Decodable objects properties. This causes subtle bugs where a given property may not be correctly decoded. The solution proposed here is one of a few, simply settings the variable to a `var` while making its setter private. This retains the original behavior for those consuming the code, while also allowing Decodable to work properly.
I know that it has been a while since this has been merged but, have there been any considerations to have a way to disable this warning? |
Now that SwiftUI/Combine is in full swing, there are going to be more people using the Having to create the If this change is here to stay, then perhaps a new property wrapper could help with silencing the warning. Alternatively, fix |
I agree with @BeauNouvelle. struct Model: Codable, Identifiable {
public let id = UUID() // warning presented
public let name: String
} Given that Xcode provides the struct Model: Codable, Identifiable {
public var id = UUID() // warning silenced
public let name: String
} It is poor practise to have a mutating identifier especially when SwiftUI relies heavily upon it. Until this has been resolved (my hope would be that this merge is reverted), explicitly defining CodingKeys should not be recommended (in my opinion) as now a developer needs to remember to add/remove/modify/match the properties in their model (murphy's law states that a developer will eventually fail to maintain the coding keys). public struct IdentifierWrapper<T>: Identifiable {
public let id = UUID()
public let value: T
} let wrapper = IdentifierWrapper(value: Model(name: "ptrkstr")) |
When a decodable immutable property has an initial value, it will not be decoded and get skipped. This is a common source of confusion among users (example here and here), so emit a specialised warning for it.
To silence the warning, the user can do one of the following things:
CodingKeys
enum without the key in it to make it explicit that it's not meant to be decoded.let
tovar
)This won't trigger in some cases when the type is
Codable
because removing the key will break encoding which is most likely not what the user would expect.Also, if the key has been explicitly specified and the type is just
Decodable
, then this warning will be triggered because explicitly declaring a key in theCodingKeys
enum means it's meant to be decoded.This strategy was mentioned here: https://forums.swift.org/t/revisit-synthesized-init-from-decoder-for-structs-with-default-property-values/12296/2
Resolves SR-11996
Resolves rdar://problem/58455438