-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Emit proper errors when on missing closure braces #88546
Emit proper errors when on missing closure braces #88546
Conversation
921a11b
to
3bdda1c
Compare
error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>` | ||
--> $DIR/ruby_style_closure.rs:2:22 | ||
| | ||
LL | let p = Some(45).and_then({ | ||
| ^^^^^^^^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be pointing at the Some(x * 2)
as well. (Not something to address in this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in #88719
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me after addressing the comments.
src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr
Outdated
Show resolved
Hide resolved
if self.token.kind == TokenKind::Semi && self.token_cursor.frame.delim == DelimToken::Paren | ||
{ | ||
// It is likely that the closure body is a block but where the | ||
// braces have been removed. We will recover and eat the next | ||
// statements later in the parsing process. | ||
body = self.mk_expr_err(body.span); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm somewhat uneasy with this check, but having both Semi
and Paren
be true should only happen on malformed code.
@bors r+ |
📌 Commit 99c46c0 has been approved by |
…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`
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.
99c46c0
to
b21425d
Compare
@bors r+ |
📌 Commit b21425d has been approved by |
Thanks for the approval and sorry for the noise I created. I'll do better next time :) |
…arth Rollup of 15 pull requests Successful merges: - rust-lang#85200 (Ignore derived Clone and Debug implementations during dead code analysis) - rust-lang#86165 (Add proc_macro::Span::{before, after}.) - rust-lang#87088 (Fix stray notes when the source code is not available) - rust-lang#87441 (Emit suggestion when passing byte literal to format macro) - rust-lang#88546 (Emit proper errors when on missing closure braces) - rust-lang#88578 (fix(rustc): suggest `items` be borrowed in `for i in items[x..]`) - rust-lang#88632 (Fix issues with Markdown summary options) - rust-lang#88639 (rustdoc: Fix ICE with `doc(hidden)` on tuple variant fields) - rust-lang#88667 (Tweak `write_fmt` doc.) - rust-lang#88720 (Rustdoc coverage fields count) - rust-lang#88732 (RustWrapper: avoid deleted unclear attribute methods) - rust-lang#88742 (Fix table in docblocks) - rust-lang#88776 (Workaround blink/chromium grid layout limitation of 1000 rows) - rust-lang#88807 (Fix typo in docs for iterators) - rust-lang#88812 (Fix typo `option` -> `options`.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
… r=nagisa Point at argument instead of call for their obligations When an obligation is introduced by a specific `fn` argument, point at the argument instead of the `fn` call if the obligation fails to be fulfilled. Move the information about pointing at the call argument expression in an unmet obligation span from the `FulfillmentError` to a new `ObligationCauseCode`. When giving an error about an obligation introduced by a function call that an argument doesn't fulfill, and that argument is a block, add a span_label pointing at the innermost tail expression. Current output: ``` error[E0425]: cannot find value `x` in this scope --> f10.rs:4:14 | 4 | Some(x * 2) | ^ not found in this scope error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>` --> f10.rs:2:31 | 2 | let p = Some(45).and_then({ | ______________________--------_^ | | | | | required by a bound introduced by this call 3 | | |x| println!("doubling {}", x); 4 | | Some(x * 2) | | ----------- 5 | | }); | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` | = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>` ``` Previous output: ``` error[E0425]: cannot find value `x` in this scope --> f10.rs:4:14 | 4 | Some(x * 2) | ^ not found in this scope error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>` --> f10.rs:2:22 | 2 | let p = Some(45).and_then({ | ^^^^^^^^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` | = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>` ``` Partially address rust-lang#27300. Will require rebasing on top of rust-lang#88546.
…-in-macro, r=fee1-dead Allow semicolon after closure within parentheses in macros rust-lang#88546 added some parsing logic that if we're parsing a closure, and we're within parentheses, and a semicolon follows, then we must be parsing something erroneous like: `f(|| a; b)`, so it replaces the closure body with an error expression. However, it's valid to parse those tokens if we're within a macro, as in rust-lang#103222. This is a bit unsatisfying fix. Is there a more robust way of checking that we're within a macro? I would also be open to removing this "_It is likely that the closure body is a block but where the braces have been removed_" check altogether at the expense of more verbose errors, since it seems very suspicious in the first place... Fixes rust-lang#103222.
This commit focuses on emitting clean errors for the following syntax
error:
Previous implementation tried to recover after parsing the closure body
(the
dbg
expression) by replacing the next;
with a,
, which madethe next expression belong to the next function argument. As such, the
following errors were emitted (among others):
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 aspossible 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 #88065.
r? @estebank