Description
Description
Type checker appears to fail to cast an implicit @Sendable
inferred function type to the expected return type in specific circumstances such as when it is directly returned. There may be other cases this is happening but the issue results in a compile time error that is otherwise unexpected as this behavior appears to work fine prior to Swift 6.
Context
There is an example in the Swift Programming Language Documentation under the Function Types as Return Types section which includes a code snippet for returning an inferred function type. The example from the documentation is as follows:
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
}
However, the line return backward ? stepBackward : stepForward
results in a compile time error that reads: "Type of expression is ambiguous without a type annotation."
To get the code to compile with the return
line as-is, it requires explicitly adding the otherwise implicit @Sendable
annotation to the return type as follows:
func chooseStepFunction2(backward: Bool) -> @Sendable (Int) -> Int {
return backward ? stepForward : stepBackward
}
Workarounds
There are several workarounds that do work as found by several community members which I will summarize here:
- Splitting the code into two lines by instead returning a variable
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
let sendableFunc = backward ? stepBackward : stepForward
return sendableFunc // casts `@Sendable (Int)->Int` to `(Int) -> Int`
}
- Casting to
@Sendable
in the function body
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
(backward ? stepBackward : stepForward) as @Sendable (_) -> _
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
if backward { stepBackward as @Sendable (_) -> _ }
else { stepForward as (_) -> _ }
}
- Using internally scoped nested functions
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
Reproduction
- Install Xcode 16.2 (or simply make Swift 6 available).
- Open a new Playground.
- Remove "Hello World" code.
- Add the documentation code snippet (below).
- Compile.
- Observe type annotation error
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward // Error: Type of expression is ambiguous without a type annotation.
}
Expected behavior
The Swift Programming Language Documentation Function Types as Return Types code should compile without error and correctly infer the return type when it is an inferred function type.
Environment
- swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
- Xcode 16.2
- Apple M4 MacBook Pro
- macOS Sequoia Version 15.1
- First reproduced using Playgrounds
Note: Please see the forum post links where other community members tried on different environments, setups, Xcode projects and packages (not just Playgrounds).
Additional information
Please read these posts for detailed background. I posted these to get help from the community to understand what was going on and it has valuable discussion and context. Thank you to all who contributed and encouraged me to submit this issue!