diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 8921c1c6a03..2b86c8d13ac 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -674,15 +674,6 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { ); } - // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens - // there are unclosed angle brackets - if self.unmatched_angle_bracket_count > 0 - && self.token.kind == TokenKind::Eq - && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt))) - { - err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket"); - } - let sp = if self.token == token::Eof { // This is EOF; don't want to point at the following char, but rather the last token. self.prev_token.span @@ -819,6 +810,7 @@ pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) { } err.emit(); } + fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool { let sm = self.sess.source_map(); match (&self.prev_token.kind, &self.token.kind) { @@ -1994,6 +1986,39 @@ pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P> { } } + /// When trying to close a generics list and encountering code like + /// ```text + /// impl> From for Canonical {} + /// // ^ missing > here + /// ``` + /// we provide a structured suggestion on the error from `expect_gt`. + pub(super) fn expect_gt_or_maybe_suggest_closing_generics( + &mut self, + params: &[ast::GenericParam], + ) -> PResult<'a, ()> { + let Err(mut err) = self.expect_gt() else { + return Ok(()); + }; + // Attempt to find places where a missing `>` might belong. + if let [.., ast::GenericParam { bounds, .. }] = params + && let Some(poly) = bounds + .iter() + .filter_map(|bound| match bound { + ast::GenericBound::Trait(poly, _) => Some(poly), + _ => None, + }) + .last() + { + err.span_suggestion_verbose( + poly.span.shrink_to_hi(), + "you might have meant to end the type parameters here", + ">", + Applicability::MaybeIncorrect, + ); + } + Err(err) + } + pub(super) fn recover_seq_parse_error( &mut self, delim: Delimiter, diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 242c9d332bb..20f67b284b2 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -279,7 +279,7 @@ pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { let span_lo = self.token.span; let (params, span) = if self.eat_lt() { let params = self.parse_generic_params()?; - self.expect_gt()?; + self.expect_gt_or_maybe_suggest_closing_generics(¶ms)?; (params, span_lo.to(self.prev_token.span)) } else { (ThinVec::new(), self.prev_token.span.shrink_to_hi()) diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr index 59c21e24a42..838d37cc64f 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -2,9 +2,7 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` --> $DIR/trait-path-expected-token.rs:5:33 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of 7 possible tokens - | | - | maybe try to close unmatched angle bracket + | ^ expected one of 7 possible tokens error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr index cf2b1763fc9..06dbf00af63 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -10,9 +10,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-expressions.rs:16:36 | LL | fn f2<'a>(arg : Box>) {} - | - ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr index bfddb6dc693..4bc57f55096 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -8,9 +8,7 @@ error: expected one of `>`, a const expression, lifetime, or type, found `=` --> $DIR/trait-path-missing-gen_arg.rs:11:30 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of `>`, a const expression, lifetime, or type - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to 2 previous errors diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr index 8bc737d6752..0ab155590e2 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -2,9 +2,7 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` --> $DIR/trait-path-segments.rs:6:36 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of 8 possible tokens - | | - | maybe try to close unmatched angle bracket + | ^ expected one of 8 possible tokens | help: you might have meant to end the type parameters here | @@ -15,9 +13,7 @@ error: expected one of `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:17:35 | LL | impl::Y<'a> = &'a u32>> Z for T {} - | - ^ expected one of `,`, `::`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `::`, `:`, or `>` | help: you might have meant to end the type parameters here | @@ -28,9 +24,7 @@ error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:28:25 | LL | impl = &'a u32>> Z for T {} - | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` | help: you might have meant to end the type parameters here | diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.stderr b/tests/ui/generic-associated-types/parse/trait-path-types.stderr index 8f7a73c95b6..ec1aa71846d 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-types.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-types.stderr @@ -2,9 +2,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:6:37 | LL | fn f<'a>(arg : Box>) {} - | - ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | @@ -15,9 +13,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:11:37 | LL | fn f1<'a>(arg : Box) = &'a ()>>) {} - | - ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | @@ -28,9 +24,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:16:33 | LL | fn f1<'a>(arg : Box>) {} - | -- ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | diff --git a/tests/ui/generics/unclosed-generics-in-impl-def.rs b/tests/ui/generics/unclosed-generics-in-impl-def.rs new file mode 100644 index 00000000000..2ec99b16e55 --- /dev/null +++ b/tests/ui/generics/unclosed-generics-in-impl-def.rs @@ -0,0 +1,2 @@ +impl> From for Canonical {} //~ ERROR expected +fn main() {} diff --git a/tests/ui/generics/unclosed-generics-in-impl-def.stderr b/tests/ui/generics/unclosed-generics-in-impl-def.stderr new file mode 100644 index 00000000000..aa1977ad82a --- /dev/null +++ b/tests/ui/generics/unclosed-generics-in-impl-def.stderr @@ -0,0 +1,13 @@ +error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From` + --> $DIR/unclosed-generics-in-impl-def.rs:1:46 + | +LL | impl> From for Canonical {} + | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | impl>> From for Canonical {} + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr index 753942dd1d1..ac2e63eca3e 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/issues/issue-34334.stderr @@ -2,9 +2,8 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/issue-34334.rs:2:29 | LL | let sr: Vec<(u32, _, _) = vec![]; - | -- - ^ expected one of `,`, `:`, or `>` - | | | - | | maybe try to close unmatched angle bracket + | -- ^ expected one of `,`, `:`, or `>` + | | | while parsing the type for `sr` | help: you might have meant to end the type parameters here diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index b2448774ae9..e40d9858262 100644 --- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -2,9 +2,8 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:23 | LL | let v : Vec<(u32,_) = vec![]; - | - - ^ expected one of `,`, `:`, or `>` - | | | - | | maybe try to close unmatched angle bracket + | - ^ expected one of `,`, `:`, or `>` + | | | while parsing the type for `v` | help: you might have meant to end the type parameters here @@ -29,9 +28,8 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18 | LL | let v : Vec<'a = vec![]; - | - -- ^ expected one of `,`, `:`, or `>` - | | | - | | maybe try to close unmatched angle bracket + | - ^ expected one of `,`, `:`, or `>` + | | | while parsing the type for `v` | help: you might have meant to end the type parameters here