Skip to content

Missing 'in' in closure leads to unhelpful error #59928

Open
@jrose-signal

Description

@jrose-signal

Compiling the following code

func test<T>(make: () -> [T], consume: (T) -> Void) {
    consume(make()[0])
}

func main() {
    test(make: { () -> [Int] // in
        print("hi")
        return [3]
    }, consume: { _ in
        print("bye")
    })
}

leads to the following diagnostics:

<source>:6:18: warning: expression of type '(() -> [Int]).Type' is unused
    test(make: { () -> [Int] // in
                 ^~~~~~~~~~~
<source>:6:18: error: expected member name or constructor call after type name
    test(make: { () -> [Int] // in
                 ^
<source>:6:28: note: use '.self' to reference the type object
    test(make: { () -> [Int] // in
                           ^
                 (          ).self

(thanks, swift.godbolt.org)

This is not a great error message for several reasons:

  1. "constructor" instead of "initializer"
  2. Function types don't currently have members or initializers anyway
  3. A function type as the first statement in a closure without a signature is probably intended to be a signature

With parameters, we get different poor errors:

x -> Int, (x) -> Int
func test<T>(make: (Int) -> [T], consume: (T) -> Void) {
    consume(make(1)[0])
}

func main() {
    test(make: { x -> [Int] // in
        print("hi")
        return [3]
    }, consume: { _ in
        print("bye")
    })
}
<source>:6:18: error: cannot find 'x' in scope
    test(make: { x -> [Int] // in
                 ^
<source>:6:18: error: expected type before '->'
    test(make: { x -> [Int] // in
                 ^
<source>:6:5: error: type of expression is ambiguous without more context
    test(make: { x -> [Int] // in
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(x: Int) -> Int
func test<T>(make: (Int) -> [T], consume: (T) -> Void) {
    consume(make(1)[0])
}

func main() {
    test(make: { (x: Int) -> [Int] // in
        print("hi")
        return [3]
    }, consume: { _ in
        print("bye")
    })
}
<source>:6:16: error: contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored
    test(make: { (x: Int) -> [Int] // in
               ^
                 _ in
x, y -> Int
func test<T>(make: (Int, Int) -> [T], consume: (T) -> Void) {
    consume(make(1, 2)[0])
}

func main() {
    test(make: { x, y -> [Int] // in
        print("hi")
        return [3]
    }, consume: { _ in
        print("bye")
    })
}
<source>:6:19: error: consecutive statements on a line must be separated by ';'
    test(make: { x, y -> [Int] // in
                  ^
                  ;
<source>:6:19: error: expected expression
    test(make: { x, y -> [Int] // in
                  ^
<source>:6:18: error: cannot find 'x' in scope
    test(make: { x, y -> [Int] // in
                 ^
(x, y) -> Int
func test<T>(make: (Int, Int) -> [T], consume: (T) -> Void) {
    consume(make(1, 2)[0])
}

func main() {
    test(make: { (x, y) -> [Int] // in
        print("hi")
        return [3]
    }, consume: { _ in
        print("bye")
    })
}
<source>:6:19: error: cannot find 'x' in scope
    test(make: { (x, y) -> [Int] // in
                  ^
<source>:6:22: error: cannot find 'y' in scope
    test(make: { (x, y) -> [Int] // in
                     ^
<source>:6:18: error: expected type before '->'
    test(make: { (x, y) -> [Int] // in
                 ^
<source>:6:5: error: type of expression is ambiguous without more context
    test(make: { (x, y) -> [Int] // in
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(x: Int, y: Int) -> Int
func test<T>(make: (Int, Int) -> [T], consume: (T) -> Void) {
    consume(make(1, 2)[0])
}

func main() {
    test(make: { (x: Int, y: Int) -> [Int] // in
        print("hi")
        return [3]
    }, consume: { _ in
        print("bye")
    })
}
<source>:6:16: error: contextual type for closure argument list expects 2 arguments, which cannot be implicitly ignored
    test(make: { (x: Int, y: Int) -> [Int] // in
               ^
                 _,_ in

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.closuresFeature: closurescompilerThe Swift compiler itselfdiagnostics QoIBug: Diagnostics Quality of Implementationgood first issueGood for newcomersmissing warningBug: Missing warningparserArea → compiler: The legacy C++ parserswift 5.9

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions