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#[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 Empty,
20 Delimited(DelimArgs),
22 Eq {
24 eq_span: Span,
26 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#[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 pub path: AttrPath,
74 pub args: AttrArgs,
75 pub style: AttrStyle,
78 pub span: Span,
80}
81
82#[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 }
93}
94#[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 Parsed(AttributeKind),
112
113 Tool(Box<AttrItem>),
118
119 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 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 #[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 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}