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

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

Open
jrose-signal opened this issue Jul 6, 2022 · 5 comments
Open

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

jrose-signal opened this issue Jul 6, 2022 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. closures Feature: closures compiler The Swift compiler itself diagnostics QoI Bug: Diagnostics Quality of Implementation good first issue Good for newcomers missing warning Bug: Missing warning parser Area → compiler: The legacy C++ parser swift 5.9

Comments

@jrose-signal
Copy link

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
@jrose-signal jrose-signal added the bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. label Jul 6, 2022
@xedin
Copy link
Contributor

xedin commented Jul 6, 2022

@rintaro Could parser help us here?

@AnthonyLatsis
Copy link
Collaborator

Related to swiftlang/swift-syntax#2204

@rintaro
Copy link
Member

rintaro commented Jul 6, 2022

As shown in swiftlang/swift-syntax#2204, parser can't know it's meant to be a signature, or actual expressions.
Maybe, if the parser see -> at the "top level" of the closure, assuming it's always invalid as an expression, the parser can parse it as a signature. So the cases in this specific bug should be resolvable in parser, but only if there's a -> (or maybe async or throws). So it won't fix swiftlang/swift-syntax#2204.

@xedin
Copy link
Contributor

xedin commented Jul 7, 2022

:( This is somewhat unfortunate...

@xedin
Copy link
Contributor

xedin commented Jul 13, 2022

Found another one swiftlang/swift-syntax#2196

@AnthonyLatsis AnthonyLatsis added parser Area → compiler: The legacy C++ parser closures Feature: closures missing warning Bug: Missing warning compiler The Swift compiler itself swift 5.9 diagnostics QoI Bug: Diagnostics Quality of Implementation good first issue Good for newcomers labels Sep 10, 2023
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. closures Feature: closures compiler The Swift compiler itself diagnostics QoI Bug: Diagnostics Quality of Implementation good first issue Good for newcomers missing warning Bug: Missing warning parser Area → compiler: The legacy C++ parser swift 5.9
Projects
None yet
Development

No branches or pull requests

4 participants