-
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
parser: recover on for<'a> |...| body
closures
#70209
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -925,8 +925,17 @@ impl<'a> Parser<'a> { | |
self.parse_closure_expr(attrs) | ||
} else if self.eat_keyword(kw::If) { | ||
self.parse_if_expr(attrs) | ||
} else if self.eat_keyword(kw::For) { | ||
self.parse_for_expr(None, self.prev_token.span, attrs) | ||
} else if self.check_keyword(kw::For) { | ||
if self.choose_generics_over_qpath(1) { | ||
// NOTE(Centril, eddyb): DO NOT REMOVE! Beyond providing parser recovery, | ||
// this is an insurance policy in case we allow qpaths in (tuple-)struct patterns. | ||
// When `for <Foo as Bar>::Proj in $expr $block` is wanted, | ||
// you can disambiguate in favor of a pattern with `(...)`. | ||
self.recover_quantified_closure_expr(attrs) | ||
} else { | ||
assert!(self.eat_keyword(kw::For)); | ||
self.parse_for_expr(None, self.prev_token.span, attrs) | ||
} | ||
} else if self.eat_keyword(kw::While) { | ||
self.parse_while_expr(None, self.prev_token.span, attrs) | ||
} else if let Some(label) = self.eat_label() { | ||
|
@@ -1416,6 +1425,26 @@ impl<'a> Parser<'a> { | |
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)) | ||
} | ||
|
||
/// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`. | ||
fn recover_quantified_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { | ||
let lo = self.token.span; | ||
let _ = self.parse_late_bound_lifetime_defs()?; | ||
let span_for = lo.to(self.prev_token.span); | ||
let closure = self.parse_closure_expr(attrs)?; | ||
|
||
self.struct_span_err(span_for, "cannot introduce explicit parameters for a closure") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if the language here could be more focused on the present rather than sounding absolute. Like "not yet supported" but maybe not suggesting future support is certain? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We tend to shy away from "not yet" so as to not suggest that it will happen; "cannot" is a fairly standard start of a diagnostic message in the compiler. |
||
.span_label(closure.span, "the parameters are attached to this closure") | ||
.span_suggestion( | ||
span_for, | ||
"remove the parameters", | ||
String::new(), | ||
Applicability::MachineApplicable, | ||
) | ||
.emit(); | ||
|
||
Ok(self.mk_expr_err(lo.to(closure.span))) | ||
} | ||
|
||
/// Parses a closure expression (e.g., `move |args| expr`). | ||
fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { | ||
let lo = self.token.span; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
fn main() { | ||
for<'a> |x: &'a u8| *x + 1; | ||
//~^ ERROR cannot introduce explicit parameters for a closure | ||
} | ||
|
||
enum Foo { Bar } | ||
fn foo(x: impl Iterator<Item = Foo>) { | ||
for <Foo>::Bar in x {} | ||
//~^ ERROR expected one of `move`, `static`, `|` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
error: cannot introduce explicit parameters for a closure | ||
--> $DIR/recover-quantified-closure.rs:2:5 | ||
| | ||
LL | for<'a> |x: &'a u8| *x + 1; | ||
| ^^^^^^^ ------------------ the parameters are attached to this closure | ||
| | | ||
| help: remove the parameters | ||
|
||
error: expected one of `move`, `static`, `|`, or `||`, found `::` | ||
--> $DIR/recover-quantified-closure.rs:8:14 | ||
| | ||
LL | for <Foo>::Bar in x {} | ||
| ^^ expected one of `move`, `static`, `|`, or `||` | ||
|
||
error: aborting due to 2 previous errors | ||
|
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 guess what I was worried about is this any early exist from here resulting in a
for
loop successfully parsing but I guess that's not possible.