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

Attempting to debug in a iterator's closure without {} gives unhelpful error #88065

Closed
schneems opened this issue Aug 15, 2021 · 3 comments · Fixed by #88546
Closed

Attempting to debug in a iterator's closure without {} gives unhelpful error #88065

schneems opened this issue Aug 15, 2021 · 3 comments · Fixed by #88546
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@schneems
Copy link
Contributor

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9b9dfd706291c45a1f6a567324b6c860

Given the following code:

fn main() {
    let num = 5;
    (1..num).reduce(|a, b| 
        println!("{}", a); // <== Here
        a * b
    ).unwrap();
}

The current output is:

   Compiling playground v0.0.1 (/playground)
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
 --> src/main.rs:4:26
  |
4 |         println!("{}", a); // <== Here
  |                          ^
  |                          |
  |                          expected one of `)`, `,`, `.`, `?`, or an operator
  |                          help: missing `,`

error[E0425]: cannot find value `a` in this scope
 --> src/main.rs:5:9
  |
5 |         a * b
  |         ^ not found in this scope

error[E0425]: cannot find value `b` in this scope
 --> src/main.rs:5:13
  |
5 |         a * b
  |             ^ not found in this scope

error[E0061]: this function takes 1 argument but 2 arguments were supplied
    --> src/main.rs:3:14
     |
3    |       (1..num).reduce(|a, b| 
     |  ______________^^^^^^_-
     | |              |
     | |              expected 1 argument
4    | |         println!("{}", a); // <== Here
     | |_________________________-
5    |           a * b
     |           ----- supplied 2 arguments
     |
note: associated function defined here

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0061, E0425.
For more information about an error, try `rustc --explain E0061`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

Ideally the output should look like:

3    |       (1..num).reduce(|a, b| {
     |  ____________________________^
     | | Multi-line closure requires scope brackets

I was trying to debug an iterator and added a println! call. To my surprise, it caused the compiler to fail and emit MANY warnings. None of them pointed at the real problem which is that I was missing curly brackets {}.

@schneems schneems added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 15, 2021
@inquisitivecrystal inquisitivecrystal added D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Aug 15, 2021
@scrabsha
Copy link
Contributor

Hi there! I'd like to work on this issue, as it's an error I frequently hit too.

@jyn514
Copy link
Member

jyn514 commented Aug 16, 2021

 | | Multi-line closure requires scope brackets

Note that the compiler ignores whitespace - this should say something like "if a closure body contains a statement, it must be surrounded by braces".

@scrabsha I'm not sure exactly how to fix this issue, but there are general instructions in https://rustc-dev-guide.rust-lang.org/, and the relevant code lives in

let body = match decl.output {
. You can ask on Zulip for help: https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp

@estebank estebank added the A-parser Area: The parsing of Rust source code to an AST label Aug 16, 2021
@estebank
Copy link
Contributor

estebank commented Aug 16, 2021

Note that the compiler ignores whitespace

But also keep in mind that for error recovery, we are free to use the whitespace as a signal. The parser isn't well set up to make it easy, but there's a method SourceMap::is_multiline(&self, Span) that you can use to see if two different things are on different lines (usually by doing something like sp1.between(sp2) to make a new span covering the space between two spans you already have).

This ticket is somewhat related to #27300, where someone might try to use the Ruby syntax. If we fix this one, that one could also get fixed by default, depending on the specifics. I tried unsuccessfully to tackle that one some time back, but I can think of multiple better approaches than what I did back then.

The big problem here is that code is syntactically correct, but there are multiple knock down errors during typechecking and name resolution.

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Sep 9, 2021
…races, r=estebank

Emit proper errors when on missing closure braces

This commit focuses on emitting clean errors for the following syntax
error:

```
Some(42).map(|a|
    dbg!(a);
    a
);
```

Previous implementation tried to recover after parsing the closure body
(the `dbg` expression) by replacing the next `;` with a `,`, which made
the next expression belong to the next function argument. As such, the
following errors were emitted (among others):
  - the semicolon token was not expected,
  - a is not in scope,
  - Option::map is supposed to take one argument, not two.

This commit allows us to gracefully handle this situation by adding
giving the parser the ability to remember when it has just parsed a
closure body inside a function call. When this happens, we can treat the
unexpected `;` specifically and try to parse as much statements as
possible in order to eat the whole block. When we can't parse statements
anymore, we generate a clean error indicating that the braces are
missing, and return an ExprKind::Err.

Closes rust-lang#88065.

r? `@estebank`
@bors bors closed this as completed in dc003dd Sep 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST C-enhancement Category: An issue proposing an enhancement or a PR with one. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants