Skip to content

Commit 36a27ec

Browse files
committed
Auto merge of rust-lang#79519 - cjgillot:noattr, r=wesleywiser
Store HIR attributes in a side table Same idea as rust-lang#72015 but for attributes. The objective is to reduce incr-comp invalidations due to modified attributes. Notably, those due to modified doc comments. Implementation: - collect attributes during AST->HIR lowering, in `LocalDefId -> ItemLocalId -> &[Attributes]` nested tables; - access the attributes through a `hir_owner_attrs` query; - local refactorings to use this access; - remove `attrs` from HIR data structures one-by-one. Change in behaviour: - the HIR visitor traverses all attributes at once instead of parent-by-parent; - attribute arrays are sometimes duplicated: for statements and variant constructors; - as a consequence, attributes are marked as used after unused-attribute lint emission to avoid duplicate lints. ~~Current bug: the lint level is not correctly applied in `std::backtrace_rs`, triggering an unused attribute warning on `#![no_std]`. I welcome suggestions.~~
2 parents cb8bc0b + 6c66826 commit 36a27ec

26 files changed

+103
-81
lines changed

clippy_lints/src/attrs.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
276276
}
277277

278278
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
279+
let attrs = cx.tcx.hir().attrs(item.hir_id());
279280
if is_relevant_item(cx, item) {
280-
check_attrs(cx, item.span, item.ident.name, &item.attrs)
281+
check_attrs(cx, item.span, item.ident.name, attrs)
281282
}
282283
match item.kind {
283284
ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
284-
let skip_unused_imports = item.attrs.iter().any(|attr| attr.has_name(sym::macro_use));
285+
let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
285286

286-
for attr in item.attrs {
287+
for attr in attrs {
287288
if in_external_macro(cx.sess(), attr.span) {
288289
return;
289290
}
@@ -353,13 +354,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
353354

354355
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
355356
if is_relevant_impl(cx, item) {
356-
check_attrs(cx, item.span, item.ident.name, &item.attrs)
357+
check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
357358
}
358359
}
359360

360361
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
361362
if is_relevant_trait(cx, item) {
362-
check_attrs(cx, item.span, item.ident.name, &item.attrs)
363+
check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
363364
}
364365
}
365366
}

