diff --git a/Cargo.lock b/Cargo.lock index 7cb05bce70ec4..2c9dc442663f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4430,6 +4430,7 @@ dependencies = [ "rustc_arena", "rustc_ast", "rustc_ast_ir", + "rustc_attr_ir", "rustc_crate_store", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_attr_ir/src/lib.rs b/compiler/rustc_attr_ir/src/lib.rs index 588bcfafb208d..0b142ca92df6b 100644 --- a/compiler/rustc_attr_ir/src/lib.rs +++ b/compiler/rustc_attr_ir/src/lib.rs @@ -1,7 +1,7 @@ //! Data structures for representing parsed attributes in the Rust compiler. //! //! For detailed documentation about attribute processing, -//! see [rustc_attr_parsing](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html). +//! see [rustc_attr_parsing](../rustc_attr_parsing/index.html). // tidy-alphabetical-start #![feature(const_default)] @@ -20,7 +20,6 @@ pub use lang_items::*; pub use pretty_printing::PrintAttribute; pub use stability::*; -// FIXME remove pub on some of these modules? It's fairly inconsistent. mod attr; mod canonical_symbols; mod data_structures; @@ -35,40 +34,38 @@ pub mod weak_lang_items; /// 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`. +/// It is an implementation detail of the [`find_attr!`] macro to be able to accept either a +/// [`DefId`], [`LocalDefId`], [`OwnerId`], or [`HirId`]. It is defined here with a generic `Tcx` +/// because this crate can't depend on `rustc_middle`. The concrete implementations are in +/// `rustc_middle`. +/// +/// Not to be confused with [`rustc_ast::ast_traits::HasAttrs`]. +/// +/// [`DefId`]: rustc_span::def_id::DefId +/// [`LocalDefId`]: rustc_span::def_id::LocalDefId +/// [`OwnerId`]: ../rustc_hir/struct.OwnerId.html +/// [`HirId`]: ../rustc_hir/struct.HirId.html pub trait HasAttrs<'tcx, Tcx> { - fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::attr::Attribute]; + fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::Attribute]; } -/// Finds attributes in sequences of attributes by pattern matching. +/// Finds attributes by pattern matching. /// /// A little like `matches` but for attributes. /// -/// ```rust,ignore (illustrative) -/// // finds the repr attribute -/// if let Some(r) = find_attr!(attrs, AttributeKind::Repr(r) => r) { -/// -/// } -/// -/// // checks if one has matched -/// if find_attr!(attrs, AttributeKind::Repr(_)) { -/// -/// } -/// ``` +/// Note that this macro accepts several "id" types: [`DefId`], [`LocalDefId`], [`OwnerId`] and +/// [`HirId`]. /// -/// Often this requires you to first end up with a list of attributes. -/// Often these are available through the `tcx`. +/// # Examples /// -/// As a convenience, this macro can do that for you! +/// It is most commonly used to check whether something has an attribute or to get its contents +/// if it is present: +/// ```rust,ignore (illustrative) +/// let is_naked: bool = find_attr!(tcx, def_id, Naked(..)); /// -/// Instead of providing an attribute list, provide the `tcx` and an id -/// (a `DefId`, `LocalDefId`, `OwnerId` or `HirId`). +/// let is_visible: bool = find_attr!(tcx, def_id, Doc(doc) if doc.hidden.is_none()); /// -/// ```rust,ignore (illustrative) -/// find_attr!(tcx, def_id, ) -/// find_attr!(tcx, hir_id, ) +/// let link_name: Option = find_attr!(tcx, def_id, LinkName { name, .. } => *name); /// ``` /// /// Another common case is finding attributes applied to the root of the current crate. @@ -77,6 +74,27 @@ pub trait HasAttrs<'tcx, Tcx> { /// ```rust, ignore (illustrative) /// find_attr!(tcx, crate, ) /// ``` +/// +/// If you already have a list of attributes in scope, you can also use that: +/// +/// ```rust,ignore (illustrative) +/// let attrs = ; +/// +/// // finds the repr attribute +/// if let Some(r) = find_attr!(attrs, Repr(r) => r) { +/// +/// } +/// +/// // checks if one has matched +/// if find_attr!(attrs, Repr(_)) { +/// +/// } +/// ``` +/// +/// [`DefId`]: rustc_span::def_id::DefId +/// [`LocalDefId`]: rustc_span::def_id::LocalDefId +/// [`OwnerId`]: ../rustc_hir/struct.OwnerId.html +/// [`HirId`]: ../rustc_hir/struct.HirId.html #[macro_export] macro_rules! find_attr { ($tcx: expr, crate, $pattern: pat $(if $guard: expr)?) => { @@ -89,6 +107,7 @@ macro_rules! find_attr { ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)?) => { $crate::find_attr!($tcx, $id, $pattern $(if $guard)? => ()).is_some() }; + ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ $crate::find_attr!( $crate::HasAttrs::get_attrs($id, &$tcx), @@ -96,7 +115,6 @@ macro_rules! find_attr { ) }}; - ($attributes_list: expr, $pattern: pat $(if $guard: expr)?) => {{ $crate::find_attr!($attributes_list, $pattern $(if $guard)? => ()).is_some() }}; diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index b26969a830f11..361aa2583fd2b 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -15,6 +15,7 @@ rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index dcfd7a6e610b8..91f772f15b9ab 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -53,6 +53,8 @@ use rustc_arena::TypedArena; use rustc_ast as ast; use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::tokenstream::TokenStream; +use rustc_attr_ir::lang_items::{LangItem, LanguageItems}; +use rustc_attr_ir::{CanonicalSymbols, EiiDecl, EiiImpl, StrippedCfgItem}; use rustc_crate_store::{ CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, }; @@ -63,8 +65,6 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{ErrorGuaranteed, catch_fatal_errors}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::{LangItem, LanguageItems}; -use rustc_hir::attrs::{CanonicalSymbols, EiiDecl, EiiImpl, StrippedCfgItem}; use rustc_hir::def::{DefKind, DocLinkResMap}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdSet, LocalModId}; use rustc_hir::{ItemLocalId, PreciseCapturingArgKind}; @@ -1526,8 +1526,12 @@ rustc_queries! { /// Returns the attributes on the item at `def_id`. /// - /// Do not use this directly, use `tcx.get_attrs` instead. - query attrs_for_def(def_id: DefId) -> &'tcx [hir::Attribute] { + ///
+ /// + /// Do not use this directly, use [`rustc_attr_ir::find_attr`] instead. + /// + ///
+ query attrs_for_def(def_id: DefId) -> &'tcx [rustc_attr_ir::Attribute] { desc { "collecting attributes of `{}`", tcx.def_path_str(def_id) } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ddaa01640b64b..0ced7d1ea2bc5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -31,18 +31,18 @@ use rustc_abi::{ use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, NodeId}; pub use rustc_ast_ir::{Movability, Mutability, try_visit}; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{self as attr, StrippedCfgItem, find_attr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer}; -use rustc_hir::attrs::StrippedCfgItem; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; -use rustc_hir::{self as hir, MissingLifetimeKind, attrs as attr, find_attr}; use rustc_index::bit_set::BitMatrix; use rustc_index::{IndexVec, static_assert_size}; pub use rustc_lint_defs::RegisteredTools; @@ -221,7 +221,7 @@ pub struct PerOwnerResolverData<'tcx> { /// Resolution for import nodes, which have multiple resolutions in different namespaces. pub import_res: hir::def::PerNS>> = Default::default(), /// Lifetime parameters that lowering will have to introduce. - pub extra_lifetime_params_map: NodeMap> = Default::default(), + pub extra_lifetime_params_map: NodeMap> = Default::default(), /// The id of the owner pub id: ast::NodeId, @@ -251,7 +251,10 @@ impl<'tcx> PerOwnerResolverData<'tcx> { /// /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring /// should appear at the enclosing `PolyTraitRef`. - pub fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] { + pub fn extra_lifetime_params( + &self, + id: NodeId, + ) -> &[(Ident, NodeId, hir::MissingLifetimeKind)] { self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } } @@ -2008,17 +2011,22 @@ impl<'tcx> TyCtxt<'tcx> { self, did: impl Into, attr: Symbol, - ) -> impl Iterator { + ) -> impl Iterator { #[expect(deprecated)] - self.get_all_attrs(did).iter().filter(move |a: &&hir::Attribute| a.has_name(attr)) + self.get_all_attrs(did).iter().filter(move |a: &&rustc_attr_ir::Attribute| a.has_name(attr)) } /// Gets all attributes. /// + ///
+ /// /// To see if an item has a specific attribute, you should use - /// [`rustc_hir::find_attr!`] so you can use matching. + /// [`rustc_attr_ir::find_attr!`] so you can use matching. + /// + ///
+ /// #[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to call rustc_hir::find_attr! instead."] - pub fn get_all_attrs(self, did: impl Into) -> &'tcx [hir::Attribute] { + pub fn get_all_attrs(self, did: impl Into) -> &'tcx [rustc_attr_ir::Attribute] { let did: DefId = did.into(); if let Some(did) = did.as_local() { self.hir_attrs(self.local_def_id_to_hir_id(did)) @@ -2031,8 +2039,8 @@ impl<'tcx> TyCtxt<'tcx> { self, did: DefId, attr: &[Symbol], - ) -> impl Iterator { - let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr); + ) -> impl Iterator { + let filter_fn = move |a: &&rustc_attr_ir::Attribute| a.path_matches(attr); if let Some(did) = did.as_local() { self.hir_attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn) } else { @@ -2474,8 +2482,8 @@ 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] { +impl<'tcx> rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for DefId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [rustc_attr_ir::Attribute] { if let Some(did) = self.as_local() { tcx.hir_attrs(tcx.local_def_id_to_hir_id(did)) } else { @@ -2484,20 +2492,20 @@ impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for DefId { } } -impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for LocalDefId { - fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] { +impl<'tcx> rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for LocalDefId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [rustc_attr_ir::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> rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::OwnerId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [rustc_attr_ir::Attribute] { + rustc_attr_ir::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] { +impl<'tcx> rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::HirId { + fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [rustc_attr_ir::Attribute] { tcx.hir_attrs(self) } }