about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/messages.ftl7
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs23
-rw-r--r--compiler/rustc_resolve/src/errors.rs15
-rw-r--r--tests/ui/macros/issue-121061-defined-later-2.rs13
-rw-r--r--tests/ui/macros/issue-121061-defined-later-2.stderr14
-rw-r--r--tests/ui/macros/issue-121061-defined-later.rs9
-rw-r--r--tests/ui/macros/issue-121061-defined-later.stderr14
7 files changed, 94 insertions, 1 deletions
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 0747685c35c..c9463e59173 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -87,6 +87,10 @@ resolve_consider_declaring_with_pub =
 resolve_consider_marking_as_pub =
     consider marking `{$ident}` as `pub` in the imported module
 
+resolve_consider_move_macro_position =
+    consider moving the definition of `{$ident}` before this call
+
+
 resolve_const_not_member_of_trait =
     const `{$const_}` is not a member of trait `{$trait_}`
     .label = not a member of trait `{$trait_}`
@@ -186,6 +190,9 @@ resolve_lowercase_self =
     attempt to use a non-constant value in a constant
     .suggestion = try using `Self`
 
+resolve_macro_defined_later =
+    a macro with the same name exists, but it appears later at here
+
 resolve_macro_expected_found =
     expected {$expected}, found {$found} `{$macro_path}`
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e4298a98129..dfd2688457d 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -30,7 +30,10 @@ use rustc_span::{BytePos, Span, SyntaxContext};
 use thin_vec::{thin_vec, ThinVec};
 
 use crate::errors::{AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion};
-use crate::errors::{ConsiderAddingADerive, ExplicitUnsafeTraits, MaybeMissingMacroRulesName};
+use crate::errors::{
+    ConsiderAddingADerive, ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition,
+    MaybeMissingMacroRulesName,
+};
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::{errors as errs, BindingKey};
@@ -1456,6 +1459,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             return;
         }
 
+        let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
+            if unused_ident.name == ident.name {
+                Some((def_id.clone(), unused_ident.clone()))
+            } else {
+                None
+            }
+        });
+
+        if let Some((def_id, unused_ident)) = unused_macro {
+            let scope = self.local_macro_def_scopes[&def_id];
+            let parent_nearest = parent_scope.module.nearest_parent_mod();
+            if Some(parent_nearest) == scope.opt_def_id() {
+                err.subdiagnostic(self.dcx(), MacroDefinedLater { span: unused_ident.span });
+                err.subdiagnostic(self.dcx(), MacroSuggMovePosition { span: ident.span, ident });
+                return;
+            }
+        }
+
         if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
             err.subdiagnostic(self.dcx(), AddedMacroUse);
             return;
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index adc4cd911a7..b3f67e788d4 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -686,6 +686,21 @@ pub(crate) struct ExplicitUnsafeTraits {
 }
 
 #[derive(Subdiagnostic)]
+#[note(resolve_macro_defined_later)]
+pub(crate) struct MacroDefinedLater {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[label(resolve_consider_move_macro_position)]
+pub(crate) struct MacroSuggMovePosition {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
 #[note(resolve_missing_macro_rules_name)]
 pub(crate) struct MaybeMissingMacroRulesName {
     #[primary_span]
diff --git a/tests/ui/macros/issue-121061-defined-later-2.rs b/tests/ui/macros/issue-121061-defined-later-2.rs
new file mode 100644
index 00000000000..3db76c281ec
--- /dev/null
+++ b/tests/ui/macros/issue-121061-defined-later-2.rs
@@ -0,0 +1,13 @@
+mod demo {
+    fn hello() {
+        something_later!(); //~ ERROR cannot find macro `something_later` in this scope
+    }
+
+    macro_rules! something_later {
+        () => {
+            println!("successfully expanded!");
+        };
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/macros/issue-121061-defined-later-2.stderr b/tests/ui/macros/issue-121061-defined-later-2.stderr
new file mode 100644
index 00000000000..b42bd79170a
--- /dev/null
+++ b/tests/ui/macros/issue-121061-defined-later-2.stderr
@@ -0,0 +1,14 @@
+error: cannot find macro `something_later` in this scope
+  --> $DIR/issue-121061-defined-later-2.rs:3:9
+   |
+LL |         something_later!();
+   |         ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
+   |
+note: a macro with the same name exists, but it appears later at here
+  --> $DIR/issue-121061-defined-later-2.rs:6:18
+   |
+LL |     macro_rules! something_later {
+   |                  ^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/issue-121061-defined-later.rs b/tests/ui/macros/issue-121061-defined-later.rs
new file mode 100644
index 00000000000..07c6d406f03
--- /dev/null
+++ b/tests/ui/macros/issue-121061-defined-later.rs
@@ -0,0 +1,9 @@
+fn main() {
+    something_later!(); //~ ERROR cannot find macro `something_later` in this scope
+}
+
+macro_rules! something_later {
+    () => {
+        println!("successfully expanded!");
+    };
+}
diff --git a/tests/ui/macros/issue-121061-defined-later.stderr b/tests/ui/macros/issue-121061-defined-later.stderr
new file mode 100644
index 00000000000..abf48214201
--- /dev/null
+++ b/tests/ui/macros/issue-121061-defined-later.stderr
@@ -0,0 +1,14 @@
+error: cannot find macro `something_later` in this scope
+  --> $DIR/issue-121061-defined-later.rs:2:5
+   |
+LL |     something_later!();
+   |     ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call
+   |
+note: a macro with the same name exists, but it appears later at here
+  --> $DIR/issue-121061-defined-later.rs:5:14
+   |
+LL | macro_rules! something_later {
+   |              ^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+