about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSpanishPear <shrey.somaiya@gmail.com>2022-10-24 00:52:59 +1100
committerSpanishPear <shrey.somaiya@gmail.com>2023-01-22 17:05:37 +1100
commite813132e4f8b0c469c9959c2efa1b0629067b3b8 (patch)
tree6367f65c34fd4cfdd72e3bb474b1db3d87fb9a30
parent1c394e1b9abf83f26d68f441e9f0ef0062bde703 (diff)
downloadrust-e813132e4f8b0c469c9959c2efa1b0629067b3b8.tar.gz
rust-e813132e4f8b0c469c9959c2efa1b0629067b3b8.zip
--wip-- [skip ci]
--wip-- [skip ci]

get the generic text and put it int he suggestion, but suggestion not working on derive subdiagnostic

refactor away from derives and use span_suggestion() instead. Show's the correct(?) generic contents, but overwrites the fn name :(

x fmt

drop commented code and s/todo/fixme

get the correct diagnostic for functions, at least

x fmt

remove some debugs

remove format

remove debugs

remove useless change

remove useless change

remove legacy approach

correct lookahead + error message contains the ident name

fmt

refactor code

tests

add tests

remoev debug

remove comment
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs57
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/enum.fixed10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/enum.rs10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/enum.stderr13
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/existing_generics.rs9
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/existing_generics.stderr10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr13
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs8
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr8
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-simple.fixed10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-simple.rs10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/fn-simple.stderr13
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/struct.fixed10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/struct.rs10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/struct.stderr13
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/trait.fixed12
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/trait.rs12
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/trait.stderr13
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/type.fixed10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/type.rs10
-rw-r--r--src/test/ui/parser/suggest_misplaced_generics/type.stderr13
23 files changed, 292 insertions, 2 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 4c918c6702e..6df9cfd3ff4 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -284,7 +284,7 @@ impl<'a> Parser<'a> {
         self.sess.source_map().span_to_snippet(span)
     }
 
