Skip to content

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

@stefanspringer1

Description

@stefanspringer1

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureA feature request or implementationtriage neededThis issue needs more specific labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions