Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
schifano opened this issue Jan 21, 2025 · 0 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels

Comments

@schifano
Copy link

schifano commented Jan 21, 2025

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!

@schifano schifano added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

1 participant