From 58765d61ee1762ce0dd9565074000cb9c1267a02 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 18 Jun 2021 10:22:23 +0900 Subject: Emit clearer diagnostics for parens around `for` loop heads --- compiler/rustc_parse/src/parser/diagnostics.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4fccfc287fd..ab7478c7e5f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1346,8 +1346,9 @@ impl<'a> Parser<'a> { .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap()) .unwrap_or_else(|_| pprust::pat_to_string(&pat)); - self.struct_span_err(self.prev_token.span, "unexpected closing `)`") - .span_label(begin_par_sp, "opening `(`") + let sp = MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]); + + self.struct_span_err(sp, "unexpected parenthesis surrounding `for` loop head") .span_suggestion( begin_par_sp.to(self.prev_token.span), "remove parenthesis in `for` loop", -- cgit 1.4.1-3-g733a5 From e9bf73cb2b025e188787683f1423177a9102d260 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 17 Sep 2021 13:39:26 +0900 Subject: Use `multipart_suggestion` --- compiler/rustc_parse/src/parser/diagnostics.rs | 32 +++++++++------------- compiler/rustc_parse/src/parser/expr.rs | 2 +- .../recover-for-loop-parens-around-head.stderr | 10 +++++-- 3 files changed, 21 insertions(+), 23 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ab7478c7e5f..88b5f89f680 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1334,31 +1334,25 @@ impl<'a> Parser<'a> { pub(super) fn recover_parens_around_for_head( &mut self, pat: P, - expr: &Expr, begin_paren: Option, ) -> P { match (&self.token.kind, begin_paren) { (token::CloseDelim(token::Paren), Some(begin_par_sp)) => { self.bump(); - let pat_str = self - // Remove the `(` from the span of the pattern: - .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap()) - .unwrap_or_else(|_| pprust::pat_to_string(&pat)); - - let sp = MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]); - - self.struct_span_err(sp, "unexpected parenthesis surrounding `for` loop head") - .span_suggestion( - begin_par_sp.to(self.prev_token.span), - "remove parenthesis in `for` loop", - format!("{} in {}", pat_str, pprust::expr_to_string(&expr)), - // With e.g. `for (x) in y)` this would replace `(x) in y)` - // with `x) in y)` which is syntactically invalid. - // However, this is prevented before we get here. - Applicability::MachineApplicable, - ) - .emit(); + self.struct_span_err( + MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]), + "unexpected parenthesis surrounding `for` loop head", + ) + .multipart_suggestion( + "remove parenthesis in `for` loop", + vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())], + // With e.g. `for (x) in y)` this would replace `(x) in y)` + // with `x) in y)` which is syntactically invalid. + // However, this is prevented before we get here. + Applicability::MachineApplicable, + ) + .emit(); // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. pat.and_then(|pat| match pat.kind { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 737f1d9cbb1..d8f9fc9179e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> { self.check_for_for_in_in_typo(self.prev_token.span); let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; - let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren); + let pat = self.recover_parens_around_for_head(pat, begin_paren); let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr index 98f6b5b884b..21991348327 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr @@ -8,9 +8,13 @@ error: unexpected parenthesis surrounding `for` loop head --> $DIR/recover-for-loop-parens-around-head.rs:10:9 | LL | for ( elem in vec ) { - | ^-------------^ - | | - | help: remove parenthesis in `for` loop: `elem in vec` + | ^ ^ + | +help: remove parenthesis in `for` loop + | +LL - for ( elem in vec ) { +LL + for elem in vec { + | error[E0308]: mismatched types --> $DIR/recover-for-loop-parens-around-head.rs:13:38 -- cgit 1.4.1-3-g733a5 From 9342be5538ad5c97e8d2496e1cbbf2530d377e5e Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 29 Jul 2021 05:49:56 +0900 Subject: Recover invalid assoc type bounds using `==` --- compiler/rustc_parse/src/parser/diagnostics.rs | 14 +++++++++++- src/test/ui/const-generics/issues/issue-87493.rs | 14 ++++++++++++ .../ui/const-generics/issues/issue-87493.stderr | 26 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const-generics/issues/issue-87493.rs create mode 100644 src/test/ui/const-generics/issues/issue-87493.stderr (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4fccfc287fd..39651bd5e67 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1955,7 +1955,19 @@ impl<'a> Parser<'a> { } match self.parse_expr_res(Restrictions::CONST_EXPR, None) { Ok(expr) => { - if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() { + // Find a mistake like `MyTrait`. + if token::EqEq == snapshot.token.kind { + err.span_suggestion( + snapshot.token.span, + "replace `==` with `=`", + "=".to_string(), + Applicability::MaybeIncorrect, + ); + let value = self.mk_expr_err(expr.span); + err.emit(); + return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); + } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() + { // Avoid the following output by checking that we consumed a full const arg: // help: expressions must be enclosed in braces to be used as const generic // arguments diff --git a/src/test/ui/const-generics/issues/issue-87493.rs b/src/test/ui/const-generics/issues/issue-87493.rs new file mode 100644 index 00000000000..d8599ab22a3 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87493.rs @@ -0,0 +1,14 @@ +pub trait MyTrait { + type Assoc; +} + +pub fn foo(_s: S, _t: T) +where + S: MyTrait, + T: MyTrait, + //~^ ERROR: expected one of `,` or `>`, found `==` + //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied +{ +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-87493.stderr b/src/test/ui/const-generics/issues/issue-87493.stderr new file mode 100644 index 00000000000..b1ac08b51b5 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87493.stderr @@ -0,0 +1,26 @@ +error: expected one of `,` or `>`, found `==` + --> $DIR/issue-87493.rs:8:22 + | +LL | T: MyTrait, + | ^^ + | | + | expected one of `,` or `>` + | help: replace `==` with `=`: `=` + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-87493.rs:8:8 + | +LL | T: MyTrait, + | ^^^^^^^------------------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/issue-87493.rs:1:11 + | +LL | pub trait MyTrait { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. -- cgit 1.4.1-3-g733a5 From ee99bb393953c31169e89597ec893fd15a3ff4ee Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 17 Sep 2021 14:10:41 +0900 Subject: Apply review comments --- compiler/rustc_parse/src/parser/diagnostics.rs | 4 ++-- src/test/ui/const-generics/issues/issue-87493.stderr | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 39651bd5e67..1a77057939f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1959,11 +1959,11 @@ impl<'a> Parser<'a> { if token::EqEq == snapshot.token.kind { err.span_suggestion( snapshot.token.span, - "replace `==` with `=`", + "if you meant to use an associated type binding, replace `==` with `=`", "=".to_string(), Applicability::MaybeIncorrect, ); - let value = self.mk_expr_err(expr.span); + let value = self.mk_expr_err(start.to(expr.span)); err.emit(); return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() diff --git a/src/test/ui/const-generics/issues/issue-87493.stderr b/src/test/ui/const-generics/issues/issue-87493.stderr index b1ac08b51b5..8f92eeaffd1 100644 --- a/src/test/ui/const-generics/issues/issue-87493.stderr +++ b/src/test/ui/const-generics/issues/issue-87493.stderr @@ -2,10 +2,12 @@ error: expected one of `,` or `>`, found `==` --> $DIR/issue-87493.rs:8:22 | LL | T: MyTrait, - | ^^ - | | - | expected one of `,` or `>` - | help: replace `==` with `=`: `=` + | ^^ expected one of `,` or `>` + | +help: if you meant to use an associated type binding, replace `==` with `=` + | +LL | T: MyTrait, + | ~ error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied --> $DIR/issue-87493.rs:8:8 -- cgit 1.4.1-3-g733a5