diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index dbe24c9cdf24c..679367634276d 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -630,7 +630,8 @@ lint_opaque_hidden_inferred_bound_sugg = add this bound lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro .suggestion = use pat_param to preserve semantics -lint_out_of_scope_macro_calls = cannot find macro `{$path}` in this scope +lint_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location} + .label = not found from {$location} .help = import `macro_rules` with `use` to make it callable above its definition lint_overflowing_bin_hex = literal out of range for `{$ty}` diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index aeb5a03a4f7e3..40ca9e05d95d6 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -444,8 +444,8 @@ pub(super) fn decorate_lint( lints::InnerAttributeUnstable::CustomInnerAttribute } .decorate_lint(diag), - BuiltinLintDiag::OutOfScopeMacroCalls { path } => { - lints::OutOfScopeMacroCalls { path }.decorate_lint(diag) + BuiltinLintDiag::OutOfScopeMacroCalls { span, path, location } => { + lints::OutOfScopeMacroCalls { span, path, location }.decorate_lint(diag) } BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 368d36bfdd0b2..0058630957291 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3108,7 +3108,10 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[diag(lint_out_of_scope_macro_calls)] #[help] pub(crate) struct OutOfScopeMacroCalls { + #[label] + pub span: Span, pub path: String, + pub location: String, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7ffe4e4e4901c..66fdba28502bd 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -819,7 +819,9 @@ pub enum BuiltinLintDiag { is_macro: bool, }, OutOfScopeMacroCalls { + span: Span, path: String, + location: String, }, UnexpectedBuiltinCfg { cfg: String, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index cca01a01e9877..a70def2f6c93c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -857,8 +857,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ), path_res @ (PathResult::NonModule(..) | PathResult::Failed { .. }) => { let mut suggestion = None; - let (span, label, module) = - if let PathResult::Failed { span, label, module, .. } = path_res { + let (span, label, module, segment) = + if let PathResult::Failed { span, label, module, segment_name, .. } = + path_res + { // try to suggest if it's not a macro, maybe a function if let PathResult::NonModule(partial_res) = self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None) @@ -876,7 +878,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Applicability::MaybeIncorrect, )); } - (span, label, module) + (span, label, module, segment_name) } else { ( path_span, @@ -886,12 +888,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { kind.descr() ), None, + path.last().map(|segment| segment.ident.name).unwrap(), ) }; self.report_error( span, ResolutionError::FailedToResolve { - segment: path.last().map(|segment| segment.ident.name), + segment: Some(segment), label, suggestion, module, @@ -1067,11 +1070,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, ); if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) { + let location = match parent_scope.module.kind { + ModuleKind::Def(_, _, name) if name == kw::Empty => { + "the crate root".to_string() + } + ModuleKind::Def(kind, def_id, name) => { + format!("{} `{name}`", kind.descr(def_id)) + } + ModuleKind::Block => "this scope".to_string(), + }; self.tcx.sess.psess.buffer_lint( OUT_OF_SCOPE_MACRO_CALLS, path.span, node_id, - BuiltinLintDiag::OutOfScopeMacroCalls { path: pprust::path_to_string(path) }, + BuiltinLintDiag::OutOfScopeMacroCalls { + span: path.span, + path: pprust::path_to_string(path), + location, + }, ); } } diff --git a/tests/ui/attributes/key-value-expansion-scope.rs b/tests/ui/attributes/key-value-expansion-scope.rs index b6eab1571d490..49a59502377f5 100644 --- a/tests/ui/attributes/key-value-expansion-scope.rs +++ b/tests/ui/attributes/key-value-expansion-scope.rs @@ -1,7 +1,7 @@ -#![doc = in_root!()] //~ WARN cannot find macro `in_root` in this scope +#![doc = in_root!()] //~ WARN cannot find macro `in_root` //~| WARN this was previously accepted by the compiler #![doc = in_mod!()] //~ ERROR cannot find macro `in_mod` in this scope -#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope +#![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` //~| WARN this was previously accepted by the compiler #![doc = in_block!()] //~ ERROR cannot find macro `in_block` in this scope @@ -18,10 +18,10 @@ fn before() { macro_rules! in_root { () => { "" } } -#[doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope +#[doc = in_mod!()] //~ WARN cannot find macro `in_mod` //~| WARN this was previously accepted by the compiler mod macros_stay { - #![doc = in_mod!()] //~ WARN cannot find macro `in_mod` in this scope + #![doc = in_mod!()] //~ WARN cannot find macro `in_mod` //~| WARN this was previously accepted by the compiler macro_rules! in_mod { () => { "" } } @@ -33,10 +33,10 @@ mod macros_stay { } #[macro_use] -#[doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope +#[doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` //~| WARN this was previously accepted by the compiler mod macros_escape { - #![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` in this scope + #![doc = in_mod_escape!()] //~ WARN cannot find macro `in_mod_escape` //~| WARN this was previously accepted by the compiler macro_rules! in_mod_escape { () => { "" } } diff --git a/tests/ui/attributes/key-value-expansion-scope.stderr b/tests/ui/attributes/key-value-expansion-scope.stderr index d22fef7dd251e..91a602e57d9e4 100644 --- a/tests/ui/attributes/key-value-expansion-scope.stderr +++ b/tests/ui/attributes/key-value-expansion-scope.stderr @@ -126,62 +126,62 @@ LL | #![doc = in_block!()] | = help: have you added the `#[macro_use]` on the module/import? -warning: cannot find macro `in_root` in this scope +warning: cannot find macro `in_root` in the current scope when looking from the crate root --> $DIR/key-value-expansion-scope.rs:1:10 | LL | #![doc = in_root!()] - | ^^^^^^^ + | ^^^^^^^ not found from the crate root | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124535 = help: import `macro_rules` with `use` to make it callable above its definition = note: `#[warn(out_of_scope_macro_calls)]` on by default -warning: cannot find macro `in_mod_escape` in this scope +warning: cannot find macro `in_mod_escape` in the current scope when looking from the crate root --> $DIR/key-value-expansion-scope.rs:4:10 | LL | #![doc = in_mod_escape!()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ not found from the crate root | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124535 = help: import `macro_rules` with `use` to make it callable above its definition -warning: cannot find macro `in_mod` in this scope +warning: cannot find macro `in_mod` in the current scope when looking from module `macros_stay` --> $DIR/key-value-expansion-scope.rs:21:9 | LL | #[doc = in_mod!()] - | ^^^^^^ + | ^^^^^^ not found from module `macros_stay` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124535 = help: import `macro_rules` with `use` to make it callable above its definition -warning: cannot find macro `in_mod` in this scope +warning: cannot find macro `in_mod` in the current scope when looking from module `macros_stay` --> $DIR/key-value-expansion-scope.rs:24:14 | LL | #![doc = in_mod!()] - | ^^^^^^ + | ^^^^^^ not found from module `macros_stay` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124535 = help: import `macro_rules` with `use` to make it callable above its definition -warning: cannot find macro `in_mod_escape` in this scope +warning: cannot find macro `in_mod_escape` in the current scope when looking from module `macros_escape` --> $DIR/key-value-expansion-scope.rs:36:9 | LL | #[doc = in_mod_escape!()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ not found from module `macros_escape` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124535 = help: import `macro_rules` with `use` to make it callable above its definition -warning: cannot find macro `in_mod_escape` in this scope +warning: cannot find macro `in_mod_escape` in the current scope when looking from module `macros_escape` --> $DIR/key-value-expansion-scope.rs:39:14 | LL | #![doc = in_mod_escape!()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ not found from module `macros_escape` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124535