diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index ad4c9aa5ff9bd..0b5065f12f805 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -37,7 +37,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness { } } Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => { - if find_attr!(tcx.hir_attrs(ti.hir_id()), RustcNonConstTraitMethod) { + if find_attr!(tcx, ti.hir_id(), RustcNonConstTraitMethod) { Constness::NotConst } else { tcx.trait_def(tcx.local_parent(def_id)).constness diff --git a/compiler/rustc_hir/src/attrs/mod.rs b/compiler/rustc_hir/src/attrs/mod.rs index 09fa144a16041..b3c1deaa48fa8 100644 --- a/compiler/rustc_hir/src/attrs/mod.rs +++ b/compiler/rustc_hir/src/attrs/mod.rs @@ -13,6 +13,15 @@ pub mod diagnostic; mod encode_cross_crate; mod pretty_printing; +/// A trait for types that can provide a list of attributes given a `TyCtxt`. +/// +/// It allows `find_attr!` to accept either a `DefId`, `LocalDefId`, `OwnerId`, or `HirId`. +/// It is defined here with a generic `Tcx` because `rustc_hir` can't depend on `rustc_middle`. +/// The concrete implementations are in `rustc_middle`. +pub trait HasAttrs<'tcx, Tcx> { + fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::Attribute]; +} + /// Finds attributes in sequences of attributes by pattern matching. /// /// A little like `matches` but for attributes. @@ -34,10 +43,12 @@ mod pretty_printing; /// /// As a convenience, this macro can do that for you! /// -/// Instead of providing an attribute list, provide the `tcx` and a `DefId`. +/// Instead of providing an attribute list, provide the `tcx` and an id +/// (a `DefId`, `LocalDefId`, `OwnerId` or `HirId`). /// /// ```rust,ignore (illustrative) /// find_attr!(tcx, def_id, ) +/// find_attr!(tcx, hir_id, ) /// ``` /// /// Another common case is finding attributes applied to the root of the current crate. @@ -55,13 +66,14 @@ macro_rules! find_attr { $crate::find_attr!($tcx.hir_krate_attrs(), $pattern $(if $guard)? => $e) }; - ($tcx: expr, $def_id: expr, $pattern: pat $(if $guard: expr)?) => { - $crate::find_attr!($tcx, $def_id, $pattern $(if $guard)? => ()).is_some() + ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)?) => { + $crate::find_attr!($tcx, $id, $pattern $(if $guard)? => ()).is_some() }; - ($tcx: expr, $def_id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ - #[allow(deprecated)] { - $crate::find_attr!($tcx.get_all_attrs($def_id), $pattern $(if $guard)? => $e) - } + ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ + $crate::find_attr!( + $crate::attrs::HasAttrs::get_attrs($id, &$tcx), + $pattern $(if $guard)? => $e + ) }}; diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index e77c93641e1a6..21b408064fac5 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -207,7 +207,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { }; // A `#[const_continue]` must break to a block in a `#[loop_match]`. - if find_attr!(self.tcx.hir_attrs(e.hir_id), ConstContinue(_)) { + if find_attr!(self.tcx, e.hir_id, ConstContinue(_)) { let Some(label) = break_destination.label else { let span = e.span; self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span }); @@ -420,7 +420,7 @@ impl<'hir> CheckLoopVisitor<'hir> { e: &'hir hir::Expr<'hir>, body: &'hir hir::Block<'hir>, ) -> Option { - if !find_attr!(self.tcx.hir_attrs(e.hir_id), LoopMatch(_)) { + if !find_attr!(self.tcx, e.hir_id, LoopMatch(_)) { return None; } diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 63fed51b020a9..eb60c61b0af71 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -7,7 +7,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { let mut decls = None; for id in tcx.hir_free_items() { - if find_attr!(tcx.hir_attrs(id.hir_id()), RustcProcMacroDecls) { + if find_attr!(tcx, id.hir_id(), RustcProcMacroDecls) { decls = Some(id.owner_id.def_id); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6abe7d1466990..282d566a4a94a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2199,6 +2199,36 @@ impl<'tcx> TyCtxt<'tcx> { } } +// `HasAttrs` impls: allow `find_attr!(tcx, id, ...)` to work with both DefId-like types and HirId. + +impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for DefId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] { + if let Some(did) = self.as_local() { + tcx.hir_attrs(tcx.local_def_id_to_hir_id(did)) + } else { + tcx.attrs_for_def(self) + } + } +} + +impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for LocalDefId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] { + tcx.hir_attrs(tcx.local_def_id_to_hir_id(self)) + } +} + +impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::OwnerId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] { + hir::attrs::HasAttrs::get_attrs(self.def_id, tcx) + } +} + +impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::HirId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] { + tcx.hir_attrs(self) + } +} + pub fn provide(providers: &mut Providers) { closure::provide(providers); context::provide(providers); diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index bcac45199437c..01c1e2e79b501 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -491,7 +491,7 @@ fn construct_fn<'tcx>( }; if let Some((dialect, phase)) = - find_attr!(tcx.hir_attrs(fn_id), CustomMir(dialect, phase, _) => (dialect, phase)) + find_attr!(tcx, fn_id, CustomMir(dialect, phase, _) => (dialect, phase)) { return custom::build_custom_mir( tcx, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index c5eeb8b1aa856..b868fa7984b60 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -873,7 +873,7 @@ impl<'tcx> ThirBuildCx<'tcx> { hir::ExprKind::Ret(v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) }, hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) }, hir::ExprKind::Break(dest, ref value) => { - if find_attr!(self.tcx.hir_attrs(expr.hir_id), ConstContinue(_)) { + if find_attr!(self.tcx, expr.hir_id, ConstContinue(_)) { match dest.target_id { Ok(target_id) => { let (Some(value), Some(_)) = (value, dest.label) else { @@ -938,7 +938,7 @@ impl<'tcx> ThirBuildCx<'tcx> { match_source, }, hir::ExprKind::Loop(body, ..) => { - if find_attr!(self.tcx.hir_attrs(expr.hir_id), LoopMatch(_)) { + if find_attr!(self.tcx, expr.hir_id, LoopMatch(_)) { let dcx = self.tcx.dcx(); // Accept either `state = expr` or `state = expr;`. diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 60cb509ee9dd2..e3bba5d2f9356 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -104,7 +104,7 @@ impl<'tcx> ThirBuildCx<'tcx> { typing_env: ty::TypingEnv::non_body_analysis(tcx, def), typeck_results, body_owner: def.to_def_id(), - apply_adjustments: !find_attr!(tcx.hir_attrs(hir_id), CustomMir(..) => ()).is_some(), + apply_adjustments: !find_attr!(tcx, hir_id, CustomMir(..)), } } diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 04c657104fe1d..7c1b3ef225c6a 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -24,7 +24,7 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason)); + let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason)); if let hir::ItemKind::Fn { ref sig, body: ref body_id, @@ -65,7 +65,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason)); + let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason)); if let Some((attr_span, reason)) = attr { check_needless_must_use( cx, @@ -98,7 +98,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); - let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason)); + let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason)); if let Some((attr_span, reason)) = attr { check_needless_must_use( cx, diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index ad81810b58cb9..1ae8198a432dd 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -269,5 +269,5 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool { cx.tcx .hir_parent_id_iter(hir_id) - .any(|id| find_attr!(cx.tcx.hir_attrs(id), CfgTrace(..) | CfgAttrTrace)) + .any(|id| find_attr!(cx.tcx, id, CfgTrace(..) | CfgAttrTrace)) } diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 9ababe87f9dec..703c9137d5437 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { .then_some((v.def_id, v.span)) }); if let Ok((id, span)) = iter.exactly_one() - && !find_attr!(cx.tcx.hir_attrs(item.hir_id()), NonExhaustive(..)) + && !find_attr!(cx.tcx, item.hir_id(), NonExhaustive(..)) { self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } @@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { "this seems like a manual implementation of the non-exhaustive pattern", |diag| { if let Some(non_exhaustive_span) = - find_attr!(cx.tcx.hir_attrs(item.hir_id()), NonExhaustive(span) => *span) + find_attr!(cx.tcx, item.hir_id(), NonExhaustive(span) => *span) { diag.span_note(non_exhaustive_span, "the struct is already non-exhaustive"); } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs index 4577be34d4a77..cfda39ed08ff1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs @@ -39,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { cx.tcx .hir_parent_id_iter(id) - .any(|id| find_attr!(cx.tcx.hir_attrs(id), CfgTrace(..))) + .any(|id| find_attr!(cx.tcx, id, CfgTrace(..))) } /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1e73e43e0a719..ac66b1e5338d6 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1710,7 +1710,7 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { } pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - find_attr!(cx.tcx.hir_attrs(hir_id), Repr { .. }) + find_attr!(cx.tcx, hir_id, Repr { .. }) } pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool { @@ -2362,7 +2362,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(& && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind // We could also check for the type name `test::TestDescAndFn` && let Res::Def(DefKind::Struct, _) = path.res - && find_attr!(tcx.hir_attrs(item.hir_id()), RustcTestMarker(..)) + && find_attr!(tcx, item.hir_id(), RustcTestMarker(..)) { names.push(ident.name); } @@ -2420,7 +2420,7 @@ pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool { /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent /// use [`is_in_cfg_test`] pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { - if let Some(cfgs) = find_attr!(tcx.hir_attrs(id), CfgTrace(cfgs) => cfgs) + if let Some(cfgs) = find_attr!(tcx, id, CfgTrace(cfgs) => cfgs) && cfgs .iter() .any(|(cfg, _)| matches!(cfg, CfgEntry::NameValue { name: sym::test, .. }))