-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
Previous ID | SR-13990 |
Radar | rdar://problem/72864707 |
Original Reporter | benpious (JIRA User) |
Type | Bug |
Environment
Version 12.2 (12B45b), Swift 5.3
Additional Detail from JIRA
Votes | 0 |
Component/s | Compiler |
Labels | Bug |
Assignee | None |
Priority | Medium |
md5: c1e7328831e888c4bb625eef730911b5
Issue Description:
If I write a property wrapper like the following:
@dynamicMemberLookup
struct Passthrough<T> {
var backing: T
subscript<U>(dynamicMember member: WritableKeyPath<T, U>) -> U {
get {
backing[keyPath: member]
}
set {
backing[keyPath: member] = newValue
}
}
}
Then use it in this manner:
struct S {
let a: Int = 7
}
let l = Passthrough<S>(backing: S())
print(l.a)
It's reasonable (imo) to expect it to compile, since the `get` doesn't actually modify the struct. However, it fails with the error "Cannot assign to property: 'a' is a 'let' constant," which is confusing because no mutation is taking place.
It seems that the true error is that it is impossible to construct a `WriteableKeyPath` in the first place for a `let`, which I discovered while trying to write this bug report.
The only solution I've found to this issue so far is to write out the dynamicMemberLookup subscript again using `KeyPath` instead of `WriteableKeyPath`:
subscript<U>(dynamicMember member: KeyPath<T, U>) -> U {
backing[keyPath: member]
}
I think at minimum the correct approach to solve this issue should be documented, and the compiler should detect this case and suggest this solution.
Ideally, imo the compiler would, whenever possible, synthesize a version of the subscript getter that used KeyPath instead of WriteableKeyPath, or otherwise abstract this away.