When compiling my project with Swift 5 I found that the compiler now complains about ambiguity where it previously didn't. Is this a bug or intentional? (/cc @jrose)
import Cocoa
class MsPiggy: NSObject {
let k = Kermit()
func party() {
// Here I get `Type of expression is ambiguous without more context`
// but only with the Swift 5 compiler. In Swift 4.2 mode everything is fine.
k.a(\.color) { v in }
}
}
class Kermit: NSObject {
// If I remove the `private(set)` here, even Swift 5 is happily compiling this
@objc dynamic private(set) var color: NSColor!
}
extension NSObjectProtocol where Self: NSObject {
func a<Value>(_ keyPath: ReferenceWritableKeyPath<Self, Value>, onChange: @escaping (Value) -> ()) {}
func a<Value>(_ keyPath: ReferenceWritableKeyPath<Self, Value>, onChange: @escaping (Self, Value) -> ()) {}
}
This sounds like a case where we've regressed on deciding whether something is a tuple splat or not. @xedin would know better than me if it's a known issue.
Ah, with the private(set) your call is invalid, so maybe it's just being diagnosed incorrectly? This might have been a bug in 4.2 that got fixed (that it was allowed originally), but now you've uncovered a separate bug with diagnostics.
Why was it invalid? I was only reading from the keypath, so the setter shouldn't matter right?
Mhm, the objc runtime would be able to write regardless of the private(set) no?
I was using those methods in KVO. (Sorry the code is just a strawman handpuppet example)
This looks like a bad error message for a real type error. From MsPiggy.party, Kermit.color is only gettable, so \.color results in a read-only KeyPath. You can't pass that statically as a ReferenceWritableKeyPath. If you make Kermit.color fileprivate, that should address the issue. In earlier versions of Swift, we didn't correctly diagnose this so you should get compatibility warnings, but in Swift 5 mode it is strictly enforced as an error.
Yeah in my real code those are in viewmodels and model objects so not in the same file or even framework. KVO always worked so far, but I get the argument about the keypath requiring writability.
You shouldn't need a ReferenceWritableKeyPath for KVO, since there are observable properties that are read-only and that only change value because of implementation-side modifications or because of indirect mutations of dependent state.
Thanks, that makes perfect sense of course and now I feel stupid . It's kinda obvious even.
Should I file a bug about the misleading error message? If I understand correctly there is no ambiguity, but rather both methods definitely don't match because the key-path definitely doesn't fit.