In Swift, we can normally pass a function reference as an argument to a function that expects a closure. However, in many cases that fails or produces warnings. Here are some:
Mutating function references:
let items = [1, 2, 3]
var destination: [Int] = []
// Error: Cannot reference 'mutating' method as function value
items.forEach(destination.append)
// ok!
items.forEach { destination.append($0) }
Non-Sendable functions:
var body: some View {
Text("Hello, World!")
// Warning: Converting non-sendable function value to '@Sendable () async -> Void' may introduce data races
.task(doTask)
// ok!
.task { doTask() }
}
Discardable return value is not void:
@discardableResult
func log<T>(_ value: T) -> T {
print(value)
return value
}
// Error: Cannot convert value of type '(Void) -> Void' to expected argument type '(Int) throws -> Void'
items.forEach(log)
// ok!
items.forEach { log($0) }
Since the trivial solution of wrapping these in the most elementary closure seems to work — should we make the compiler generate the necessary thunks to do this automatically? If not, why?
I'm not sure these are problematic enough to warrant a pitch to change the lanhuage, or even needs fixing. But I'm interested in learning about the quirks of how these (and possible similar issues) surface in the language, and possible pitfalls of "fixing" them.
In the non-sendable example, I'm not even sure what is going on and why the explicit closure gets rid of the warning.