about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-02-15 20:33:30 +0100
committerUrgau <urgau@numericable.fr>2024-02-17 14:00:08 +0100
commit63469ab762b5710b07418e61ff758bd48d0f8b3e (patch)
tree0f16c44a274fc694d07223eb456734caa5e4d090 /compiler
parent85e3a2ee043f6404561a9fbed799c07d83f305ce (diff)
downloadrust-63469ab762b5710b07418e61ff758bd48d0f8b3e.tar.gz
rust-63469ab762b5710b07418e61ff758bd48d0f8b3e.zip
Add cargo update suggestion for non local defs
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/lints.rs18
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs25
3 files changed, 42 insertions, 3 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index ca3941c06f4..3f7abebf7b9 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -411,6 +411,8 @@ lint_non_fmt_panic_unused =
     }
     .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
 
+lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`
+
 lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 lint_non_local_definitions_impl = non-local `impl` definition, they should be avoided as they go against expectation
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 1a56fa751c2..3a795205059 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1305,6 +1305,8 @@ pub enum NonLocalDefinitionsDiag {
         depth: u32,
         body_kind_descr: &'static str,
         body_name: String,
+        #[subdiagnostic]
+        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
         #[suggestion(lint_const_anon, code = "_", applicability = "machine-applicable")]
         const_anon: Option<Span>,
     },
@@ -1313,7 +1315,21 @@ pub enum NonLocalDefinitionsDiag {
     #[note(lint_non_local)]
     #[note(lint_exception)]
     #[note(lint_non_local_definitions_deprecation)]
-    MacroRules { depth: u32, body_kind_descr: &'static str, body_name: String },
+    MacroRules {
+        depth: u32,
+        body_kind_descr: &'static str,
+        body_name: String,
+        #[subdiagnostic]
+        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[note(lint_non_local_definitions_cargo_update)]
+pub struct NonLocalDefinitionsCargoUpdateNote {
+    pub macro_kind: &'static str,
+    pub macro_name: Symbol,
+    pub crate_name: Symbol,
 }
 
 // pass_by_value.rs
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index bfd7b4a72f9..6cb6fd1cbd5 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -1,9 +1,11 @@
 use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind};
-use rustc_span::{def_id::DefId, sym, symbol::kw, MacroKind};
+use rustc_span::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
 
 use smallvec::{smallvec, SmallVec};
 
-use crate::{lints::NonLocalDefinitionsDiag, LateContext, LateLintPass, LintContext};
+use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
+use crate::{LateContext, LateLintPass, LintContext};
 
 declare_lint! {
     /// The `non_local_definitions` lint checks for `impl` blocks and `#[macro_export]`
@@ -77,6 +79,23 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
             return;
         }
 
+        let cargo_update = || {
+            let oexpn = item.span.ctxt().outer_expn_data();
+            if let Some(def_id) = oexpn.macro_def_id
+                && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind
+                && def_id.krate != LOCAL_CRATE
+                && std::env::var_os("CARGO").is_some()
+            {
+                Some(NonLocalDefinitionsCargoUpdateNote {
+                    macro_kind: macro_kind.descr(),
+                    macro_name,
+                    crate_name: cx.tcx.crate_name(def_id.krate),
+                })
+            } else {
+                None
+            }
+        };
+
         match item.kind {
             ItemKind::Impl(impl_) => {
                 // The RFC states:
@@ -162,6 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                             body_name: parent_opt_item_name
                                 .map(|s| s.to_ident_string())
                                 .unwrap_or_else(|| "<unnameable>".to_string()),
+                            cargo_update: cargo_update(),
                             const_anon,
                         },
                     )
@@ -179,6 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                         body_name: parent_opt_item_name
                             .map(|s| s.to_ident_string())
                             .unwrap_or_else(|| "<unnameable>".to_string()),
+                        cargo_update: cargo_update(),
                     },
                 )
             }