The Problem
Right now it's very easy to accidentally introduce bugs into Decodable
structures. For example, given the following type:
struct Settings: Decodable {
let theme: String
let updated: Date
}
We may modify it to make mocking or instantiating it easier by inlining the property value in the let
.
struct Settings: Decodable {
let theme: String = "light"
let updated: Date
}
This assumption is wrong, though, and now theme
will return "light"
no matter what because initializers can't set over a let
s initial value. In my mind, this structure is no longer decodable by default because it contains a property that cannot be decoded.
Solutions
I think whenever a let
has a default, the compiler should stop and make the developer state their intentions more explicitly, e.g., the above may provide the following error:
implementation of 'Decodable' cannot be automatically synthesized for types with assigned let properties
There are two potential solutions with fix-its:
1. Require explicit coding keys
Do you want to add coding key stubs?
By stubbing out coding keys that omit fields with defaults, the intention becomes explicit:
struct Settings: Decodable {
let theme: String = "light"
let updated: Date
enum CodingKeys: String, CodingKey {
case updated
}
}
2. Require an explicit initializer
Do you want to add protocol stubs?
By providing an explicit init(from:)
implementation, the intention becomes even more so:
struct Settings: Decodable {
let theme: String = "light"
let updated: Date
init(from decoder: Decoder) {
<#code#>
}
}
3. Suggest loosening the let
requirement
Change 'let' to 'var' to make it mutable
This would make the decoding work again.
How does it play with Encodable?
One issue to consider is how this plays with types that are also Encodable
. I don't foresee there to be problems here given the suggested solutions above, but I'm probably missing something.
I've introduced regressions into my code base again and again by accident with the current behavior. It all makes sense but it's easy to forget without the compiler assistance you get when defining an initializer and attempting to assign over a let
property that already has a value.
I think introducing more requirements and diagnostics here will help keep some of us in better check