about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs43
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs2
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr4
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-expressions.stderr4
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr4
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-segments.stderr12
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-types.stderr12
-rw-r--r--tests/ui/generics/unclosed-generics-in-impl-def.rs2
-rw-r--r--tests/ui/generics/unclosed-generics-in-impl-def.stderr13
-rw-r--r--tests/ui/issues/issue-34334.stderr5
-rw-r--r--tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr10
11 files changed, 65 insertions, 46 deletions
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 @@ impl<'a> Parser<'a> {
             );
         }
 
-        // 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 @@ impl<'a> Parser<'a> {
         }
         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 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// When trying to close a generics list and encountering code like
+    /// ```text
+    /// impl<S: Into<std::borrow::Cow<'static, str>> From<S> 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 @@ impl<'a> Parser<'a> {
         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(&params)?;
             (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<dyn X<Y = B = &'a ()>>) {}
-   |                               - ^ 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<dyn X< { 1 } = 32 >>) {}
-   |                                  - ^ 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<dyn X< = 32 >>) {}
-   |                            - ^ 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<dyn X<X::Y = u32>>) {}
-   |                                  - ^ 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<T : X<<Self as X>::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<T : X<X::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
    |
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<dyn X< [u8; 1] = u32>>) {}
-   |                                   - ^ 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<dyn X<(Y<'a>) = &'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<dyn X< 'a = u32 >>) {}
-   |                              -- ^ 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<S: Into<std::borrow::Cow<'static, str>> From<S> 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<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical {}
+   |                                              ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> 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