This is in regard to a lazy var.
What is the reason behind this restriction?
It would be helpful if you posted the code that's producing that error.
This is very much a strawman example, but...
struct S {
var i = 1
lazy var j = 1
}
var s = S()
let si = \S.i
print(s[keyPath: si])
let sj = \S.j // this is the line with the error
print(s[keyPath: sj])
lazy1.swift:9:13: error: key path cannot refer to 'j', which has a mutating getter
First, lazy vars generate a mutating getter on structs:
struct S {
var i = 1
lazy var j = 1
}
let s = S()
s.j // Cannot use mutating getter on immutable value: 's' is a 'let' constant
Second, the getter of the [keyPath:]
subscript is not mutating.
Therefore, the [keyPath:]
subscript can not accept a key path to a mutating getter.
Therefore, the key path implementors did not bother implementing key paths to mutable getters. They would have been a dead-end anyway.
A possible workaround is to use a class, or a a private inner storage class:
class S {
lazy var j: Int = 1
}
let s = S()
let sj = \S.j // no error
print(s[keyPath: sj])
// ---------------------------------------------
struct S {
private class Storage {
lazy var j = 1
}
private let storage = Storage()
var j: Int {
get { return storage.j }
set { storage.j = newValue }
}
}
let s = S()
let sj = \S.j // no error
print(s[keyPath: sj])
Why is it a dead end? Shouldn't Swift be fixed/amended with a key path subscript
that takes a mutating
getter (or generalized to take either kind of getter)?
Supporting mutating getters would require a combinatorial explosion of key-path types for very little gain. We currently have five key path types: AnyKeyPath
(immutable, fully type-erased), PartialKeyPath
(immutable, type-erased value), KeyPath
(immutable), WritableKeyPath
(mutable, mutating setter), and ReferenceWritableKeyPath
(mutable, non-mutating setter). To support mutating getters we would need to double this (with the possible exception of AnyKeyPath
). It's a corner case that clearly doesn't justify the increase in complexity.
We had a similar combinatorial explosion when exploring throwing writable key paths in Extract Payload for enum cases having associated value - #233 by sveinhal. We have difficulties extending the key path model.