Skip to main content

rustc_attr_ir/
attr.rs

1use std::fmt;
2
3use rustc_ast::attr::AttributeExt;
4use rustc_ast::token::DocFragmentKind;
5use rustc_ast::{AttrStyle, DelimArgs, MetaItemLit, ast, join_path_idents};
6use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher};
7use rustc_error_messages::{DiagArgValue, IntoDiagArg};
8use rustc_macros::{Decodable, Encodable, StableHash};
9use rustc_span::{AttrId, DUMMY_SP, Ident, Span, Symbol};
10use smallvec::SmallVec;
11use thin_vec::ThinVec;
12
13use crate::AttributeKind;
14
15/// Arguments of a unparsed attribute.
16#[derive(#[automatically_derived]impl ::core::clone::Clone for AttrArgs {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Empty => AttrArgs::Empty,
            Self::Delimited(__self_0) =>
                AttrArgs::Delimited(::core::clone::Clone::clone(__self_0)),
            Self::Eq { eq_span: __self_0, expr: __self_1 } =>
                AttrArgs::Eq {
                    eq_span: ::core::clone::Clone::clone(__self_0),
                    expr: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for AttrArgs {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Empty => ::core::fmt::Formatter::write_str(f, "Empty"),
            Self::Delimited(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Delimited", &__self_0),
            Self::Eq { eq_span: __self_0, expr: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "Eq eq_span expr", __self_0, &__self_1),
        }
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AttrArgs {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    AttrArgs::Empty => 0u8.stable_hash(__hcx, __hasher),
                    AttrArgs::Delimited(ref __binding_0) =>
                        1u8.stable_hash(__hcx, __hasher),
                    AttrArgs::Eq {
                        eq_span: ref __binding_0, expr: ref __binding_1 } =>
                        2u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    AttrArgs::Empty => {}
                    AttrArgs::Delimited(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    AttrArgs::Eq {
                        eq_span: ref __binding_0, expr: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AttrArgs {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AttrArgs::Empty => { 0usize }
                        AttrArgs::Delimited(ref __binding_0) => { 1usize }
                        AttrArgs::Eq {
                            eq_span: ref __binding_0, expr: ref __binding_1 } => {
                            2usize
                        }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    AttrArgs::Empty => {}
                    AttrArgs::Delimited(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    AttrArgs::Eq {
                        eq_span: ref __binding_0, expr: ref __binding_1 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AttrArgs {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { AttrArgs::Empty }
                    1usize => {
                        AttrArgs::Delimited(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => {
                        AttrArgs::Eq {
                            eq_span: ::rustc_serialize::Decodable::decode(__decoder),
                            expr: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AttrArgs`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
17pub enum AttrArgs {
18    /// No arguments: `#[attr]`.
19    Empty,
20    /// Delimited arguments: `#[attr()/[]/{}]`.
21    Delimited(DelimArgs),
22    /// Arguments of a key-value attribute: `#[attr = "value"]`.
23    Eq {
24        /// Span of the `=` token.
25        eq_span: Span,
26        /// The "value".
27        expr: MetaItemLit,
28    },
29}
30
31#[derive(#[automatically_derived]impl ::core::clone::Clone for AttrPath {
    #[inline]
    fn clone(&self) -> Self {
        AttrPath {
            segments: ::core::clone::Clone::clone(&self.segments),
            span: ::core::clone::Clone::clone(&self.span),
        }
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for AttrPath {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "AttrPath segments span", &self.segments, &&self.span)
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AttrPath {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    AttrPath { segments: ref __binding_0, span: ref __binding_1
                        } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AttrPath {
            fn encode(&self, __encoder: &mut __E) {
                let AttrPath {
                        segments: ref __binding_0, span: ref __binding_1 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AttrPath {
            fn decode(__decoder: &mut __D) -> Self {
                AttrPath {
                    segments: ::rustc_serialize::Decodable::decode(__decoder),
                    span: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
32pub struct AttrPath {
33    pub segments: Box<[Symbol]>,
34    pub span: Span,
35}
36
37impl IntoDiagArg for AttrPath {
38    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
39        self.to_string().into_diag_arg(path)
40    }
41}
42
43impl AttrPath {
44    pub fn from_ast(path: &ast::Path, lower_span: impl Copy + Fn(Span) -> Span) -> Self {
45        AttrPath {
46            segments: path
47                .segments
48                .iter()
49                .map(|i| i.ident.name)
50                .collect::<Vec<_>>()
51                .into_boxed_slice(),
52            span: lower_span(path.span),
53        }
54    }
55}
56
57impl fmt::Display for AttrPath {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        f.write_fmt(format_args!("{0}",
        join_path_idents(self.segments.iter().map(|i|
                    Ident { name: *i, span: DUMMY_SP }))))write!(
60            f,
61            "{}",
62            join_path_idents(self.segments.iter().map(|i| Ident { name: *i, span: DUMMY_SP }))
63        )
64    }
65}
66
67/// A non built-in attribute.
68///
69/// This is either a tool attribute or a derive helper attribute.
70#[derive(#[automatically_derived]impl ::core::clone::Clone for AttrItem {
    #[inline]
    fn clone(&self) -> Self {
        AttrItem {
            path: ::core::clone::Clone::clone(&self.path),
            args: ::core::clone::Clone::clone(&self.args),
            style: ::core::clone::Clone::clone(&self.style),
            span: ::core::clone::Clone::clone(&self.span),
        }
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for AttrItem {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f,
            "AttrItem path args style span", &self.path, &self.args,
            &self.style, &&self.span)
    }
}Debug, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for AttrItem {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    AttrItem {
                        path: ref __binding_0,
                        args: ref __binding_1,
                        style: ref __binding_2,
                        span: ref __binding_3 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AttrItem {
            fn encode(&self, __encoder: &mut __E) {
                let AttrItem {
                        path: ref __binding_0,
                        args: ref __binding_1,
                        style: ref __binding_2,
                        span: ref __binding_3 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_3,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AttrItem {
            fn decode(__decoder: &mut __D) -> Self {
                AttrItem {
                    path: ::rustc_serialize::Decodable::decode(__decoder),
                    args: ::rustc_serialize::Decodable::decode(__decoder),
                    style: ::rustc_serialize::Decodable::decode(__decoder),
                    span: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
71pub struct AttrItem {
72    // Not lowered to hir::Path because we have no NodeId to resolve to.
73    pub path: AttrPath,
74    pub args: AttrArgs,
75    /// Denotes if the attribute decorates the following construct (outer)
76    /// or the construct this attribute is contained within (inner).
77    pub style: AttrStyle,
78    /// Span of the entire attribute
79    pub span: Span,
80}
81
82/// The derived implementation of [`StableHash`] on [`Attribute`]s shouldn't hash
83/// [`AttrId`]s. By wrapping them in this, we make sure we never do.
84#[derive(#[automatically_derived]impl ::core::marker::Copy for HashIgnoredAttrId { }Copy, #[automatically_derived]impl ::core::fmt::Debug for HashIgnoredAttrId {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "HashIgnoredAttrId attr_id", &&self.attr_id)
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for HashIgnoredAttrId {
            fn encode(&self, __encoder: &mut __E) {
                let HashIgnoredAttrId { attr_id: ref __binding_0 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for HashIgnoredAttrId {
            fn decode(__decoder: &mut __D) -> Self {
                HashIgnoredAttrId {
                    attr_id: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for HashIgnoredAttrId {
}
#[automatically_derived]impl ::core::clone::Clone for HashIgnoredAttrId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<AttrId>;
        *self
    }
}Clone)]
85pub struct HashIgnoredAttrId {
86    pub attr_id: AttrId,
87}
88
89impl StableHash for HashIgnoredAttrId {
90    fn stable_hash<Hcx: StableHashCtxt>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {
91        /* we don't hash HashIgnoredAttrId, we ignore them */
92    }
93}
94/// A high level representation of an attribute.
95///
96/// Not to be confused with [`ast::Attribute`], which represents the syntax-level form of
97/// an attribute.
98///
99/// [`ast::Attribute`]: rustc_ast::ast::Attribute
100#[derive(#[automatically_derived]impl ::core::clone::Clone for Attribute {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Parsed(__self_0) =>
                Attribute::Parsed(::core::clone::Clone::clone(__self_0)),
            Self::Tool(__self_0) =>
                Attribute::Tool(::core::clone::Clone::clone(__self_0)),
            Self::DeriveHelper(__self_0) =>
                Attribute::DeriveHelper(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for Attribute {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Parsed(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Parsed",
                    &__self_0),
            Self::Tool(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Tool",
                    &__self_0),
            Self::DeriveHelper(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "DeriveHelper", &__self_0),
        }
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Attribute {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Attribute::Parsed(ref __binding_0) => { 0usize }
                        Attribute::Tool(ref __binding_0) => { 1usize }
                        Attribute::DeriveHelper(ref __binding_0) => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Attribute::Parsed(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    Attribute::Tool(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    Attribute::DeriveHelper(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Attribute {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        Attribute::Parsed(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        Attribute::Tool(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => {
                        Attribute::DeriveHelper(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Attribute`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Attribute {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    Attribute::Parsed(ref __binding_0) =>
                        0u8.stable_hash(__hcx, __hasher),
                    Attribute::Tool(ref __binding_0) =>
                        1u8.stable_hash(__hcx, __hasher),
                    Attribute::DeriveHelper(ref __binding_0) =>
                        2u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    Attribute::Parsed(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    Attribute::Tool(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    Attribute::DeriveHelper(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
101pub enum Attribute {
102    /// A parsed built-in attribute.
103    ///
104    /// Parsed attributes don't generally have a span associated with them. This is because
105    /// multiple syntax-level attributes can be represented into a single semantic attribute. For
106    /// example, an item can have multiple `repr` attributes on it, which will coalesce into a
107    /// single [`AttributeKind::Repr`], and the `stable`, `unstable`, and
108    /// `rustc_allowed_through_unstable_modules` all combine into a single
109    /// [`AttributeKind::Stability`] attribute. Most `Attribute` variants do have a [`Span`] field,
110    /// though, mostly for the purpose of generating diagnostics later in the compilation process.
111    Parsed(AttributeKind),
112
113    /// A tool attribute.
114    ///
115    /// Tool attributes, with the exception of diagnostic attributes, are not converted into a
116    /// parsed form.
117    Tool(Box<AttrItem>),
118
119    /// A derive helper attribute.
120    ///
121    /// Derive helper attributes serve no use beyond macro expansion, but they are useful to
122    /// consumers of `rustdoc-json`, so we keep them around. See
123    /// <https://github.com/rust-lang/rust/issues/157107> for context.
124    DeriveHelper(Box<AttrItem>),
125}
126
127impl Attribute {
128    pub fn value_lit(&self) -> Option<&MetaItemLit> {
129        match &self {
130            Attribute::Tool(n) | Attribute::DeriveHelper(n) => match n.as_ref() {
131                AttrItem { args: AttrArgs::Eq { eq_span: _, expr }, .. } => Some(expr),
132                _ => None,
133            },
134            _ => None,
135        }
136    }
137
138    pub fn is_prefix_attr_for_suggestions(&self) -> bool {
139        match self {
140            Attribute::Tool(attr) | Attribute::DeriveHelper(attr) => {
141                attr.span.desugaring_kind().is_none()
142            }
143            // Other parsed attributes that can appear on expressions originate from source and
144            // should make suggestions treat the expression like a prefixed form.
145            Attribute::Parsed(_) => true,
146        }
147    }
148}
149
150impl AttributeExt for Attribute {
151    #[inline]
152    fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
153        match &self {
154            Attribute::Tool(n) | Attribute::DeriveHelper(n) => match n.as_ref() {
155                AttrItem { args: AttrArgs::Delimited(d), .. } => {
156                    ast::MetaItemKind::list_from_tokens(d.tokens.clone())
157                }
158                _ => None,
159            },
160            _ => None,
161        }
162    }
163
164    #[inline]
165    fn value_str(&self) -> Option<Symbol> {
166        self.value_lit().and_then(|x| x.value_as_str())
167    }
168
169    #[inline]
170    fn value_span(&self) -> Option<Span> {
171        self.value_lit().map(|i| i.span)
172    }
173
174    /// For a single-segment attribute, returns its name; otherwise, returns `None`.
175    #[inline]
176    fn name(&self) -> Option<Symbol> {
177        match &self {
178            Attribute::DeriveHelper(n) => {
179                if let [ident] = n.path.segments.as_ref() {
180                    Some(*ident)
181                } else {
182                    None
183                }
184            }
185            Attribute::Parsed(..) => None,
186            // Tools are never single segment attributes
187            Attribute::Tool(..) => None,
188        }
189    }
190
191    #[inline]
192    fn path_matches(&self, name: &[Symbol]) -> bool {
193        match &self {
194            Attribute::Tool(n) | Attribute::DeriveHelper(n) => n.path.segments.iter().eq(name),
195            _ => false,
196        }
197    }
198
199    #[inline]
200    fn is_doc_comment(&self) -> Option<Span> {
201        if let Attribute::Parsed(AttributeKind::DocComment { span, .. }) = self {
202            Some(*span)
203        } else {
204            None
205        }
206    }
207
208    #[inline]
209    fn is_word(&self) -> bool {
210        match &self {
211            Attribute::Tool(n) | Attribute::DeriveHelper(n) => {
212                #[allow(non_exhaustive_omitted_patterns)] match n.args {
    AttrArgs::Empty => true,
    _ => false,
}matches!(n.args, AttrArgs::Empty)
213            }
214            _ => false,
215        }
216    }
217
218    #[inline]
219    fn symbol_path(&self) -> Option<SmallVec<[Symbol; 1]>> {
220        match &self {
221            Attribute::Tool(n) | Attribute::DeriveHelper(n) => {
222                Some(n.path.segments.iter().copied().collect())
223            }
224            _ => None,
225        }
226    }
227
228    fn path_span(&self) -> Option<Span> {
229        match &self {
230            Attribute::Tool(attr) | Attribute::DeriveHelper(attr) => Some(attr.path.span),
231            Attribute::Parsed(_) => None,
232        }
233    }
234
235    #[inline]
236    fn doc_str(&self) -> Option<Symbol> {
237        match &self {
238            Attribute::Parsed(AttributeKind::DocComment { comment, .. }) => Some(*comment),
239            _ => None,
240        }
241    }
242
243    #[inline]
244    fn doc_str_and_fragment_kind(&self) -> Option<(Symbol, DocFragmentKind, Span)> {
245        match &self {
246            Attribute::Parsed(AttributeKind::DocComment { kind, comment, span, .. }) => {
247                Some((*comment, *kind, *span))
248            }
249            _ => None,
250        }
251    }
252
253    fn doc_resolution_scope(&self) -> Option<AttrStyle> {
254        match self {
255            Attribute::Parsed(AttributeKind::DocComment { style, .. }) => Some(*style),
256            _ => None,
257        }
258    }
259
260    fn is_proc_macro_attr(&self) -> bool {
261        #[allow(non_exhaustive_omitted_patterns)] match self {
    Attribute::Parsed(AttributeKind::ProcMacro |
        AttributeKind::ProcMacroAttribute | AttributeKind::ProcMacroDerive {
        .. }) => true,
    _ => false,
}matches!(
262            self,
263            Attribute::Parsed(
264                AttributeKind::ProcMacro
265                    | AttributeKind::ProcMacroAttribute
266                    | AttributeKind::ProcMacroDerive { .. }
267            )
268        )
269    }
270
271    fn is_doc_keyword_or_attribute(&self) -> bool {
272        #[allow(non_exhaustive_omitted_patterns)] match self {
    Attribute::Parsed(AttributeKind::Doc(d)) if
        d.attribute.is_some() || d.keyword.is_some() => true,
    _ => false,
}matches!(self, Attribute::Parsed(AttributeKind::Doc(d)) if d.attribute.is_some() || d.keyword.is_some())
273    }
274
275    fn is_rustc_doc_primitive(&self) -> bool {
276        #[allow(non_exhaustive_omitted_patterns)] match self {
    Attribute::Parsed(AttributeKind::RustcDocPrimitive(..)) => true,
    _ => false,
}matches!(self, Attribute::Parsed(AttributeKind::RustcDocPrimitive(..)))
277    }
278}