Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ae4900c

Browse files
committed
Fix #[expect] for clippy::macro_use_imports
1 parent 79fc271 commit ae4900c

File tree

5 files changed

+85
-24
lines changed

5 files changed

+85
-24
lines changed

clippy_lints/src/macro_use.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::span_lint_and_sugg;
1+
use clippy_utils::diagnostics::span_lint_hir_and_then;
22
use clippy_utils::source::snippet;
33
use hir::def::{DefKind, Res};
44
use if_chain::if_chain;
@@ -51,8 +51,9 @@ impl MacroRefData {
5151
#[derive(Default)]
5252
#[expect(clippy::module_name_repetitions)]
5353
pub struct MacroUseImports {
54-
/// the actual import path used and the span of the attribute above it.
55-
imports: Vec<(String, Span)>,
54+
/// the actual import path used and the span of the attribute above it. The value is
55+
/// the location, where the lint should be emitted.
56+
imports: Vec<(String, Span, hir::HirId)>,
5657
/// the span of the macro reference, kept to ensure only one reference is used per macro call.
5758
collected: FxHashSet<Span>,
5859
mac_refs: Vec<MacroRefData>,
@@ -91,7 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
9192
if_chain! {
9293
if cx.sess().opts.edition >= Edition::Edition2018;
9394
if let hir::ItemKind::Use(path, _kind) = &item.kind;
94-
let attrs = cx.tcx.hir().attrs(item.hir_id());
95+
let hir_id = item.hir_id();
96+
let attrs = cx.tcx.hir().attrs(hir_id);
9597
if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use));
9698
if let Res::Def(DefKind::Mod, id) = path.res;
9799
if !id.is_local();
@@ -100,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
100102
if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
101103
let span = mac_attr.span;
102104
let def_path = cx.tcx.def_path_str(mac_id);
103-
self.imports.push((def_path, span));
105+
self.imports.push((def_path, span, hir_id));
104106
}
105107
}
106108
} else {
@@ -138,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
138140
fn check_crate_post(&mut self, cx: &LateContext<'_>) {
139141
let mut used = FxHashMap::default();
140142
let mut check_dup = vec![];
141-
for (import, span) in &self.imports {
143+
for (import, span, hir_id) in &self.imports {
142144
let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name));
143145

144146
if let Some(idx) = found_idx {
@@ -151,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
151153
[] | [_] => return,
152154
[root, item] => {
153155
if !check_dup.contains(&(*item).to_string()) {
154-
used.entry(((*root).to_string(), span))
156+
used.entry(((*root).to_string(), span, hir_id))
155157
.or_insert_with(Vec::new)
156158
.push((*item).to_string());
157159
check_dup.push((*item).to_string());
@@ -169,13 +171,13 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
169171
}
170172
})
171173
.collect::<Vec<_>>();
172-
used.entry(((*root).to_string(), span))
174+
used.entry(((*root).to_string(), span, hir_id))
173175
.or_insert_with(Vec::new)
174176
.push(filtered.join("::"));
175177
check_dup.extend(filtered);
176178
} else {
177179
let rest = rest.to_vec();
178-
used.entry(((*root).to_string(), span))
180+
used.entry(((*root).to_string(), span, hir_id))
179181
.or_insert_with(Vec::new)
180182
.push(rest.join("::"));
181183
check_dup.extend(rest.iter().map(ToString::to_string));
@@ -186,27 +188,33 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
186188
}
187189

188190
let mut suggestions = vec![];
189-
for ((root, span), path) in used {
191+
for ((root, span, hir_id), path) in used {
190192
if path.len() == 1 {
191-
suggestions.push((span, format!("{}::{}", root, path[0])));
193+
suggestions.push((span, format!("{}::{}", root, path[0]), hir_id));
192194
} else {
193-
suggestions.push((span, format!("{}::{{{}}}", root, path.join(", "))));
195+
suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")), hir_id));
194196
}
195197
}
196198

197199
// If mac_refs is not empty we have encountered an import we could not handle
198200
// such as `std::prelude::v1::foo` or some other macro that expands to an import.
199201
if self.mac_refs.is_empty() {
200-
for (span, import) in suggestions {
202+
for (span, import, hir_id) in suggestions {
201203
let help = format!("use {};", import);
202-
span_lint_and_sugg(
204+
span_lint_hir_and_then(
203205
cx,
204206
MACRO_USE_IMPORTS,
207+
*hir_id,
205208
*span,
206209
"`macro_use` attributes are no longer needed in the Rust 2018 edition",
207-
"remove the attribute and import the macro directly, try",
208-
help,
209-
Applicability::MaybeIncorrect,
210+
|diag| {
211+
diag.span_suggestion(
212+
*span,
213+
"remove the attribute and import the macro directly, try",
214+
help,
215+
Applicability::MaybeIncorrect,
216+
);
217+
},
210218
);
211219
}
212220
}

tests/ui/macro_use_imports.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// run-rustfix
55
// ignore-32bit
66

7+
#![feature(lint_reasons)]
78
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
89
#![allow(clippy::single_component_path_imports)]
910
#![warn(clippy::macro_use_imports)]

tests/ui/macro_use_imports.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// run-rustfix
55
// ignore-32bit
66

7+
#![feature(lint_reasons)]
78
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
89
#![allow(clippy::single_component_path_imports)]
910
#![warn(clippy::macro_use_imports)]

tests/ui/macro_use_imports.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
2-
--> $DIR/macro_use_imports.rs:18:5
2+
--> $DIR/macro_use_imports.rs:23:5
33
|
44
LL | #[macro_use]
5-
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};`
5+
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
66
|
77
= note: `-D clippy::macro-use-imports` implied by `-D warnings`
88

99
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
10-
--> $DIR/macro_use_imports.rs:20:5
10+
--> $DIR/macro_use_imports.rs:21:5
1111
|
1212
LL | #[macro_use]
1313
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
1414

1515
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
16-
--> $DIR/macro_use_imports.rs:22:5
16+
--> $DIR/macro_use_imports.rs:25:5
1717
|
1818
LL | #[macro_use]
19-
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
19+
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
2020

2121
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
22-
--> $DIR/macro_use_imports.rs:24:5
22+
--> $DIR/macro_use_imports.rs:19:5
2323
|
2424
LL | #[macro_use]
25-
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
25+
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};`
2626

2727
error: aborting due to 4 previous errors
2828

tests/ui/macro_use_imports_expect.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// aux-build:macro_rules.rs
2+
// aux-build:macro_use_helper.rs
3+
// aux-build:proc_macro_derive.rs
4+
// ignore-32bit
5+
6+
#![feature(lint_reasons)]
7+
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
8+
#![allow(clippy::single_component_path_imports)]
9+
#![warn(clippy::macro_use_imports)]
10+
11+
#[macro_use]
12+
extern crate macro_use_helper as mac;
13+
14+
#[macro_use]
15+
extern crate proc_macro_derive as mini_mac;
16+
17+
mod a {
18+
#[expect(clippy::macro_use_imports)]
19+
#[macro_use]
20+
use mac;
21+
#[expect(clippy::macro_use_imports)]
22+
#[macro_use]
23+
use mini_mac;
24+
#[expect(clippy::macro_use_imports)]
25+
#[macro_use]
26+
use mac::inner;
27+
#[expect(clippy::macro_use_imports)]
28+
#[macro_use]
29+
use mac::inner::nested;
30+
31+
#[derive(ClippyMiniMacroTest)]
32+
struct Test;
33+
34+
fn test() {
35+
pub_macro!();
36+
inner_mod_macro!();
37+
pub_in_private_macro!(_var);
38+
function_macro!();
39+
let v: ty_macro!() = Vec::default();
40+
41+
inner::try_err!();
42+
inner::foofoo!();
43+
nested::string_add!();
44+
}
45+
}
46+
47+
// issue #7015, ICE due to calling `module_children` with local `DefId`
48+
#[macro_use]
49+
use a as b;
50+
51+
fn main() {}

0 commit comments

Comments
 (0)