From 017747fa5afb1e5396582498303c8437792966d7 Mon Sep 17 00:00:00 2001
From: Esteban Kuber <esteban@kuber.com.ar>
Date: Wed, 19 Jan 2022 02:27:15 +0000
Subject: [PATCH] Only suggest adding `!` to expressions that can be macro
 invocation

---
 compiler/rustc_resolve/src/late.rs            |  4 ++
 .../rustc_resolve/src/late/diagnostics.rs     | 11 ++++-
 .../hygiene/rustc-macro-transparency.stderr   | 28 ++++--------
 src/test/ui/resolve/resolve-hint-macro.fixed  | 11 +++++
 src/test/ui/resolve/resolve-hint-macro.rs     |  7 +++
 src/test/ui/resolve/resolve-hint-macro.stderr | 45 +++++++++++++++++--
 6 files changed, 82 insertions(+), 24 deletions(-)
 create mode 100644 src/test/ui/resolve/resolve-hint-macro.fixed

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ccaaa2eaf4672..2c678e71ae179 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2517,6 +2517,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 self.visit_expr(elem);
                 self.resolve_anon_const(ct, IsRepeatExpr::Yes);
             }
+            ExprKind::Index(ref elem, ref idx) => {
+                self.resolve_expr(elem, Some(expr));
+                self.visit_expr(idx);
+            }
             _ => {
                 visit::walk_expr(self, expr);
             }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 4cd1b34bedc95..7b4fe6f0e07b3 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -970,7 +970,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         };
 
         match (res, source) {
-            (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
+            (
+                Res::Def(DefKind::Macro(MacroKind::Bang), _),
+                PathSource::Expr(Some(Expr {
+                    kind: ExprKind::Index(..) | ExprKind::Call(..), ..
+                }))
+                | PathSource::Struct,
+            ) => {
                 err.span_label(span, fallback_label);
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
@@ -982,6 +988,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     err.note("if you want the `try` keyword, you need Rust 2018 or later");
                 }
             }
+            (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
+                err.span_label(span, fallback_label);
+            }
             (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
                 err.span_label(span, "type aliases cannot be used as traits");
                 if self.r.session.is_nightly_build() {
diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr
index e4c1c8ad293b7..17d05dd09636c 100644
--- a/src/test/ui/hygiene/rustc-macro-transparency.stderr
+++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr
@@ -11,16 +11,10 @@ LL |     struct SemiTransparent;
    |     ----------------------- similarly named unit struct `SemiTransparent` defined here
 ...
 LL |     semitransparent;
-   |     ^^^^^^^^^^^^^^^ not a value
-   |
-help: use `!` to invoke the macro
-   |
-LL |     semitransparent!;
-   |                    +
-help: a unit struct with a similar name exists
-   |
-LL |     SemiTransparent;
-   |     ~~~~~~~~~~~~~~~
+   |     ^^^^^^^^^^^^^^^
+   |     |
+   |     not a value
+   |     help: a unit struct with a similar name exists: `SemiTransparent`
 
 error[E0423]: expected value, found macro `opaque`
   --> $DIR/rustc-macro-transparency.rs:30:5
@@ -29,16 +23,10 @@ LL |     struct Opaque;
    |     -------------- similarly named unit struct `Opaque` defined here
 ...
 LL |     opaque;
-   |     ^^^^^^ not a value
-   |
-help: use `!` to invoke the macro
-   |
-LL |     opaque!;
-   |           +
-help: a unit struct with a similar name exists
-   |
-LL |     Opaque;
-   |     ~~~~~~
+   |     ^^^^^^
+   |     |
+   |     not a value
+   |     help: a unit struct with a similar name exists (notice the capitalization): `Opaque`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/resolve/resolve-hint-macro.fixed b/src/test/ui/resolve/resolve-hint-macro.fixed
new file mode 100644
index 0000000000000..54e01608498f8
--- /dev/null
+++ b/src/test/ui/resolve/resolve-hint-macro.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+fn main() {
+    assert_eq!(1, 1);
+    //~^ ERROR expected function, found macro `assert_eq`
+    assert_eq! { 1, 1 };
+    //~^ ERROR expected struct, variant or union type, found macro `assert_eq`
+    //~| ERROR expected identifier, found `1`
+    //~| ERROR expected identifier, found `1`
+    assert![true];
+    //~^ ERROR expected value, found macro `assert`
+}
diff --git a/src/test/ui/resolve/resolve-hint-macro.rs b/src/test/ui/resolve/resolve-hint-macro.rs
index 5532c8b90e326..f16e8c0755384 100644
--- a/src/test/ui/resolve/resolve-hint-macro.rs
+++ b/src/test/ui/resolve/resolve-hint-macro.rs
@@ -1,4 +1,11 @@
+// run-rustfix
 fn main() {
     assert_eq(1, 1);
     //~^ ERROR expected function, found macro `assert_eq`
+    assert_eq { 1, 1 };
+    //~^ ERROR expected struct, variant or union type, found macro `assert_eq`
+    //~| ERROR expected identifier, found `1`
+    //~| ERROR expected identifier, found `1`
+    assert[true];
+    //~^ ERROR expected value, found macro `assert`
 }
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
index 78d77678083c3..bc69ddd8ffea2 100644
--- a/src/test/ui/resolve/resolve-hint-macro.stderr
+++ b/src/test/ui/resolve/resolve-hint-macro.stderr
@@ -1,5 +1,21 @@
+error: expected identifier, found `1`
+  --> $DIR/resolve-hint-macro.rs:5:17
+   |
+LL |     assert_eq { 1, 1 };
+   |     ---------   ^ expected identifier
+   |     |
+   |     while parsing this struct
+
+error: expected identifier, found `1`
+  --> $DIR/resolve-hint-macro.rs:5:20
+   |
+LL |     assert_eq { 1, 1 };
+   |     ---------      ^ expected identifier
+   |     |
+   |     while parsing this struct
+
 error[E0423]: expected function, found macro `assert_eq`
-  --> $DIR/resolve-hint-macro.rs:2:5
+  --> $DIR/resolve-hint-macro.rs:3:5
    |
 LL |     assert_eq(1, 1);
    |     ^^^^^^^^^ not a function
@@ -9,6 +25,29 @@ help: use `!` to invoke the macro
 LL |     assert_eq!(1, 1);
    |              +
 
-error: aborting due to previous error
+error[E0574]: expected struct, variant or union type, found macro `assert_eq`
+  --> $DIR/resolve-hint-macro.rs:5:5
+   |
+LL |     assert_eq { 1, 1 };
+   |     ^^^^^^^^^ not a struct, variant or union type
+   |
+help: use `!` to invoke the macro
+   |
+LL |     assert_eq! { 1, 1 };
+   |              +
+
+error[E0423]: expected value, found macro `assert`
+  --> $DIR/resolve-hint-macro.rs:9:5
+   |
+LL |     assert[true];
+   |     ^^^^^^ not a value
+   |
+help: use `!` to invoke the macro
+   |
+LL |     assert![true];
+   |           +
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0423`.
+Some errors have detailed explanations: E0423, E0574.
+For more information about an error, try `rustc --explain E0423`.