Skip to content

Swift 6 fails to cast inferred function types as return types from implicit @Sendable on return statement #78769

Open
@schifano

Description

@schifano

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."

Screenshot of the error in Playgrounds

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:

  1. 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`
}
  1. 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 (_) -> _ }
}
  1. 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!

Metadata

Metadata

Assignees

Labels

SendableArea → standard library: The Sendable protocolbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfconcurrencyFeature: umbrella label for concurrency language featuresfunction typesFeature → types: function typesimplicit conversionsFeature: implicit conversionsswift 6.2type checkerArea → compiler: Semantic analysistypesFeature: typesunexpected errorBug: Unexpected error

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions