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-12488] Type inference (of Void) for generic method fails without explicit return #54930

Closed
ktoso opened this issue Apr 2, 2020 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@ktoso
Copy link
Member

ktoso commented Apr 2, 2020

Previous ID SR-12488
Radar rdar://problem/61911119
Original Reporter @ktoso
Type Bug
Status Closed
Resolution Won't Do
Environment

Apple Swift version 5.2 (swiftlang-1103.0.32.1 clang-1103.0.32.29)

Additional Detail from JIRA
Votes 1
Component/s
Labels Bug
Assignee None
Priority Medium

md5: ee03922ab21551c314b95d6f7799763a

Issue Description:

Consider such example function:

public func TODO<T>(_ hint: StaticString, function: StaticString = #function, file: String = #file, line: UInt = #line) -> T {
    fatalError("undefined \(function) -> \(T.self): \(hint)", file: file, line: line)
}

This can be used to mark "TODO once something is implemented" and we use it like this:

func hello() { 
    return TODO("Once #&#8203;22323 is solved")
}

This works fine... However default swift-format (the non-apple one, for now) rules may (and do) cause this function to changed to:

func boom() {
    TODO("once #&#8203;2222 is solved")
}
error: repl.swift:14:5: error: generic parameter 'T' could not be inferred
    TODO("once #&#8203;2222 is solved")
    ^
repl.swift:5:13: note: in call to function 'TODO(_:function:file:line:)'
public func TODO<T>(_ hint: String, function: StaticString = #function, file: StaticString = #file, line: UInt = #line) -> T {

It's somewhat annoying since we'd like to use that swift-format rule to remove returns where they are not necessary, however it does break code whenever such method is encountered.

Expectation: the <T> should still be inferred as Void, even without the return keyword present.

@ktoso
Copy link
Member Author

ktoso commented Apr 2, 2020

One might argue to make that function just -> Never and that's fine for this function, but we also use undefined() -> T while prototyping sometimes, this ticket is more about the general type inference behavior.

@ktoso
Copy link
Member Author

ktoso commented Apr 13, 2020

@swift-ci create

@ktoso
Copy link
Member Author

ktoso commented Apr 21, 2020

Interesting observation, adding a `T.Type = T.self` parameter actually helps the inference get it right. A bit weird that it makes a difference tbh, but it solves the Void inference case:

without:

  1> func TODO<T>() -> T { fatalError() }
  2> func x() { TODO() }
error: repl.swift:2:12: error: generic parameter 'T' could not be inferred
func x() { TODO() }
           ^

with:

  1> func TODO<T>(t: T.Type = T.self) -> T { fatalError() }
  2> func x() { TODO() }
error: repl.swift:2:12: error: generic parameter 'T' could not be inferred
func x() { TODO() }
           ^

Those two should be equivalent for type inference imho, but I guess that's a workaround.

@hborla
Copy link
Member

hborla commented May 5, 2020

For Void-returning functions that have single-expression bodies, the single expression is not parsed as an implicit return statement. This exception is intentional and justified in the proposal for implicit return statements.

One workaround is to coerce the result of TODO() to Void, e.g.

func boom() {
    TODO("once #&#8203;2222 is solved") as Void
}

@ktoso
Copy link
Member Author

ktoso commented May 6, 2020

Thanks for pulling up the SE, Holly! I missed that exception there.

I see... A bit disappointing that there's exceptions like that to be honest, but ok, seems to be as it was designed.

For context: other languages with return inference handle this case well, without burdening the developer with edge cases (e.g. Scala), so it was a surprise to me. Perhaps some time it could be ironed out, we'll see.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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.
Projects
None yet
Development

No branches or pull requests

2 participants