From 419df5f4a06bc4dff05152413c783758b46ff6b9 Mon Sep 17 00:00:00 2001 From: Yiming Lei Date: Thu, 13 Oct 2022 10:30:33 -0700 Subject: [PATCH] error parsing lifetime following by Sized and message + between them detect the pattern at the general site parse_impl_ty() this will fix #102598 --- compiler/rustc_parse/src/parser/item.rs | 1 - compiler/rustc_parse/src/parser/ty.rs | 19 +++++++++++ src/test/ui/type/issue-102598.rs | 8 +++++ src/test/ui/type/issue-102598.stderr | 43 +++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/type/issue-102598.rs create mode 100644 src/test/ui/type/issue-102598.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index beb9d55d454..063421d62fe 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2449,7 +2449,6 @@ impl<'a> Parser<'a> { }; let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - let (pat, colon) = this.parse_fn_param_pat_colon()?; if !colon { let mut err = this.unexpected::<()>().unwrap_err(); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b7206b57642..fc26278909c 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -613,6 +613,25 @@ impl<'a> Parser<'a> { /// Parses an `impl B0 + ... + Bn` type. fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { // Always parse bounds greedily for better error recovery. + if self.token.is_lifetime() { + self.look_ahead(1, |t| { + if let token::Ident(symname, _) = t.kind { + // parse pattern with "'a Sized" we're supposed to give suggestion like + // "'a + Sized" + self.struct_span_err( + self.token.span, + &format!("expected `+` between lifetime and {}", symname), + ) + .span_suggestion_verbose( + self.token.span.shrink_to_hi(), + "add `+`", + " +", + Applicability::MaybeIncorrect, + ) + .emit(); + } + }) + } let bounds = self.parse_generic_bounds(None)?; *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) diff --git a/src/test/ui/type/issue-102598.rs b/src/test/ui/type/issue-102598.rs new file mode 100644 index 00000000000..93808f18b99 --- /dev/null +++ b/src/test/ui/type/issue-102598.rs @@ -0,0 +1,8 @@ +fn foo<'a>(_: impl 'a Sized) {} +//~^ ERROR: expected `+` between lifetime and Sized +//~| ERROR: expected one of `:`, `@`, or `|`, found `)` +//~| ERROR: expected one of `)`, `+`, or `,`, found `Sized` +//~| ERROR: at least one trait must be specified + +fn main(){ +} diff --git a/src/test/ui/type/issue-102598.stderr b/src/test/ui/type/issue-102598.stderr new file mode 100644 index 00000000000..a232395cedb --- /dev/null +++ b/src/test/ui/type/issue-102598.stderr @@ -0,0 +1,43 @@ +error: expected `+` between lifetime and Sized + --> $DIR/issue-102598.rs:1:20 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^^ + | +help: add `+` + | +LL | fn foo<'a>(_: impl 'a + Sized) {} + | + + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/issue-102598.rs:1:28 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn foo<'a>(_: impl 'a Sized: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo<'a>(_: impl 'a _: Sized) {} + | ++ + +error: expected one of `)`, `+`, or `,`, found `Sized` + --> $DIR/issue-102598.rs:1:23 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | -^^^^^ expected one of `)`, `+`, or `,` + | | + | help: missing `,` + +error: at least one trait must be specified + --> $DIR/issue-102598.rs:1:15 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^^^^^^^ + +error: aborting due to 4 previous errors +