So I got a notice that SE-0249 finally got merged into master.
After the proposal was accepted there seem to have been some sort of alignment of the precise semantics.
Now in the past I discovered that key-paths have a requirement that every key-path literal parameter has to be hashable in order to form a valid key-path value. I opened up a thread and got an answer from Joe Groff that with SE-0249 closures that are formed using a key-path literal do not have to suffer from the same requirements as normal key-path values.
As for right now we cannot form key-paths over methods, but we eventually will be able to do so. Combined with SE-0249 I think it's fair to say that this hypothetical example is very tempting because it seems to be a very convenient way to get rid of some boilerplate code.
array.map(\.someFunction(someObject))
Now the newly added section in the proposal says the following:
The compiler may generate any code that has the same semantics as this example; it might not even use a key path at all.
That last part is important because it lets us assume that the key-path literal to form a closure might indeed no require parameter hashability.
However this seems to be not the case with the current implementation of the feature. Disclaimer: I do understand that one reason for that might be that the core seek for implicit transformation from key-paths into closures in some future.
Right now it's fairly rare that we use objects as subscript parameters, but this is a common thing with methods. And usually not every class conforms to Hashable
protocol, which means that the above example won't compile with the current restrictions on the SE-0249 implementation.
The closest example we can write today with the toolchain from master might look like this:
class Object {}
let object = Object()
struct Value {
subscript(_ object: Object) -> Object {
object
}
}
var array = [Value()]
// error: Subscript index of type 'Object' in a key path must be Hashable
let result: [Object] = array.map(\.[object])
This contradicts with the answer I received in the linked thread and with the quote from the proposal that explicitly says that the compiler might not use a key-path at all to form a closure from a key-path literal.
It means that the above closure formed using \.[object]
literal probably decomposes into this code:
let closure: (Value) -> Object = { keyPath in
{ value in
value[keyPath: keyPath]
}
}(\Value.[object])
That of course won't compile because it uses a real key-path value which cannot drop the hashability requirement.
Based on the answer from the linked thread and the quote from the proposal however, I would have expected that the compiler won't use an actual key-path to form that particular closure. What I would have expected might look like this:
let closure: (Value) -> Object = { value in
value[object]
}
Long story short, I invite everyone to discuss this issue in this thread and to clarify where we're heading right now.
P.S.: If my English failed somewhere, feel free to correct me. I'll be happy to edit.