Skip to content

Commit 63469ab

Browse files
committed
Add cargo update suggestion for non local defs
1 parent 85e3a2e commit 63469ab

File tree

6 files changed

+155
-52
lines changed

6 files changed

+155
-52
lines changed

compiler/rustc_lint/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ lint_non_fmt_panic_unused =
411411
}
412412
.add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
413413
414+
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}`
415+
414416
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>
415417
416418
lint_non_local_definitions_impl = non-local `impl` definition, they should be avoided as they go against expectation

compiler/rustc_lint/src/lints.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,8 @@ pub enum NonLocalDefinitionsDiag {
13051305
depth: u32,
13061306
body_kind_descr: &'static str,
13071307
body_name: String,
1308+
#[subdiagnostic]
1309+
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
13081310
#[suggestion(lint_const_anon, code = "_", applicability = "machine-applicable")]
13091311
const_anon: Option<Span>,
13101312
},
@@ -1313,7 +1315,21 @@ pub enum NonLocalDefinitionsDiag {
13131315
#[note(lint_non_local)]
13141316
#[note(lint_exception)]
13151317
#[note(lint_non_local_definitions_deprecation)]
1316-
MacroRules { depth: u32, body_kind_descr: &'static str, body_name: String },
1318+
MacroRules {
1319+
depth: u32,
1320+
body_kind_descr: &'static str,
1321+
body_name: String,
1322+
#[subdiagnostic]
1323+
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1324+
},
1325+
}
1326+
1327+
#[derive(Subdiagnostic)]
1328+
#[note(lint_non_local_definitions_cargo_update)]
1329+
pub struct NonLocalDefinitionsCargoUpdateNote {
1330+
pub macro_kind: &'static str,
1331+
pub macro_name: Symbol,
1332+
pub crate_name: Symbol,
13171333
}
13181334

13191335
// pass_by_value.rs

compiler/rustc_lint/src/non_local_def.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind};
2-
use rustc_span::{def_id::DefId, sym, symbol::kw, MacroKind};
2+
use rustc_span::def_id::{DefId, LOCAL_CRATE};
3+
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
34

45
use smallvec::{smallvec, SmallVec};
56

6-
use crate::{lints::NonLocalDefinitionsDiag, LateContext, LateLintPass, LintContext};
7+
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
8+
use crate::{LateContext, LateLintPass, LintContext};
79

810
declare_lint! {
911
/// The `non_local_definitions` lint checks for `impl` blocks and `#[macro_export]`
@@ -77,6 +79,23 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
7779
return;
7880
}
7981

82+
let cargo_update = || {
83+
let oexpn = item.span.ctxt().outer_expn_data();
84+
if let Some(def_id) = oexpn.macro_def_id
85+
&& let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind
86+
&& def_id.krate != LOCAL_CRATE
87+
&& std::env::var_os("CARGO").is_some()
88+
{
89+
Some(NonLocalDefinitionsCargoUpdateNote {
90+
macro_kind: macro_kind.descr(),
91+
macro_name,
92+
crate_name: cx.tcx.crate_name(def_id.krate),
93+
})
94+
} else {
95+
None
96+
}
97+
};
98+
8099
match item.kind {
81100
ItemKind::Impl(impl_) => {
82101
// The RFC states:
@@ -162,6 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
162181
body_name: parent_opt_item_name
163182
.map(|s| s.to_ident_string())
164183
.unwrap_or_else(|| "<unnameable>".to_string()),
184+
cargo_update: cargo_update(),
165185
const_anon,
166186
},
167187
)
@@ -179,6 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
179199
body_name: parent_opt_item_name
180200
.map(|s| s.to_ident_string())
181201
.unwrap_or_else(|| "<unnameable>".to_string()),
202+
cargo_update: cargo_update(),
182203
},
183204
)
184205
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[macro_export]
2+
macro_rules! non_local_impl {
3+
($a:ident) => {
4+
const _IMPL_DEBUG: () = {
5+
impl ::std::fmt::Debug for $a {
6+
fn fmt(&self, _: &mut ::std::fmt::Formatter<'_>)
7+
-> ::std::result::Result<(), ::std::fmt::Error>
8+
{
9+
todo!()
10+
}
11+
}
12+
};
13+
}
14+
}
15+
16+
#[macro_export]
17+
macro_rules! non_local_macro_rules {
18+
($a:ident) => {
19+
const _MACRO_EXPORT: () = {
20+
#[macro_export]
21+
macro_rules! $a {
22+
() => {}
23+
}
24+
};
25+
}
26+
}

tests/ui/lint/non_local_definitions.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
//@ check-pass
22
//@ edition:2021
3+
//@ aux-build:non_local_macro.rs
4+
//@ rustc-env:CARGO=/usr/bin/cargo
35

46
#![feature(inline_const)]
57

8+
extern crate non_local_macro;
9+
610
use std::fmt::{Debug, Display};
711

812
struct Test;
@@ -364,6 +368,14 @@ macro_rules! m {
364368

365369
m!();
366370

371+
struct CargoUpdate;
372+
373+
non_local_macro::non_local_impl!(CargoUpdate);
374+
//~^ WARN non-local `impl` definition
375+
376+
non_local_macro::non_local_macro_rules!(my_macro);
377+
//~^ WARN non-local `macro_rules!` definition
378+
367379
fn bitflags() {
368380
struct Flags;
369381

0 commit comments

Comments
 (0)