Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4430,6 +4430,7 @@ dependencies = [
"rustc_arena",
"rustc_ast",
"rustc_ast_ir",
"rustc_attr_ir",
"rustc_crate_store",
"rustc_data_structures",
"rustc_errors",
Expand Down
72 changes: 45 additions & 27 deletions compiler/rustc_attr_ir/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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;
Expand All @@ -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, <pattern>)
/// find_attr!(tcx, hir_id, <pattern>)
/// let link_name: Option<Symbol> = find_attr!(tcx, def_id, LinkName { name, .. } => *name);
/// ```
///
/// Another common case is finding attributes applied to the root of the current crate.
Expand All @@ -77,6 +74,27 @@ pub trait HasAttrs<'tcx, Tcx> {
/// ```rust, ignore (illustrative)
/// find_attr!(tcx, crate, <pattern>)
/// ```
///
/// If you already have a list of attributes in scope, you can also use that:
///
/// ```rust,ignore (illustrative)
/// let attrs = <list of attributes>;
///
/// // 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)?) => {
Expand All @@ -89,14 +107,14 @@ 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),
$pattern $(if $guard)? => $e
)
}};


($attributes_list: expr, $pattern: pat $(if $guard: expr)?) => {{
$crate::find_attr!($attributes_list, $pattern $(if $guard)? => ()).is_some()
}};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -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};
Expand Down Expand Up @@ -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] {
/// <div class="warning">
///
/// Do not use this directly, use [`rustc_attr_ir::find_attr`] instead.
///
/// </div>
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
}
Expand Down
48 changes: 28 additions & 20 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Option<Res<ast::NodeId>>> = Default::default(),
/// Lifetime parameters that lowering will have to introduce.
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, MissingLifetimeKind)>> = Default::default(),
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, hir::MissingLifetimeKind)>> = Default::default(),

/// The id of the owner
pub id: ast::NodeId,
Expand Down Expand Up @@ -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[..])
}
}
Expand Down Expand Up @@ -2008,17 +2011,22 @@ impl<'tcx> TyCtxt<'tcx> {
self,
did: impl Into<DefId>,
attr: Symbol,
) -> impl Iterator<Item = &'tcx hir::Attribute> {
) -> impl Iterator<Item = &'tcx rustc_attr_ir::Attribute> {
#[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.
///
/// <div class="warning">
///
/// 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.
///
/// </div>
///
#[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<DefId>) -> &'tcx [hir::Attribute] {
pub fn get_all_attrs(self, did: impl Into<DefId>) -> &'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))
Expand All @@ -2031,8 +2039,8 @@ impl<'tcx> TyCtxt<'tcx> {
self,
did: DefId,
attr: &[Symbol],
) -> impl Iterator<Item = &'tcx hir::Attribute> {
let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr);
) -> impl Iterator<Item = &'tcx rustc_attr_ir::Attribute> {
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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
}
}
Expand Down
Loading