最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why is there a "Type of expression is ambiguous without a type annotation." error when using a ternary operato

programmeradmin4浏览0评论

I'm reading the official Swift Programming Language Documentation and writing the code snippet examples in Playgrounds. Currently, I'm on Function Types as Return Types which seemed pretty straightforward. I'm using Xcode 16.2

The following code snippet copied from the Function Types as Return Types section 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 following error is seen for the ternary operator for stepBackward (and stepForward): "Type of expression is ambiguous without a type annotation."

This is a clean Playgrounds workspace with the default Hello World removed to verify the behavior.

I'm able to fix this by writing explicit type annotation as follows:

let forwardFunc: (Int) -> Int = stepForward
let backwardFunc: (Int) -> Int = stepBackward

@MainActor func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? backwardFunc : forwardFunc
}

This is to my understanding a good practice, but the documentation in the Functions section does not make clear this would be required.

Did something change in Swift recently that would make the documentation out of date? Is writing an explicit type annotation in these cases required now? I would like to understand why in this context the type annotation is now required, in particular with this ternary operator using inferred function types.

I'm reading the official Swift Programming Language Documentation and writing the code snippet examples in Playgrounds. Currently, I'm on Function Types as Return Types which seemed pretty straightforward. I'm using Xcode 16.2

The following code snippet copied from the Function Types as Return Types section 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 following error is seen for the ternary operator for stepBackward (and stepForward): "Type of expression is ambiguous without a type annotation."

This is a clean Playgrounds workspace with the default Hello World removed to verify the behavior.

I'm able to fix this by writing explicit type annotation as follows:

let forwardFunc: (Int) -> Int = stepForward
let backwardFunc: (Int) -> Int = stepBackward

@MainActor func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? backwardFunc : forwardFunc
}

This is to my understanding a good practice, but the documentation in the Functions section does not make clear this would be required.

Did something change in Swift recently that would make the documentation out of date? Is writing an explicit type annotation in these cases required now? I would like to understand why in this context the type annotation is now required, in particular with this ternary operator using inferred function types.

Share Improve this question edited Jan 20 at 2:30 schifano asked Jan 20 at 0:20 schifanoschifano 3264 silver badges6 bronze badges 9
  • 1 Splitting return backward ? stepBackward : stepForward into two lines also solves the issue: let res = backward ? stepBackward : stepForward and return res. – HangarRash Commented Jan 20 at 1:23
  • 1 This is a pretty bizarre case of this issue. The types here are an exact match, idk why the type system would struggle to check this. Could you please start a topic abotu this on the Swift Forums? That might attract some interest from the Swift devs, who can explain what's going on – Alexander Commented Jan 20 at 1:46
  • Thank you for the suggestion. I have posted the question on the Swift Forums here: forums.swift.org/t/… – schifano Commented Jan 20 at 2:26
  • 1 @schifano No, none of my tests or comments have been based on a Playground. I've done everything in a full Xcode project. BTW - if you are replying to a specific person's comment, address the comment directly to them by entering @ followed by their username (as I did at the start of this comment). – HangarRash Commented Jan 20 at 4:18
  • 1 @schifano I'm using Xcode 18.2 under macOS 15.2. It's a macOS command line app setup to use Swift 6. With that setup I easily replicate your issue. Switching to Swift 5 in the same project makes the issue go away. – HangarRash Commented Jan 20 at 5:04
 |  Show 4 more comments

1 Answer 1

Reset to default 2

The following answer summarizes some of the discussion found on the Swift Forum.

This issue arose with Swift 6 and is caused by the fact that the sendForward and sendBackward functions are implicitly marked as @Sendable.

The issue is resolved by updating the code from:

@MainActor func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? backwardFunc : forwardFunc
}

to:

@MainActor func chooseStepFunction(backward: Bool) -> @Sendable (Int) -> Int {
    return backward ? backwardFunc : forwardFunc
}

Note the addition of @Sendable for the function's return type.

Another workaround is to split the return line:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    let sendableFunc = backward ? stepBackward : stepForward
    return sendableFunc // casts `@Sendable (Int)->Int` to `(Int) -> Int`
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论