mozeryansky
(Michael Ozeryansky)
1
In the proposal, now in Swift 5.2, we know keypath expressions are converted to functions. But these functions don't override equivalent functions. However, I can normally pass a non-optional value where an optional value is expected.
Should Swift allow these kind of function overrides like normal functions?
struct S {
let val: String
}
class C {
var block: ((S) -> String?)?
}
let c = C()
c.block = { (s: S) -> String in
return s.val
}
// Compiles perfectly fine
c.block = { (s: S) -> String? in
return s.val
}
let f: (S) -> String = \S.val
let f2: (S) -> String? = \S.val // Error: Key path value type 'String' cannot be converted to contextual type 'String?'
Where I ran into this was trying to use keypaths in allSatisfy which expects a function that throws.
class C {
var block: ((S) throws -> String)?
}
let c = C()
c.block = { (s: S) throws -> String in
return s.val
}
c.block = { (s: S) -> String in
return s.val
}
[true, true].allSatisfy({ $0 }) // Compiles fine
[true, true].allSatisfy(\.self) // Error: Cannot convert value of type 'WritableKeyPath<_, _>' to expected argument type '(Bool) throws -> Bool'
Edit:
I just realized the .allSatisfy(\.self) example doesn't work, but if I refer to a property it does work just fine. I think it's an error with WritableKeyPath.
2 Likes