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

Add a warning when a discardable result determines the type of a closure #78597

Open
stefanspringer1 opened this issue Jan 12, 2025 · 0 comments
Labels
feature A feature request or implementation triage needed This issue needs more specific labels

Comments

@stefanspringer1
Copy link

stefanspringer1 commented Jan 12, 2025

Motivation

Consider the code

func f() { doSomething() }

let h = { () in f() }

Clearly, h is of type () -> ().

But you might want to call the following function g instead of f in h, because g does something more appropriate:

@discardableResult
func g() -> Int { doSomethingElse(); return 1 }

let h = { () in g() }

Now the type of h is () -> Int, but this might come unexpected, because you use g at other places while ignoring its result. Also, even if you are aware that g has a discardable result, the type of h is now intuitively unclear.

Proposed solution

If a discardable result determines the type of a closure as described in the example in the motivation part, there should be a warning. A warning should not hurt existing code bases too much, as code then still compiles if it compiled before. In the example above, you can add “return ” or “_ = “ to silence that warning:

let h = { () in return g() } // h: () -> Int

or

let h = { () in _ = g() } // h: () -> ()

A warning is not necessary in the following cases:

let h = { () in if myCondition { 2 } else { g() } } // h: () -> Int

and

let h = { () in if myCondition { print("not calling g") } else { g() } } // h: () -> ()

There are cases where type annotations (and to make them possible maybe some further refactoring, or some refactoring alone without added type annotations) are then necessary to silence the warning:

With another function with a discardable result

@discardableResult
func g2() -> Int { doSomethingElse(); return 2 }

you would have to write

let h: () -> Int = { () in if myCondition { g2() } else { g() } }

or

let h: () -> () = { () in if myCondition { g2() } else { g() } }

Alternatives considered

The alternative is to leave it as it is (no warning).

Additional information

The issue came up in the discussion of the Swift forums topic Last expression as return value. The pitch discussed there would be source breaking in a case that would get the warning proposed here.

@stefanspringer1 stefanspringer1 added feature A feature request or implementation triage needed This issue needs more specific labels labels Jan 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A feature request or implementation triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

1 participant