bbrk24
1
I was looking into how keypaths are compiled as functions, when I noticed something that caught me off-guard. In the following code:
public protocol P {}
public func firstVersion(_ args: [[P]]) -> [P] {
let closure: ([P]) -> [P] = { $0 }
return args.flatMap(closure)
}
public func secondVersion(_ args: [[P]]) -> [P] {
let closure: ([P]) -> [P] = \.self
return args.flatMap(closure)
}
there is a substantial difference in firstVersion and secondVersion at some optimization levels. With -Osize and -Ounchecked, the compiler outputs a reasonably short implementation for firstVersion, and then secondVersion just calls firstVersion. However, with plain -O, they get drastically different implementations, with firstVersion being over twice as long as secondVersion.
Godbolt link
Why are they different? Is \.self meant to perform differently than { $0 }?
4 Likes