Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3use crate::attr::Attribute;
4use crate::expr::{Expr, Index, Member};
5use crate::ident::Ident;
6use crate::punctuated::{self, Punctuated};
7use crate::restriction::{FieldMutability, Visibility};
8use crate::token;
9use crate::ty::Type;
10
11ast_struct! {
12 /// An enum variant.
13 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
14 pub struct Variant {
15 pub attrs: Vec<Attribute>,
16
17 /// Name of the variant.
18 pub ident: Ident,
19
20 /// Content stored in the variant.
21 pub fields: Fields,
22
23 /// Explicit discriminant: `Variant = 1`
24 pub discriminant: Option<(Token![=], Expr)>,
25 }
26}
27
28ast_enum_of_structs! {
29 /// Data stored within an enum variant or struct.
30 ///
31 /// # Syntax tree enum
32 ///
33 /// This type is a [syntax tree enum].
34 ///
35 /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
36 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
37 pub enum Fields {
38 /// Named fields of a struct or struct variant such as `Point { x: f64,
39 /// y: f64 }`.
40 Named(FieldsNamed),
41
42 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
43 Unnamed(FieldsUnnamed),
44
45 /// Unit struct or unit variant such as `None`.
46 Unit,
47 }
48}
49
50ast_struct! {
51 /// Named fields of a struct or struct variant such as `Point { x: f64,
52 /// y: f64 }`.
53 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
54 pub struct FieldsNamed {
55 pub brace_token: token::Brace,
56 pub named: Punctuated<Field, Token![,]>,
57 }
58}
59
60ast_struct! {
61 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
62 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
63 pub struct FieldsUnnamed {
64 pub paren_token: token::Paren,
65 pub unnamed: Punctuated<Field, Token![,]>,
66 }
67}
68
69impl Fields {
70 /// Get an iterator over the borrowed [`Field`] items in this object. This
71 /// iterator can be used to iterate over a named or unnamed struct or
72 /// variant's fields uniformly.
73 pub fn iter(&self) -> punctuated::Iter<Field> {
74 match self {
75 Fields::Unit => crate::punctuated::empty_punctuated_iter(),
76 Fields::Named(f) => f.named.iter(),
77 Fields::Unnamed(f) => f.unnamed.iter(),
78 }
79 }
80
81 /// Get an iterator over the mutably borrowed [`Field`] items in this
82 /// object. This iterator can be used to iterate over a named or unnamed
83 /// struct or variant's fields uniformly.
84 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
85 match self {
86 Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
87 Fields::Named(f) => f.named.iter_mut(),
88 Fields::Unnamed(f) => f.unnamed.iter_mut(),
89 }
90 }
91
92 /// Returns the number of fields.
93 pub fn len(&self) -> usize {
94 match self {
95 Fields::Unit => 0,
96 Fields::Named(f) => f.named.len(),
97 Fields::Unnamed(f) => f.unnamed.len(),
98 }
99 }
100
101 /// Returns `true` if there are zero fields.
102 pub fn is_empty(&self) -> bool {
103 match self {
104 Fields::Unit => true,
105 Fields::Named(f) => f.named.is_empty(),
106 Fields::Unnamed(f) => f.unnamed.is_empty(),
107 }
108 }
109
110 return_impl_trait! {
111 /// Get an iterator over the fields of a struct or variant as [`Member`]s.
112 /// This iterator can be used to iterate over a named or unnamed struct or
113 /// variant's fields uniformly.
114 ///
115 /// # Example
116 ///
117 /// The following is a simplistic [`Clone`] derive for structs. (A more
118 /// complete implementation would additionally want to infer trait bounds on
119 /// the generic type parameters.)
120 ///
121 /// ```
122 /// # use quote::quote;
123 /// #
124 /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream {
125 /// let ident = &input.ident;
126 /// let members = input.fields.members();
127 /// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
128 /// quote! {
129 /// impl #impl_generics Clone for #ident #ty_generics #where_clause {
130 /// fn clone(&self) -> Self {
131 /// Self {
132 /// #(#members: self.#members.clone()),*
133 /// }
134 /// }
135 /// }
136 /// }
137 /// }
138 /// ```
139 ///
140 /// For structs with named fields, it produces an expression like `Self { a:
141 /// self.a.clone() }`. For structs with unnamed fields, `Self { 0:
142 /// self.0.clone() }`. And for unit structs, `Self {}`.
143 pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ [Members] {
144 Members {
145 fields: self.iter(),
146 index: 0,
147 }
148 }
149 }
150}
151
152impl IntoIterator for Fields {
153 type Item = Field;
154 type IntoIter = punctuated::IntoIter<Field>;
155
156 fn into_iter(self) -> Self::IntoIter {
157 match self {
158 Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
159 Fields::Named(f) => f.named.into_iter(),
160 Fields::Unnamed(f) => f.unnamed.into_iter(),
161 }
162 }
163}
164
165impl<'a> IntoIterator for &'a Fields {
166 type Item = &'a Field;
167 type IntoIter = punctuated::Iter<'a, Field>;
168
169 fn into_iter(self) -> Self::IntoIter {
170 self.iter()
171 }
172}
173
174impl<'a> IntoIterator for &'a mut Fields {
175 type Item = &'a mut Field;
176 type IntoIter = punctuated::IterMut<'a, Field>;
177
178 fn into_iter(self) -> Self::IntoIter {
179 self.iter_mut()
180 }
181}
182
183ast_struct! {
184 /// A field of a struct or enum variant.
185 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
186 pub struct Field {
187 pub attrs: Vec<Attribute>,
188
189 pub vis: Visibility,
190
191 pub mutability: FieldMutability,
192
193 /// Name of the field, if any.
194 ///
195 /// Fields of tuple structs have no names.
196 pub ident: Option<Ident>,
197
198 pub colon_token: Option<Token![:]>,
199
200 pub ty: Type,
201 }
202}
203
204pub struct Members<'a> {
205 fields: punctuated::Iter<'a, Field>,
206 index: u32,
207}
208
209impl<'a> Iterator for Members<'a> {
210 type Item = Member;
211
212 fn next(&mut self) -> Option<Self::Item> {
213 let field = self.fields.next()?;
214 let member = match &field.ident {
215 Some(ident) => Member::Named(ident.clone()),
216 None => {
217 #[cfg(all(feature = "parsing", feature = "printing"))]
218 let span = crate::spanned::Spanned::span(&field.ty);
219 #[cfg(not(all(feature = "parsing", feature = "printing")))]
220 let span = proc_macro2::Span::call_site();
221 Member::Unnamed(Index {
222 index: self.index,
223 span,
224 })
225 }
226 };
227 self.index += 1;
228 Some(member)
229 }
230}
231
232impl<'a> Clone for Members<'a> {
233 fn clone(&self) -> Self {
234 Members {
235 fields: self.fields.clone(),
236 index: self.index,
237 }
238 }
239}
240
241#[cfg(feature = "parsing")]
242pub(crate) mod parsing {
243 use crate::attr::Attribute;
244 use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant};
245 use crate::error::Result;
246 use crate::expr::Expr;
247 use crate::ext::IdentExt as _;
248 use crate::ident::Ident;
249 #[cfg(not(feature = "full"))]
250 use crate::parse::discouraged::Speculative as _;
251 use crate::parse::{Parse, ParseStream};
252 use crate::restriction::{FieldMutability, Visibility};
253 #[cfg(not(feature = "full"))]
254 use crate::scan_expr::scan_expr;
255 use crate::token;
256 use crate::ty::Type;
257 use crate::verbatim;
258
259 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
260 impl Parse for Variant {
261 fn parse(input: ParseStream) -> Result<Self> {
262 let attrs = input.call(Attribute::parse_outer)?;
263 let _visibility: Visibility = input.parse()?;
264 let ident: Ident = input.parse()?;
265 let fields = if input.peek(token::Brace) {
266 Fields::Named(input.parse()?)
267 } else if input.peek(token::Paren) {
268 Fields::Unnamed(input.parse()?)
269 } else {
270 Fields::Unit
271 };
272 let discriminant = if input.peek(Token![=]) {
273 let eq_token: Token![=] = input.parse()?;
274 #[cfg(feature = "full")]
275 let discriminant: Expr = input.parse()?;
276 #[cfg(not(feature = "full"))]
277 let discriminant = {
278 let begin = input.fork();
279 let ahead = input.fork();
280 let mut discriminant: Result<Expr> = ahead.parse();
281 if discriminant.is_ok() {
282 input.advance_to(&ahead);
283 } else if scan_expr(input).is_ok() {
284 discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input)));
285 }
286 discriminant?
287 };
288 Some((eq_token, discriminant))
289 } else {
290 None
291 };
292 Ok(Variant {
293 attrs,
294 ident,
295 fields,
296 discriminant,
297 })
298 }
299 }
300
301 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
302 impl Parse for FieldsNamed {
303 fn parse(input: ParseStream) -> Result<Self> {
304 let content;
305 Ok(FieldsNamed {
306 brace_token: braced!(content in input),
307 named: content.parse_terminated(Field::parse_named, Token![,])?,
308 })
309 }
310 }
311
312 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
313 impl Parse for FieldsUnnamed {
314 fn parse(input: ParseStream) -> Result<Self> {
315 let content;
316 Ok(FieldsUnnamed {
317 paren_token: parenthesized!(content in input),
318 unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?,
319 })
320 }
321 }
322
323 impl Field {
324 /// Parses a named (braced struct) field.
325 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
326 pub fn parse_named(input: ParseStream) -> Result<Self> {
327 let attrs = input.call(Attribute::parse_outer)?;
328 let vis: Visibility = input.parse()?;
329
330 let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]);
331 let ident = if unnamed_field {
332 input.call(Ident::parse_any)
333 } else {
334 input.parse()
335 }?;
336
337 let colon_token: Token![:] = input.parse()?;
338
339 let ty: Type = if unnamed_field
340 && (input.peek(Token![struct])
341 || input.peek(Token![union]) && input.peek2(token::Brace))
342 {
343 let begin = input.fork();
344 input.call(Ident::parse_any)?;
345 input.parse::<FieldsNamed>()?;
346 Type::Verbatim(verbatim::between(&begin, input))
347 } else {
348 input.parse()?
349 };
350
351 Ok(Field {
352 attrs,
353 vis,
354 mutability: FieldMutability::None,
355 ident: Some(ident),
356 colon_token: Some(colon_token),
357 ty,
358 })
359 }
360
361 /// Parses an unnamed (tuple struct) field.
362 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
363 pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
364 Ok(Field {
365 attrs: input.call(Attribute::parse_outer)?,
366 vis: input.parse()?,
367 mutability: FieldMutability::None,
368 ident: None,
369 colon_token: None,
370 ty: input.parse()?,
371 })
372 }
373 }
374}
375
376#[cfg(feature = "printing")]
377mod printing {
378 use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant};
379 use crate::print::TokensOrDefault;
380 use proc_macro2::TokenStream;
381 use quote::{ToTokens, TokenStreamExt};
382
383 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
384 impl ToTokens for Variant {
385 fn to_tokens(&self, tokens: &mut TokenStream) {
386 tokens.append_all(&self.attrs);
387 self.ident.to_tokens(tokens);
388 self.fields.to_tokens(tokens);
389 if let Some((eq_token, disc)) = &self.discriminant {
390 eq_token.to_tokens(tokens);
391 disc.to_tokens(tokens);
392 }
393 }
394 }
395
396 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
397 impl ToTokens for FieldsNamed {
398 fn to_tokens(&self, tokens: &mut TokenStream) {
399 self.brace_token.surround(tokens, |tokens| {
400 self.named.to_tokens(tokens);
401 });
402 }
403 }
404
405 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
406 impl ToTokens for FieldsUnnamed {
407 fn to_tokens(&self, tokens: &mut TokenStream) {
408 self.paren_token.surround(tokens, |tokens| {
409 self.unnamed.to_tokens(tokens);
410 });
411 }
412 }
413
414 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
415 impl ToTokens for Field {
416 fn to_tokens(&self, tokens: &mut TokenStream) {
417 tokens.append_all(&self.attrs);
418 self.vis.to_tokens(tokens);
419 if let Some(ident) = &self.ident {
420 ident.to_tokens(tokens);
421 TokensOrDefault(&self.colon_token).to_tokens(tokens);
422 }
423 self.ty.to_tokens(tokens);
424 }
425 }
426}