]> git.lizzy.rs Git - rust.git/commitdiff
Add a suggestion if `macro_rules` is misspelled
authorFabian Wolff <fabian.wolff@alumni.ethz.ch>
Sun, 28 Nov 2021 22:10:37 +0000 (23:10 +0100)
committerFabian Wolff <fabian.wolff@alumni.ethz.ch>
Sun, 28 Nov 2021 22:10:37 +0000 (23:10 +0100)
compiler/rustc_parse/src/parser/item.rs
src/test/ui/parser/misspelled-macro-rules.fixed [new file with mode: 0644]
src/test/ui/parser/misspelled-macro-rules.rs [new file with mode: 0644]
src/test/ui/parser/misspelled-macro-rules.stderr [new file with mode: 0644]

index 24a8df49ac7eefb20653314af14b2372d899f5dc..aa572eaf162cf0cb448f52baf69aaa7ff619f95b 100644 (file)
@@ -15,6 +15,7 @@
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
 use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
+use rustc_span::lev_distance::lev_distance;
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 
@@ -407,10 +408,30 @@ fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
     fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
         let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
         self.expect(&token::Not)?; // `!`
-        let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
-        self.eat_semi_for_macro_if_needed(&args);
-        self.complain_if_pub_macro(vis, false);
-        Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription })
+        match self.parse_mac_args() {
+            // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
+            Ok(args) => {
+                self.eat_semi_for_macro_if_needed(&args);
+                self.complain_if_pub_macro(vis, false);
+                Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription })
+            }
+
+            Err(mut err) => {
+                // Maybe the user misspelled `macro_rules` (issue #91227)
+                if self.token.is_ident()
+                    && path.segments.len() == 1
+                    && lev_distance("macro_rules", &path.segments[0].ident.to_string()) <= 3
+                {
+                    err.span_suggestion(
+                        path.span,
+                        "perhaps you meant to define a macro",
+                        "macro_rules".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                }
+                Err(err)
+            }
+        }
     }
 
     /// Recover if we parsed attributes and expected an item but there was none.
diff --git a/src/test/ui/parser/misspelled-macro-rules.fixed b/src/test/ui/parser/misspelled-macro-rules.fixed
new file mode 100644 (file)
index 0000000..62be913
--- /dev/null
@@ -0,0 +1,13 @@
+// Regression test for issue #91227.
+
+// run-rustfix
+
+#![allow(unused_macros)]
+
+macro_rules! thing {
+//~^ ERROR: expected one of
+//~| HELP: perhaps you meant to define a macro
+    () => {}
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/misspelled-macro-rules.rs b/src/test/ui/parser/misspelled-macro-rules.rs
new file mode 100644 (file)
index 0000000..4290e6e
--- /dev/null
@@ -0,0 +1,13 @@
+// Regression test for issue #91227.
+
+// run-rustfix
+
+#![allow(unused_macros)]
+
+marco_rules! thing {
+//~^ ERROR: expected one of
+//~| HELP: perhaps you meant to define a macro
+    () => {}
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/misspelled-macro-rules.stderr b/src/test/ui/parser/misspelled-macro-rules.stderr
new file mode 100644 (file)
index 0000000..56df712
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected one of `(`, `[`, or `{`, found `thing`
+  --> $DIR/misspelled-macro-rules.rs:7:14
+   |
+LL | marco_rules! thing {
+   | -----------  ^^^^^ expected one of `(`, `[`, or `{`
+   | |
+   | help: perhaps you meant to define a macro: `macro_rules`
+
+error: aborting due to previous error
+