clippy_lints/src/cognitive_complexity.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ impl CognitiveComplexity {
7676

7777
if rust_cc > self.limit.limit() {
7878
let fn_span = match kind {
79-
FnKind::ItemFn(ident, _, _, _, _) | FnKind::Method(ident, _, _, _) => ident.span,
80-
FnKind::Closure(_) => {
79+
FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
80+
FnKind::Closure => {
8181
let header_span = body_span.with_hi(decl.output.span().lo());
8282
let pos = snippet_opt(cx, header_span).and_then(|snip| {
8383
let low_offset = snip.find('|')?;

clippy_lints/src/derive.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
170170
}) = item.kind
171171
{
172172
let ty = cx.tcx.type_of(item.def_id);
173-
let is_automatically_derived = is_automatically_derived(&*item.attrs);
173+
let attrs = cx.tcx.hir().attrs(item.hir_id());
174+
let is_automatically_derived = is_automatically_derived(attrs);
174175

175176
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
176177
check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);

clippy_lints/src/doc.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,14 @@ impl_lint_pass!(DocMarkdown =>
208208
);
209209

210210
impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
211-
fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
212-
check_attrs(cx, &self.valid_idents, &krate.item.attrs);
211+
fn check_crate(&mut self, cx: &LateContext<'tcx>, _: &'tcx hir::Crate<'_>) {
212+
let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
213+
check_attrs(cx, &self.valid_idents, attrs);
213214
}
214215

215216
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
216-
let headers = check_attrs(cx, &self.valid_idents, &item.attrs);
217+
let attrs = cx.tcx.hir().attrs(item.hir_id());
218+
let headers = check_attrs(cx, &self.valid_idents, attrs);
217219
match item.kind {
218220
hir::ItemKind::Fn(ref sig, _, body_id) => {
219221
if !(is_entrypoint_fn(cx, item.def_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
@@ -249,7 +251,8 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
249251
}
250252

251253
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
252-
let headers = check_attrs(cx, &self.valid_idents, &item.attrs);
254+
let attrs = cx.tcx.hir().attrs(item.hir_id());
255+
let headers = check_attrs(cx, &self.valid_idents, attrs);
253256
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
254257
if !in_external_macro(cx.tcx.sess, item.span) {
255258
lint_for_missing_headers(cx, item.hir_id(), item.span, sig, headers, None, None);
@@ -258,7 +261,8 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
258261
}
259262

260263
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
261-
let headers = check_attrs(cx, &self.valid_idents, &item.attrs);
264+
let attrs = cx.tcx.hir().attrs(item.hir_id());
265+
let headers = check_attrs(cx, &self.valid_idents, attrs);
262266
if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) {
263267
return;
264268
}

clippy_lints/src/exhaustive_items.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ impl LateLintPass<'_> for ExhaustiveItems {
7373
if_chain! {
7474
if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind;
7575
if cx.access_levels.is_exported(item.hir_id());
76-
if !item.attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
76+
let attrs = cx.tcx.hir().attrs(item.hir_id());
77+
if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
7778
then {
7879
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
7980
if v.fields().iter().any(|f| !f.vis.node.is_pub()) {

clippy_lints/src/functions.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
251251
hir_id: hir::HirId,
252252
) {
253253
let unsafety = match kind {
254-
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _, _) => unsafety,
255-
intravisit::FnKind::Method(_, sig, _, _) => sig.header.unsafety,
256-
intravisit::FnKind::Closure(_) => return,
254+
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
255+
intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
256+
intravisit::FnKind::Closure => return,
257257
};
258258

259259
// don't warn for implementations, it's not their fault
@@ -267,9 +267,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
267267
..
268268
},
269269
_,
270-
_,
271270
)
272-
| intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => {
271+
| intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => {
273272
self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi()))
274273
},
275274
_ => {},
@@ -281,7 +280,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
281280
}
282281

283282
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
284-
let attr = must_use_attr(&item.attrs);
283+
let attrs = cx.tcx.hir().attrs(item.hir_id());
284+
let attr = must_use_attr(attrs);
285285
if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind {
286286
let is_public = cx.access_levels.is_exported(item.hir_id());
287287
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
@@ -292,7 +292,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
292292
check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
293293
return;
294294
}
295-
if is_public && !is_proc_macro(cx.sess(), &item.attrs) && attr_by_name(&item.attrs, "no_mangle").is_none() {
295+
if is_public && !is_proc_macro(cx.sess(), attrs) && attr_by_name(attrs, "no_mangle").is_none() {
296296
check_must_use_candidate(
297297
cx,
298298
&sig.decl,
@@ -313,11 +313,12 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
313313
if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() {
314314
check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
315315
}
316-
let attr = must_use_attr(&item.attrs);
316+
let attrs = cx.tcx.hir().attrs(item.hir_id());
317+
let attr = must_use_attr(attrs);
317318
if let Some(attr) = attr {
318319
check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
319320
} else if is_public
320-
&& !is_proc_macro(cx.sess(), &item.attrs)
321+
&& !is_proc_macro(cx.sess(), attrs)
321322
&& trait_ref_of_method(cx, item.hir_id()).is_none()
322323
{
323324
check_must_use_candidate(
@@ -345,15 +346,16 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
345346
check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
346347
}
347348

348-
let attr = must_use_attr(&item.attrs);
349+
let attrs = cx.tcx.hir().attrs(item.hir_id());
350+
let attr = must_use_attr(attrs);
349351
if let Some(attr) = attr {
350352
check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
351353
}
352354
if let hir::TraitFn::Provided(eid) = *eid {
353355
let body = cx.tcx.hir().body(eid);
354356
Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
355357

356-
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), &item.attrs) {
358+
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
357359
check_must_use_candidate(
358360
cx,
359361
&sig.decl,

clippy_lints/src/future_not_send.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
5858
_: Span,
5959
hir_id: HirId,
6060
) {
61-
if let FnKind::Closure(_) = kind {
61+
if let FnKind::Closure = kind {
6262
return;
6363
}
6464
let ret_ty = utils::return_ty(cx, hir_id);

clippy_lints/src/inline_fn_without_body.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]);
3434
impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
3535
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
3636
if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind {
37-
check_attrs(cx, item.ident.name, &item.attrs);
37+
let attrs = cx.tcx.hir().attrs(item.hir_id());
38+
check_attrs(cx, item.ident.name, attrs);
3839
}
3940
}
4041
}

clippy_lints/src/loops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
578578
// also check for empty `loop {}` statements, skipping those in #[panic_handler]
579579
if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) {
580580
let msg = "empty `loop {}` wastes CPU cycles";
581-
let help = if is_no_std_crate(cx.tcx.hir().krate()) {
581+
let help = if is_no_std_crate(cx) {
582582
"you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body"
583583
} else {
584584
"you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body"

clippy_lints/src/macro_use.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
107107
if_chain! {
108108
if cx.sess().opts.edition >= Edition::Edition2018;
109109
if let hir::ItemKind::Use(path, _kind) = &item.kind;
110-
if let Some(mac_attr) = item
111-
.attrs
110+
let attrs = cx.tcx.hir().attrs(item.hir_id());
111+
if let Some(mac_attr) = attrs
112112
.iter()
113113
.find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
114114
if let Res::Def(DefKind::Mod, id) = path.res;

0 commit comments

Comments
 (0)