| //! Data structures for representing parsed attributes in the Rust compiler. | |
| //! Formerly `rustc_attr_data_structures`. | |
| //! | |
| //! For detailed documentation about attribute processing, | |
| //! see [rustc_attr_parsing](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html). | |
| pub use data_structures::*; | |
| pub use encode_cross_crate::EncodeCrossCrate; | |
| pub use pretty_printing::PrintAttribute; | |
| mod data_structures; | |
| 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. | |
| /// | |
| /// ```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(_)) { | |
| /// | |
| /// } | |
| /// ``` | |
| /// | |
| /// Often this requires you to first end up with a list of attributes. | |
| /// Often these are available through the `tcx`. | |
| /// | |
| /// As a convenience, this macro can do that for you! | |
| /// | |
| /// 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, <pattern>) | |
| /// find_attr!(tcx, hir_id, <pattern>) | |
| /// ``` | |
| /// | |
| /// Another common case is finding attributes applied to the root of the current crate. | |
| /// For that, use the shortcut: | |
| /// | |
| /// ```rust, ignore (illustrative) | |
| /// find_attr!(tcx, crate, <pattern>) | |
| /// ``` | |
| #[macro_export] | |
| macro_rules! find_attr { | |
| ($tcx: expr, crate, $pattern: pat $(if $guard: expr)?) => { | |
| $crate::find_attr!($tcx, crate, $pattern $(if $guard)? => ()).is_some() | |
| }; | |
| ($tcx: expr, crate, $pattern: pat $(if $guard: expr)? => $e: expr) => { | |
| $crate::find_attr!($tcx.hir_krate_attrs(), $pattern $(if $guard)? => $e) | |
| }; | |
| ($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::attrs::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() | |
| }}; | |
| ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ | |
| 'done: { | |
| for i in $attributes_list { | |
| #[allow(unused_imports)] | |
| use rustc_hir::attrs::AttributeKind::*; | |
| let i: &rustc_hir::Attribute = i; | |
| match i { | |
| rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => { | |
| break 'done Some($e); | |
| } | |
| rustc_hir::Attribute::Unparsed(..) => {} | |
| // In lint emitting, there's a specific exception for this warning. | |
| // It's not usually emitted from inside macros from other crates | |
| // (see https://github.com/rust-lang/rust/issues/110613) | |
| // But this one is! | |
| #[deny(unreachable_patterns)] | |
| _ => {} | |
| } | |
| } | |
| None | |
| } | |
| }}; | |
| } |