-    pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+    pub(super) fn expected_ident_found(&mut self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         let valid_follow = &[
             TokenKind::Eq,
             TokenKind::Colon,
@@ -324,7 +324,60 @@ impl<'a> Parser<'a> {
             suggest_raw,
             suggest_remove_comma,
         };
-        err.into_diagnostic(&self.sess.span_diagnostic)
+        let mut err = err.into_diagnostic(&self.sess.span_diagnostic);
+
+        // if the token we have is a `<`
+        // it *might* be a misplaced generic
+        if self.token == token::Lt {
+            // all keywords that could have generic applied
+            let valid_prev_keywords =
+                [kw::Fn, kw::Type, kw::Struct, kw::Enum, kw::Union, kw::Trait];
+
+            // If we've expected an identifier,
+            // and the current token is a '<'
+            // if the previous token is a valid keyword
+            // that might use a generic, then suggest a correct
+            // generic placement (later on)
+            let maybe_keyword = self.prev_token.clone();
+            if valid_prev_keywords.into_iter().any(|x| maybe_keyword.is_keyword(x)) {
+                // if we have a valid keyword, attempt to parse generics
+                // also obtain the keywords symbol
+                match self.parse_generics() {
+                    Ok(generic) => {
+                        if let TokenKind::Ident(symbol, _) = maybe_keyword.kind {
+                            let ident_name = symbol.to_string();
+                            // at this point, we've found something like
+                            // `fn <T>id`
+                            // and current token should be Ident with the item name (i.e. the function name)
+                            // if there is a `<` after the fn name, then don't show a suggestion, show help
+
+                            if !self.look_ahead(1, |t| *t == token::Lt) &&
+                                let Ok(snippet) = self.sess.source_map().span_to_snippet(generic.span) &&
+                                let Ok(ident) = self.sess.source_map().span_to_snippet(self.token.span) {
+                                    err.span_suggestion_verbose(
+                                        generic.span.to(self.token.span),
+                                        format!("place the generic parameter name after the {ident_name} name"),
+                                        format!(" {ident}{snippet}"),
+                                        Applicability::MachineApplicable,
+                                    );
+                                } else {
+                                    err.help(format!(
+                                        "place the generic parameter name after the {ident_name} name"
+                                    ));
+                                }
+                        }
+                    }
+                    Err(err) => {
+                        // if there's an error parsing the generics,
+                        // then don't do a misplaced generics suggestion
+                        // and emit the expected ident error instead;
+                        err.cancel();
+                    }
+                }
+            }
+        }
+
+        err
     }
 
     pub(super) fn expected_one_of_not_found(
diff --git a/src/test/ui/parser/suggest_misplaced_generics/enum.fixed b/src/test/ui/parser/suggest_misplaced_generics/enum.fixed
new file mode 100644
index 00000000000..a9d3e9f86d0
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/enum.fixed
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+enum Foo<T> { Variant(T) }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the enum name
+//~| SUGGESTION  Foo<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/enum.rs b/src/test/ui/parser/suggest_misplaced_generics/enum.rs
new file mode 100644
index 00000000000..2d216ba53cc
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/enum.rs
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+enum<T> Foo { Variant(T) }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the enum name
+//~| SUGGESTION  Foo<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/enum.stderr b/src/test/ui/parser/suggest_misplaced_generics/enum.stderr
new file mode 100644
index 00000000000..521cee4f728
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/enum.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `<`
+  --> $DIR/enum.rs:5:5
+   |
+LL | enum<T> Foo { Variant(T) }
+   |     ^ expected identifier
+   |
+help: place the generic parameter name after the enum name
+   |
+LL | enum Foo<T> { Variant(T) }
+   |      ~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/existing_generics.rs b/src/test/ui/parser/suggest_misplaced_generics/existing_generics.rs
new file mode 100644
index 00000000000..1dc182398d8
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/existing_generics.rs
@@ -0,0 +1,9 @@
+// Issue: 103366
+// there is already an existing generic on f, so don't show a suggestion
+
+#[allow(unused)]
+fn<'a, B: 'a + std::ops::Add<Output = u32>> f<T>(_x: B) { }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/existing_generics.stderr b/src/test/ui/parser/suggest_misplaced_generics/existing_generics.stderr
new file mode 100644
index 00000000000..89716e6f1ed
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/existing_generics.stderr
@@ -0,0 +1,10 @@
+error: expected identifier, found `<`
+  --> $DIR/existing_generics.rs:5:3
+   |
+LL | fn<'a, B: 'a + std::ops::Add<Output = u32>> f<T>(_x: B) { }
+   |   ^ expected identifier
+   |
+   = help: place the generic parameter name after the fn name
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed b/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed
new file mode 100644
index 00000000000..06947e098ee
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn f<'a, B: 'a + std::ops::Add<Output = u32>>(_x: B) { }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+//~| SUGGESTION  f<'a, B: 'a + std::ops::Add<Output = u32>>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs b/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs
new file mode 100644
index 00000000000..cefce8d0880
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn<'a, B: 'a + std::ops::Add<Output = u32>> f(_x: B) { }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+//~| SUGGESTION  f<'a, B: 'a + std::ops::Add<Output = u32>>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr b/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr
new file mode 100644
index 00000000000..7d1b44c4494
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `<`
+  --> $DIR/fn-complex-generics.rs:5:3
+   |
+LL | fn<'a, B: 'a + std::ops::Add<Output = u32>> f(_x: B) { }
+   |   ^ expected identifier
+   |
+help: place the generic parameter name after the fn name
+   |
+LL | fn f<'a, B: 'a + std::ops::Add<Output = u32>>(_x: B) { }
+   |    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs b/src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs
new file mode 100644
index 00000000000..7fcb6a82ce4
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs
@@ -0,0 +1,8 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// The generics fail to parse here, so don't make any suggestions/help
+
+#[allow(unused)]
+fn<~>()> id(x: T) -> T { x }
+//~^ ERROR expected identifier, found `<`
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr b/src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr
new file mode 100644
index 00000000000..47e12016938
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `<`
+  --> $DIR/fn-invalid-generics.rs:5:3
+   |
+LL | fn<~>()> id(x: T) -> T { x }
+   |   ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-simple.fixed b/src/test/ui/parser/suggest_misplaced_generics/fn-simple.fixed
new file mode 100644
index 00000000000..31c5429b16b
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-simple.fixed
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn id<T>(x: T) -> T { x }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+//~| SUGGESTION  id<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-simple.rs b/src/test/ui/parser/suggest_misplaced_generics/fn-simple.rs
new file mode 100644
index 00000000000..0a466184e99
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-simple.rs
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn<T> id(x: T) -> T { x }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+//~| SUGGESTION  id<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/fn-simple.stderr b/src/test/ui/parser/suggest_misplaced_generics/fn-simple.stderr
new file mode 100644
index 00000000000..40c4581e513
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/fn-simple.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `<`
+  --> $DIR/fn-simple.rs:5:3
+   |
+LL | fn<T> id(x: T) -> T { x }
+   |   ^ expected identifier
+   |
+help: place the generic parameter name after the fn name
+   |
+LL | fn id<T>(x: T) -> T { x }
+   |    ~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/struct.fixed b/src/test/ui/parser/suggest_misplaced_generics/struct.fixed
new file mode 100644
index 00000000000..8627699a830
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/struct.fixed
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+struct Foo<T> { x: T }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the struct name
+//~| SUGGESTION  Foo<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/struct.rs b/src/test/ui/parser/suggest_misplaced_generics/struct.rs
new file mode 100644
index 00000000000..15646b06cfc
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/struct.rs
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+struct<T> Foo { x: T }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the struct name
+//~| SUGGESTION  Foo<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/struct.stderr b/src/test/ui/parser/suggest_misplaced_generics/struct.stderr
new file mode 100644
index 00000000000..ab17ee57e0b
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/struct.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `<`
+  --> $DIR/struct.rs:5:7
+   |
+LL | struct<T> Foo { x: T }
+   |       ^ expected identifier
+   |
+help: place the generic parameter name after the struct name
+   |
+LL | struct Foo<T> { x: T }
+   |        ~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/trait.fixed b/src/test/ui/parser/suggest_misplaced_generics/trait.fixed
new file mode 100644
index 00000000000..31ebf1f088f
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/trait.fixed
@@ -0,0 +1,12 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+trait Foo<T> {
+    //~^ ERROR expected identifier, found `<`
+    //~| HELP place the generic parameter name after the trait name
+    //~| SUGGESTION  Foo<T>
+}
+
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/trait.rs b/src/test/ui/parser/suggest_misplaced_generics/trait.rs
new file mode 100644
index 00000000000..81b6abbd661
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/trait.rs
@@ -0,0 +1,12 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+trait<T> Foo {
+    //~^ ERROR expected identifier, found `<`
+    //~| HELP place the generic parameter name after the trait name
+    //~| SUGGESTION  Foo<T>
+}
+
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/trait.stderr b/src/test/ui/parser/suggest_misplaced_generics/trait.stderr
new file mode 100644
index 00000000000..069683bda1b
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/trait.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `<`
+  --> $DIR/trait.rs:5:6
+   |
+LL | trait<T> Foo {
+   |      ^ expected identifier
+   |
+help: place the generic parameter name after the trait name
+   |
+LL | trait Foo<T> {
+   |       ~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/suggest_misplaced_generics/type.fixed b/src/test/ui/parser/suggest_misplaced_generics/type.fixed
new file mode 100644
index 00000000000..b04003b803d
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/type.fixed
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+type Foo<T> = T;
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the type name
+//~| SUGGESTION  Foo<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/type.rs b/src/test/ui/parser/suggest_misplaced_generics/type.rs
new file mode 100644
index 00000000000..2d759a8b1ab
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/type.rs
@@ -0,0 +1,10 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+type<T> Foo = T;
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the type name
+//~| SUGGESTION  Foo<T>
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest_misplaced_generics/type.stderr b/src/test/ui/parser/suggest_misplaced_generics/type.stderr
new file mode 100644
index 00000000000..a2832965c6d
--- /dev/null
+++ b/src/test/ui/parser/suggest_misplaced_generics/type.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found `<`
+  --> $DIR/type.rs:5:5
+   |
+LL | type<T> Foo = T;
+   |     ^ expected identifier
+   |
+help: place the generic parameter name after the type name
+   |
+LL | type Foo<T> = T;
+   |      ~~~~~~
+
+error: aborting due to previous error
+