diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 0747685c35c46..c9463e5917366 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 e4298a981292a..dfd2688457d55 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 adc4cd911a79e..b3f67e788d4f5 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -685,6 +685,21 @@ pub(crate) struct ExplicitUnsafeTraits { pub(crate) ident: Ident, } +#[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 { diff --git a/tests/ui/macros/defined-later-issue-121061-2.rs b/tests/ui/macros/defined-later-issue-121061-2.rs new file mode 100644 index 0000000000000..3db76c281ec87 --- /dev/null +++ b/tests/ui/macros/defined-later-issue-121061-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/defined-later-issue-121061-2.stderr b/tests/ui/macros/defined-later-issue-121061-2.stderr new file mode 100644 index 0000000000000..aa6ef33853193 --- /dev/null +++ b/tests/ui/macros/defined-later-issue-121061-2.stderr @@ -0,0 +1,14 @@ +error: cannot find macro `something_later` in this scope + --> $DIR/defined-later-issue-121061-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/defined-later-issue-121061-2.rs:6:18 + | +LL | macro_rules! something_later { + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/defined-later-issue-121061.rs b/tests/ui/macros/defined-later-issue-121061.rs new file mode 100644 index 0000000000000..07c6d406f03c5 --- /dev/null +++ b/tests/ui/macros/defined-later-issue-121061.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/defined-later-issue-121061.stderr b/tests/ui/macros/defined-later-issue-121061.stderr new file mode 100644 index 0000000000000..65cb53432a932 --- /dev/null +++ b/tests/ui/macros/defined-later-issue-121061.stderr @@ -0,0 +1,14 @@ +error: cannot find macro `something_later` in this scope + --> $DIR/defined-later-issue-121061.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/defined-later-issue-121061.rs:5:14 + | +LL | macro_rules! something_later { + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +