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

[SR-1570] 'Generic parameter 'Result' could not be inferred' compiler error for wrapper functions like autoreleasepool that return the result of their closure argument. #44179

Open
groue opened this issue May 20, 2016 · 6 comments

Comments

@groue
Copy link

@groue groue commented May 20, 2016

Previous ID SR-1570
Radar None
Original Reporter @groue
Type Bug
Environment

Swift 2.2 in Xcode 7.3.1 (7D1014), and swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, DiagnosticsQoI
Assignee None
Priority Medium

md5: a887c5d29245fd7788e933e40c2bc88a

is duplicated by:

  • SR-1648 Fail to infer type on closure computed property

relates to:

  • SR-893 Compiler fails to infer return type of the transform closure in a map call

Issue Description:

Hello,

It's a very common pattern to write functions that take a closure and return this closure's result. An example is autoreleasepool, since SE-0061.

The most simple one is:

func f<Result>(_ closure:() -> Result) -> Result {
    return closure()
}

The issue is that Swift compiler (in both versions 2.2 and swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a) outputs an error `Generic parameter 'Result' could not be inferred` whenever the closure contains a line of code followed with a return statement:

do {
    // Variant 1
    // Generic parameter 'Result' could not be inferred
    let x = f {
        print("foo")
        return 1
    }
}

do {
    // Variant 2
    // Generic parameter 'Result' could not be inferred
    f {
        print("foo")
        return 1
    }
}

The workaround is to add explicit type declaration:

do {
    // Workaround 1 for variant 1
    let x = f { _ -> Int in
        print("foo")
        return 1
    }
}

do {
    // Workaround 2 for variant 1
    let x: Int = f {
        print("foo")
        return 1
    }
}

do {
    // Workaround for variant 2
    f { _ -> Int in
        print("foo")
        return 1
    }
}

The problem is that this workaround is not easy to find for regular users: they complain and report issues.

As for the variant 2 itself, which does not use the returned value, it can be the sign of some unfinished code, or of some actual issue: we need an "unused result" warning, not an error.

@belkadan
Copy link
Contributor

@belkadan belkadan commented May 20, 2016

This is correct behavior: Swift does not infer parameter or return types from the bodies of multi-statement closures. But the diagnostic could be a lot better.

@groue
Copy link
Author

@groue groue commented May 20, 2016

@belkadan OK, Swift does not infer parameter or return types from the bodies of multi-statement closures. This is the current behavior.

But is it the correct behavior? Let's say that this the topic of the issue, if you prefer.

The user who initially complained (groue/GRDB.swift#53 writes code like:

f {
    let x = 1
    return x
}

Is it normal to punish him for not writing a single-line closure?

I think not.

@belkadan
Copy link
Contributor

@belkadan belkadan commented May 20, 2016

It's a technical issue as much as a design issue. I talked a bit about it on swift-evolution back in December; see the last section in https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002583.html.

@groue
Copy link
Author

@groue groue commented May 20, 2016

But the diagnostic could be a lot better.

Should the behavior remain, a fix-it would indeed be very much welcome.

Please take in account that the burden of this behavior weights on the shoulders of library developers: users get stuck, find no way to fix their trouble, and eventually report an issue. Answering issues takes time.

@groue
Copy link
Author

@groue groue commented May 20, 2016

Thanks for the link to the rationale, Jordan

@mattneub
Copy link

@mattneub mattneub commented Feb 27, 2017

Note to future readers: Observe that this issue does not arise if there's something else (e.g. another input) that resolves the generic. This compiles:

func f<T>(_ i:T, _ ff:(T) -> T) -> T {
    return ff(i)
}
let r = f(2) {
    let result = $0*10
    return result
}

It is only when all the compiler has to go on is the return type that the issue arises.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants