From 218d003ea6f37910d3d997f2183026c974063eec Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 22 Dec 2025 16:31:30 +0000 Subject: [PATCH] Support the Default Field Values Feature This is exposed as a version of the structures with a `WithDefault` suffix, as the simpler solution has been ruled out. Co-Authored-By: =?UTF-8?q?Esteban=20K=C3=BCber?= --- examples/heapsize/heapsize_derive/src/lib.rs | 17 +- src/data.rs | 521 ++++++++++- src/derive.rs | 147 ++- src/file.rs | 46 +- src/gen/clone.rs | 188 ++++ src/gen/debug.rs | 211 +++++ src/gen/eq.rs | 194 ++++ src/gen/fold.rs | 367 ++++++++ src/gen/hash.rs | 212 +++++ src/gen/visit.rs | 332 +++++++ src/gen/visit_mut.rs | 318 +++++++ src/item.rs | 407 ++++++++- src/lib.rs | 84 +- syn.json | 421 +++++++++ tests/debug/gen.rs | 296 ++++++ tests/test_derive_input.rs | 4 + tests/test_derive_input_with_default.rs | 900 +++++++++++++++++++ tests/test_item.rs | 94 +- 18 files changed, 4657 insertions(+), 102 deletions(-) create mode 100644 tests/test_derive_input_with_default.rs diff --git a/examples/heapsize/heapsize_derive/src/lib.rs b/examples/heapsize/heapsize_derive/src/lib.rs index b1246093a0..3c33b3f52b 100644 --- a/examples/heapsize/heapsize_derive/src/lib.rs +++ b/examples/heapsize/heapsize_derive/src/lib.rs @@ -2,13 +2,14 @@ use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::{ - parse_macro_input, parse_quote, Data, DeriveInput, Fields, GenericParam, Generics, Index, + parse_macro_input, parse_quote, DataWithDefault, DeriveInputWithDefault, FieldsWithDefault, + GenericParam, Generics, Index, }; #[proc_macro_derive(HeapSize)] pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream { // Parse the input tokens into a syntax tree. - let input = parse_macro_input!(input as DeriveInput); + let input = parse_macro_input!(input as DeriveInputWithDefault); // Used in the quasi-quotation below as `#name`. let name = input.ident; @@ -44,11 +45,11 @@ fn add_trait_bounds(mut generics: Generics) -> Generics { } // Generate an expression to sum up the heap size of each field. -fn heap_size_sum(data: &Data) -> TokenStream { +fn heap_size_sum(data: &DataWithDefault) -> TokenStream { match *data { - Data::Struct(ref data) => { + DataWithDefault::Struct(ref data) => { match data.fields { - Fields::Named(ref fields) => { + FieldsWithDefault::Named(ref fields) => { // Expands to an expression like // // 0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size() @@ -71,7 +72,7 @@ fn heap_size_sum(data: &Data) -> TokenStream { 0 #(+ #recurse)* } } - Fields::Unnamed(ref fields) => { + FieldsWithDefault::Unnamed(ref fields) => { // Expands to an expression like // // 0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size() @@ -85,12 +86,12 @@ fn heap_size_sum(data: &Data) -> TokenStream { 0 #(+ #recurse)* } } - Fields::Unit => { + FieldsWithDefault::Unit => { // Unit structs cannot own more than 0 bytes of heap memory. quote!(0) } } } - Data::Enum(_) | Data::Union(_) => unimplemented!(), + DataWithDefault::Enum(_) | DataWithDefault::Union(_) => unimplemented!(), } } diff --git a/src/data.rs b/src/data.rs index f973004dc6..d510a9b673 100644 --- a/src/data.rs +++ b/src/data.rs @@ -236,6 +236,241 @@ impl<'a> Clone for Members<'a> { } } +ast_struct! { + /// An enum variant. + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] + pub struct VariantWithDefault { + pub attrs: Vec, + + /// Name of the variant. + pub ident: Ident, + + /// Content stored in the variant. + pub fields: FieldsWithDefault, + + /// Explicit discriminant: `Variant = 1` + pub discriminant: Option<(Token![=], Expr)>, + } +} + +ast_enum_of_structs! { + /// Data stored within an enum variant or struct. + /// + /// # Syntax tree enum + /// + /// This type is a [syntax tree enum]. + /// + /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] + pub enum FieldsWithDefault { + /// Named fields of a struct or struct variant such as `Point { x: f64, + /// y: f64 }`. + Named(FieldsNamedWithDefault), + + /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. + Unnamed(FieldsUnnamedWithDefault), + + /// Unit struct or unit variant such as `None`. + Unit, + } +} + +ast_struct! { + /// Named fields of a struct or struct variant such as `Point { x: f64, + /// y: f64 }`. + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] + pub struct FieldsNamedWithDefault { + pub brace_token: token::Brace, + pub named: Punctuated, + } +} + +ast_struct! { + /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] + pub struct FieldsUnnamedWithDefault { + pub paren_token: token::Paren, + pub unnamed: Punctuated, + } +} + +impl FieldsWithDefault { + /// Get an iterator over the borrowed [`Field`] items in this object. This + /// iterator can be used to iterate over a named or unnamed struct or + /// variant's fields uniformly. + pub fn iter(&self) -> punctuated::Iter { + match self { + FieldsWithDefault::Unit => crate::punctuated::empty_punctuated_iter(), + FieldsWithDefault::Named(f) => f.named.iter(), + FieldsWithDefault::Unnamed(f) => f.unnamed.iter(), + } + } + + /// Get an iterator over the mutably borrowed [`Field`] items in this + /// object. This iterator can be used to iterate over a named or unnamed + /// struct or variant's fields uniformly. + pub fn iter_mut(&mut self) -> punctuated::IterMut { + match self { + FieldsWithDefault::Unit => crate::punctuated::empty_punctuated_iter_mut(), + FieldsWithDefault::Named(f) => f.named.iter_mut(), + FieldsWithDefault::Unnamed(f) => f.unnamed.iter_mut(), + } + } + + /// Returns the number of fields. + pub fn len(&self) -> usize { + match self { + FieldsWithDefault::Unit => 0, + FieldsWithDefault::Named(f) => f.named.len(), + FieldsWithDefault::Unnamed(f) => f.unnamed.len(), + } + } + + /// Returns `true` if there are zero fields. + pub fn is_empty(&self) -> bool { + match self { + FieldsWithDefault::Unit => true, + FieldsWithDefault::Named(f) => f.named.is_empty(), + FieldsWithDefault::Unnamed(f) => f.unnamed.is_empty(), + } + } + + return_impl_trait! { + /// Get an iterator over the fields of a struct or variant as [`Member`]s. + /// This iterator can be used to iterate over a named or unnamed struct or + /// variant's fields uniformly. + /// + /// # Example + /// + /// The following is a simplistic [`Clone`] derive for structs. (A more + /// complete implementation would additionally want to infer trait bounds on + /// the generic type parameters.) + /// + /// ``` + /// # use quote::quote; + /// # + /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream { + /// let ident = &input.ident; + /// let members = input.fields.members(); + /// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + /// quote! { + /// impl #impl_generics Clone for #ident #ty_generics #where_clause { + /// fn clone(&self) -> Self { + /// Self { + /// #(#members: self.#members.clone()),* + /// } + /// } + /// } + /// } + /// } + /// ``` + /// + /// For structs with named fields, it produces an expression like `Self { a: + /// self.a.clone() }`. For structs with unnamed fields, `Self { 0: + /// self.0.clone() }`. And for unit structs, `Self {}`. + pub fn members(&self) -> impl Iterator + Clone + '_ [MembersWithDefault] { + MembersWithDefault { + fields: self.iter(), + index: 0, + } + } + } +} + +impl IntoIterator for FieldsWithDefault { + type Item = FieldWithDefault; + type IntoIter = punctuated::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + match self { + FieldsWithDefault::Unit => Punctuated::::new().into_iter(), + FieldsWithDefault::Named(f) => f.named.into_iter(), + FieldsWithDefault::Unnamed(f) => f.unnamed.into_iter(), + } + } +} + +impl<'a> IntoIterator for &'a FieldsWithDefault { + type Item = &'a FieldWithDefault; + type IntoIter = punctuated::Iter<'a, FieldWithDefault>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a> IntoIterator for &'a mut FieldsWithDefault { + type Item = &'a mut FieldWithDefault; + type IntoIter = punctuated::IterMut<'a, FieldWithDefault>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +ast_struct! { + /// A field of a struct or enum variant, possibly with a provided (const) default. + #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] + pub struct FieldWithDefault { + pub attrs: Vec, + + pub vis: Visibility, + + pub mutability: FieldMutability, + + /// Name of the field, if any. + /// + /// Fields of tuple structs have no names. + pub ident: Option, + + pub colon_token: Option, + + pub ty: Type, + + /// Default value: `field_name: i32 = 1` + /// + /// `#![feature(default_field_values)]` + pub default: Option<(Token![=], Expr)>, + } +} + +pub struct MembersWithDefault<'a> { + fields: punctuated::Iter<'a, FieldWithDefault>, + index: u32, +} + +impl<'a> Iterator for MembersWithDefault<'a> { + type Item = Member; + + fn next(&mut self) -> Option { + let field = self.fields.next()?; + let member = match &field.ident { + Some(ident) => Member::Named(ident.clone()), + None => { + #[cfg(all(feature = "parsing", feature = "printing"))] + let span = crate::spanned::Spanned::span(&field.ty); + #[cfg(not(all(feature = "parsing", feature = "printing")))] + let span = proc_macro2::Span::call_site(); + Member::Unnamed(Index { + index: self.index, + span, + }) + } + }; + self.index += 1; + Some(member) + } +} + +impl<'a> Clone for MembersWithDefault<'a> { + fn clone(&self) -> Self { + MembersWithDefault { + fields: self.fields.clone(), + index: self.index, + } + } +} + #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; @@ -250,43 +485,17 @@ pub(crate) mod parsing { use crate::restriction::{FieldMutability, Visibility}; #[cfg(not(feature = "full"))] use crate::scan_expr::scan_expr; - use crate::token; use crate::ty::Type; use crate::verbatim; + use crate::{ + token, FieldWithDefault, FieldsNamedWithDefault, FieldsUnnamedWithDefault, + FieldsWithDefault, VariantWithDefault, + }; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Variant { fn parse(input: ParseStream) -> Result { - let attrs = input.call(Attribute::parse_outer)?; - let _visibility: Visibility = input.parse()?; - let ident: Ident = input.parse()?; - let fields = if input.peek(token::Brace) { - Fields::Named(input.parse()?) - } else if input.peek(token::Paren) { - Fields::Unnamed(input.parse()?) - } else { - Fields::Unit - }; - let discriminant = if input.peek(Token![=]) { - let eq_token: Token![=] = input.parse()?; - #[cfg(feature = "full")] - let discriminant: Expr = input.parse()?; - #[cfg(not(feature = "full"))] - let discriminant = { - let begin = input.fork(); - let ahead = input.fork(); - let mut discriminant: Result = ahead.parse(); - if discriminant.is_ok() { - input.advance_to(&ahead); - } else if scan_expr(input).is_ok() { - discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input))); - } - discriminant? - }; - Some((eq_token, discriminant)) - } else { - None - }; + let (attrs, ident, fields, discriminant) = parse_variants(input)?; Ok(Variant { attrs, ident, @@ -296,6 +505,57 @@ pub(crate) mod parsing { } } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for VariantWithDefault { + fn parse(input: ParseStream) -> Result { + let (attrs, ident, fields, discriminant) = parse_variants(input)?; + Ok(VariantWithDefault { + attrs, + ident, + fields, + discriminant, + }) + } + } + + // Internal function, only used directly above. + #[allow(clippy::type_complexity)] + fn parse_variants( + input: &crate::parse::ParseBuffer<'_>, + ) -> Result<(Vec, Ident, F, Option<(Token![=], Expr)>)> { + let attrs = input.call(Attribute::parse_outer)?; + let _visibility: Visibility = input.parse()?; + let ident: Ident = input.parse()?; + let fields = if input.peek(token::Brace) { + F::named(input.parse()?) + } else if input.peek(token::Paren) { + F::unnamed(input.parse()?) + } else { + F::unit() + }; + let discriminant = if input.peek(Token![=]) { + let eq_token: Token![=] = input.parse()?; + #[cfg(feature = "full")] + let discriminant: Expr = input.parse()?; + #[cfg(not(feature = "full"))] + let discriminant = { + let begin = input.fork(); + let ahead = input.fork(); + let mut discriminant: Result = ahead.parse(); + if discriminant.is_ok() { + input.advance_to(&ahead); + } else if scan_expr(input).is_ok() { + discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input))); + } + discriminant? + }; + Some((eq_token, discriminant)) + } else { + None + }; + Ok((attrs, ident, fields, discriminant)) + } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FieldsNamed { fn parse(input: ParseStream) -> Result { @@ -318,10 +578,49 @@ pub(crate) mod parsing { } } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for FieldsNamedWithDefault { + fn parse(input: ParseStream) -> Result { + let content; + Ok(FieldsNamedWithDefault { + brace_token: braced!(content in input), + named: content.parse_terminated(FieldWithDefault::parse_named, Token![,])?, + }) + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for FieldsUnnamedWithDefault { + fn parse(input: ParseStream) -> Result { + let content; + Ok(FieldsUnnamedWithDefault { + paren_token: parenthesized!(content in input), + unnamed: content.parse_terminated(FieldWithDefault::parse_unnamed, Token![,])?, + }) + } + } + impl Field { /// Parses a named (braced struct) field. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_named(input: ParseStream) -> Result { + let (res, default) = Self::parse_named_with_default(input)?; + if let Some((_eq, _)) = default { + // We choose not to emit an error in this case, because ignoring it brings implicit support + // for ignoring default field values to ecosystem derive macros. + // The counterpoint is that it will be confusing for non-derive macros (or external + // parsing), although it's much rarer to find those on structs/enums. + // (This confusion would be because the corresponding `ToTokens` impl will just silently + // exclude the default field value) + } + Ok(res) + } + + /// Parses a named (braced struct) field, optionally returning the default value. + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + fn parse_named_with_default( + input: ParseStream, + ) -> Result<(Self, Option<(Token![=], Expr)>)> { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; @@ -346,14 +645,23 @@ pub(crate) mod parsing { input.parse()? }; - Ok(Field { - attrs, - vis, - mutability: FieldMutability::None, - ident: Some(ident), - colon_token: Some(colon_token), - ty, - }) + let mut default: Option<(Token![=], Expr)> = None; + if input.peek(Token![=]) { + let eq_token: Token![=] = input.parse()?; + default = Some((eq_token, input.parse()?)); + } + + Ok(( + Field { + attrs, + vis, + mutability: FieldMutability::None, + ident: Some(ident), + colon_token: Some(colon_token), + ty, + }, + default, + )) } /// Parses an unnamed (tuple struct) field. @@ -369,12 +677,100 @@ pub(crate) mod parsing { }) } } + impl FieldWithDefault { + pub fn parse_named(input: ParseStream) -> Result { + let ( + Field { + attrs, + vis, + mutability, + ident, + colon_token, + ty, + }, + default, + ) = Field::parse_named_with_default(input)?; + Ok(Self { + attrs, + vis, + mutability, + ident, + colon_token, + ty, + default, + }) + } + + /// Parses an unnamed (tuple struct) field. + /// + /// There is no need for default field values in. + pub fn parse_unnamed(input: ParseStream) -> Result { + let Field { + attrs, + vis, + mutability, + ident, + colon_token, + ty, + } = Field::parse_unnamed(input)?; + Ok(Self { + attrs, + vis, + mutability, + ident, + colon_token, + ty, + default: None, + }) + } + } + + /// An internal trait to allow abstracting minimally over [`Fields`] and [`FieldsUnnamed`] in parsing. + pub(crate) trait FieldsStruct { + type NamedTy: Parse; + type UnnamedTy: Parse; + + fn named(named: Self::NamedTy) -> Self; + fn unnamed(unnamed: Self::UnnamedTy) -> Self; + fn unit() -> Self; + } + + impl FieldsStruct for Fields { + type NamedTy = FieldsNamed; + type UnnamedTy = FieldsUnnamed; + fn named(named: Self::NamedTy) -> Self { + Self::Named(named) + } + fn unnamed(unnamed: Self::UnnamedTy) -> Self { + Self::Unnamed(unnamed) + } + fn unit() -> Self { + Self::Unit + } + } + + impl FieldsStruct for FieldsWithDefault { + type NamedTy = FieldsNamedWithDefault; + type UnnamedTy = FieldsUnnamedWithDefault; + fn named(named: Self::NamedTy) -> Self { + Self::Named(named) + } + fn unnamed(unnamed: Self::UnnamedTy) -> Self { + Self::Unnamed(unnamed) + } + fn unit() -> Self { + Self::Unit + } + } } #[cfg(feature = "printing")] mod printing { use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant}; use crate::print::TokensOrDefault; + use crate::{ + FieldWithDefault, FieldsNamedWithDefault, FieldsUnnamedWithDefault, VariantWithDefault, + }; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt as _}; @@ -421,4 +817,51 @@ mod printing { self.ty.to_tokens(tokens); } } + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for VariantWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(&self.attrs); + self.ident.to_tokens(tokens); + self.fields.to_tokens(tokens); + if let Some((eq_token, disc)) = &self.discriminant { + eq_token.to_tokens(tokens); + disc.to_tokens(tokens); + } + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for FieldsNamedWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.brace_token.surround(tokens, |tokens| { + self.named.to_tokens(tokens); + }); + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for FieldsUnnamedWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.paren_token.surround(tokens, |tokens| { + self.unnamed.to_tokens(tokens); + }); + } + } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for FieldWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(&self.attrs); + self.vis.to_tokens(tokens); + if let Some(ident) = &self.ident { + ident.to_tokens(tokens); + TokensOrDefault(&self.colon_token).to_tokens(tokens); + } + self.ty.to_tokens(tokens); + if let Some((eq, default)) = &self.default { + eq.to_tokens(tokens); + default.to_tokens(tokens); + } + } + } } diff --git a/src/derive.rs b/src/derive.rs index 3443ecfc05..7deae74d6d 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -1,5 +1,7 @@ use crate::attr::Attribute; use crate::data::{Fields, FieldsNamed, Variant}; + +use crate::data::{FieldsWithDefault, VariantWithDefault}; use crate::generics::Generics; use crate::ident::Ident; use crate::punctuated::Punctuated; @@ -63,11 +65,67 @@ ast_struct! { } } +ast_struct! { + /// Data structure sent to a `proc_macro_derive` macro. + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + pub struct DeriveInputWithDefault { + pub attrs: Vec, + pub vis: Visibility, + pub ident: Ident, + pub generics: Generics, + pub data: DataWithDefault, + } +} + +ast_enum! { + /// The storage of a struct, enum or union data structure. + /// + /// This is a version of [`Data`](crate::Data), with added support for + /// the "default_field_values" Rust feature. + /// This is used by derive macros which wish to support default field values. + /// + /// # Syntax tree enum + /// + /// This type is a [syntax tree enum]. + /// + /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + pub enum DataWithDefault { + Struct(DataStructWithDefault), + Enum(DataEnumWithDefault), + Union(DataUnion), + } +} + +ast_struct! { + /// A struct input to a `proc_macro_derive` macro. + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + pub struct DataStructWithDefault { + pub struct_token: Token![struct], + pub fields: FieldsWithDefault, + pub semi_token: Option, + } +} + +ast_struct! { + /// An enum input to a `proc_macro_derive` macro. + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + pub struct DataEnumWithDefault { + pub enum_token: Token![enum], + pub brace_token: token::Brace, + pub variants: Punctuated, + } +} + #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; - use crate::data::{Fields, FieldsNamed, Variant}; - use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; + use crate::data::parsing::FieldsStruct; + use crate::data::FieldsNamed; + use crate::derive::{ + Data, DataEnum, DataEnumWithDefault, DataStruct, DataStructWithDefault, DataUnion, + DataWithDefault, DeriveInput, DeriveInputWithDefault, + }; use crate::error::Result; use crate::generics::{Generics, WhereClause}; use crate::ident::Ident; @@ -145,9 +203,78 @@ pub(crate) mod parsing { } } - pub(crate) fn data_struct( + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for DeriveInputWithDefault { + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let vis = input.parse::()?; + + let lookahead = input.lookahead1(); + if lookahead.peek(Token![struct]) { + let struct_token = input.parse::()?; + let ident = input.parse::()?; + let generics = input.parse::()?; + let (where_clause, fields, semi) = data_struct(input)?; + Ok(DeriveInputWithDefault { + attrs, + vis, + ident, + generics: Generics { + where_clause, + ..generics + }, + data: DataWithDefault::Struct(DataStructWithDefault { + struct_token, + fields, + semi_token: semi, + }), + }) + } else if lookahead.peek(Token![enum]) { + let enum_token = input.parse::()?; + let ident = input.parse::()?; + let generics = input.parse::()?; + let (where_clause, brace, variants) = data_enum(input)?; + Ok(DeriveInputWithDefault { + attrs, + vis, + ident, + generics: Generics { + where_clause, + ..generics + }, + data: DataWithDefault::Enum(DataEnumWithDefault { + enum_token, + brace_token: brace, + variants, + }), + }) + } else if lookahead.peek(Token![union]) { + let union_token = input.parse::()?; + let ident = input.parse::()?; + let generics = input.parse::()?; + let (where_clause, fields) = data_union(input)?; + Ok(DeriveInputWithDefault { + attrs, + vis, + ident, + generics: Generics { + where_clause, + ..generics + }, + data: DataWithDefault::Union(DataUnion { + union_token, + fields, + }), + }) + } else { + Err(lookahead.error()) + } + } + } + + pub(crate) fn data_struct( input: ParseStream, - ) -> Result<(Option, Fields, Option)> { + ) -> Result<(Option, F, Option)> { let mut lookahead = input.lookahead1(); let mut where_clause = None; if lookahead.peek(Token![where]) { @@ -166,33 +293,33 @@ pub(crate) mod parsing { if lookahead.peek(Token![;]) { let semi = input.parse()?; - Ok((where_clause, Fields::Unnamed(fields), Some(semi))) + Ok((where_clause, F::unnamed(fields), Some(semi))) } else { Err(lookahead.error()) } } else if lookahead.peek(token::Brace) { let fields = input.parse()?; - Ok((where_clause, Fields::Named(fields), None)) + Ok((where_clause, F::named(fields), None)) } else if lookahead.peek(Token![;]) { let semi = input.parse()?; - Ok((where_clause, Fields::Unit, Some(semi))) + Ok((where_clause, F::unit(), Some(semi))) } else { Err(lookahead.error()) } } - pub(crate) fn data_enum( + pub(crate) fn data_enum( input: ParseStream, ) -> Result<( Option, token::Brace, - Punctuated, + Punctuated, )> { let where_clause = input.parse()?; let content; let brace = braced!(content in input); - let variants = content.parse_terminated(Variant::parse, Token![,])?; + let variants = content.parse_terminated(Variants::parse, Token![,])?; Ok((where_clause, brace, variants)) } diff --git a/src/file.rs b/src/file.rs index 066f97b1a2..c33402e17e 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,5 +1,6 @@ use crate::attr::Attribute; use crate::item::Item; +use crate::ItemWithDefault; ast_struct! { /// A complete file of Rust source code. @@ -83,11 +84,27 @@ ast_struct! { } } +ast_struct! { + /// A complete file of Rust source code. + /// + /// Equivalent to [`File`], but with support for the `default_field_values` feature. + /// + /// Typically `FileWithDefault` objects are created with [`parse_file_with_default`]. + /// + /// [`parse_file_with_default`]: crate::parse_file_with_default + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + pub struct FileWithDefault { + pub shebang: Option, + pub attrs: Vec, + pub items: Vec, + } +} + #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::Result; - use crate::file::File; + use crate::file::{File, FileWithDefault}; use crate::parse::{Parse, ParseStream}; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] @@ -106,12 +123,29 @@ pub(crate) mod parsing { }) } } + + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for FileWithDefault { + fn parse(input: ParseStream) -> Result { + Ok(FileWithDefault { + shebang: None, + attrs: input.call(Attribute::parse_inner)?, + items: { + let mut items = Vec::new(); + while !input.is_empty() { + items.push(input.parse()?); + } + items + }, + }) + } + } } #[cfg(feature = "printing")] mod printing { - use crate::attr::FilterAttrs; use crate::file::File; + use crate::{attr::FilterAttrs, file::FileWithDefault}; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt as _}; @@ -122,4 +156,12 @@ mod printing { tokens.append_all(&self.items); } } + + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for FileWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(self.attrs.inner()); + tokens.append_all(&self.items); + } + } } diff --git a/src/gen/clone.rs b/src/gen/clone.rs index be2b698422..7ed369a513 100644 --- a/src/gen/clone.rs +++ b/src/gen/clone.rs @@ -202,6 +202,17 @@ impl Clone for crate::DataEnum { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::DataEnumWithDefault { + fn clone(&self) -> Self { + crate::DataEnumWithDefault { + enum_token: self.enum_token.clone(), + brace_token: self.brace_token.clone(), + variants: self.variants.clone(), + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DataStruct { fn clone(&self) -> Self { crate::DataStruct { @@ -213,6 +224,17 @@ impl Clone for crate::DataStruct { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::DataStructWithDefault { + fn clone(&self) -> Self { + crate::DataStructWithDefault { + struct_token: self.struct_token.clone(), + fields: self.fields.clone(), + semi_token: self.semi_token.clone(), + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DataUnion { fn clone(&self) -> Self { crate::DataUnion { @@ -223,6 +245,21 @@ impl Clone for crate::DataUnion { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::DataWithDefault { + fn clone(&self) -> Self { + match self { + crate::DataWithDefault::Struct(v0) => { + crate::DataWithDefault::Struct(v0.clone()) + } + crate::DataWithDefault::Enum(v0) => crate::DataWithDefault::Enum(v0.clone()), + crate::DataWithDefault::Union(v0) => { + crate::DataWithDefault::Union(v0.clone()) + } + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DeriveInput { fn clone(&self) -> Self { crate::DeriveInput { @@ -234,6 +271,19 @@ impl Clone for crate::DeriveInput { } } } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::DeriveInputWithDefault { + fn clone(&self) -> Self { + crate::DeriveInputWithDefault { + attrs: self.attrs.clone(), + vis: self.vis.clone(), + ident: self.ident.clone(), + generics: self.generics.clone(), + data: self.data.clone(), + } + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Expr { @@ -827,6 +877,21 @@ impl Clone for crate::FieldValue { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::FieldWithDefault { + fn clone(&self) -> Self { + crate::FieldWithDefault { + attrs: self.attrs.clone(), + vis: self.vis.clone(), + mutability: self.mutability.clone(), + ident: self.ident.clone(), + colon_token: self.colon_token.clone(), + ty: self.ty.clone(), + default: self.default.clone(), + } + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Fields { fn clone(&self) -> Self { match self { @@ -848,6 +913,16 @@ impl Clone for crate::FieldsNamed { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::FieldsNamedWithDefault { + fn clone(&self) -> Self { + crate::FieldsNamedWithDefault { + brace_token: self.brace_token.clone(), + named: self.named.clone(), + } + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FieldsUnnamed { fn clone(&self) -> Self { crate::FieldsUnnamed { @@ -856,6 +931,31 @@ impl Clone for crate::FieldsUnnamed { } } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::FieldsUnnamedWithDefault { + fn clone(&self) -> Self { + crate::FieldsUnnamedWithDefault { + paren_token: self.paren_token.clone(), + unnamed: self.unnamed.clone(), + } + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::FieldsWithDefault { + fn clone(&self) -> Self { + match self { + crate::FieldsWithDefault::Named(v0) => { + crate::FieldsWithDefault::Named(v0.clone()) + } + crate::FieldsWithDefault::Unnamed(v0) => { + crate::FieldsWithDefault::Unnamed(v0.clone()) + } + crate::FieldsWithDefault::Unit => crate::FieldsWithDefault::Unit, + } + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::File { @@ -869,6 +969,17 @@ impl Clone for crate::File { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::FileWithDefault { + fn clone(&self) -> Self { + crate::FileWithDefault { + shebang: self.shebang.clone(), + attrs: self.attrs.clone(), + items: self.items.clone(), + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FnArg { fn clone(&self) -> Self { match self { @@ -1141,6 +1252,21 @@ impl Clone for crate::ItemEnum { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::ItemEnumWithDefault { + fn clone(&self) -> Self { + crate::ItemEnumWithDefault { + attrs: self.attrs.clone(), + vis: self.vis.clone(), + enum_token: self.enum_token.clone(), + ident: self.ident.clone(), + generics: self.generics.clone(), + brace_token: self.brace_token.clone(), + variants: self.variants.clone(), + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemExternCrate { fn clone(&self) -> Self { crate::ItemExternCrate { @@ -1225,6 +1351,21 @@ impl Clone for crate::ItemMod { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::ItemModWithDefault { + fn clone(&self) -> Self { + crate::ItemModWithDefault { + attrs: self.attrs.clone(), + vis: self.vis.clone(), + unsafety: self.unsafety.clone(), + mod_token: self.mod_token.clone(), + ident: self.ident.clone(), + content: self.content.clone(), + semi: self.semi.clone(), + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemStatic { fn clone(&self) -> Self { crate::ItemStatic { @@ -1258,6 +1399,21 @@ impl Clone for crate::ItemStruct { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::ItemStructWithDefault { + fn clone(&self) -> Self { + crate::ItemStructWithDefault { + attrs: self.attrs.clone(), + vis: self.vis.clone(), + struct_token: self.struct_token.clone(), + ident: self.ident.clone(), + generics: self.generics.clone(), + fields: self.fields.clone(), + semi_token: self.semi_token.clone(), + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemTrait { fn clone(&self) -> Self { crate::ItemTrait { @@ -1338,6 +1494,26 @@ impl Clone for crate::ItemUse { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::ItemWithDefault { + fn clone(&self) -> Self { + match self { + crate::ItemWithDefault::StructWithDefault(v0) => { + crate::ItemWithDefault::StructWithDefault(v0.clone()) + } + crate::ItemWithDefault::EnumWithDefault(v0) => { + crate::ItemWithDefault::EnumWithDefault(v0.clone()) + } + crate::ItemWithDefault::ModWithDefault(v0) => { + crate::ItemWithDefault::ModWithDefault(v0.clone()) + } + crate::ItemWithDefault::Other(v0) => { + crate::ItemWithDefault::Other(v0.clone()) + } + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Label { fn clone(&self) -> Self { crate::Label { @@ -2220,6 +2396,18 @@ impl Clone for crate::Variant { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] +impl Clone for crate::VariantWithDefault { + fn clone(&self) -> Self { + crate::VariantWithDefault { + attrs: self.attrs.clone(), + ident: self.ident.clone(), + fields: self.fields.clone(), + discriminant: self.discriminant.clone(), + } + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::VisRestricted { fn clone(&self) -> Self { crate::VisRestricted { diff --git a/src/gen/debug.rs b/src/gen/debug.rs index aa42e32c60..095c9ebc1b 100644 --- a/src/gen/debug.rs +++ b/src/gen/debug.rs @@ -367,6 +367,17 @@ impl crate::DataEnum { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::DataEnumWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("DataEnumWithDefault"); + formatter.field("enum_token", &self.enum_token); + formatter.field("brace_token", &self.brace_token); + formatter.field("variants", &self.variants); + formatter.finish() + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DataStruct { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "DataStruct") @@ -384,6 +395,17 @@ impl crate::DataStruct { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::DataStructWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("DataStructWithDefault"); + formatter.field("struct_token", &self.struct_token); + formatter.field("fields", &self.fields); + formatter.field("semi_token", &self.semi_token); + formatter.finish() + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DataUnion { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "DataUnion") @@ -400,6 +422,30 @@ impl crate::DataUnion { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::DataWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("DataWithDefault::")?; + match self { + crate::DataWithDefault::Struct(v0) => { + let mut formatter = formatter.debug_tuple("Struct"); + formatter.field(v0); + formatter.finish() + } + crate::DataWithDefault::Enum(v0) => { + let mut formatter = formatter.debug_tuple("Enum"); + formatter.field(v0); + formatter.finish() + } + crate::DataWithDefault::Union(v0) => { + let mut formatter = formatter.debug_tuple("Union"); + formatter.field(v0); + formatter.finish() + } + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DeriveInput { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DeriveInput"); @@ -411,6 +457,19 @@ impl Debug for crate::DeriveInput { formatter.finish() } } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::DeriveInputWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("DeriveInputWithDefault"); + formatter.field("attrs", &self.attrs); + formatter.field("vis", &self.vis); + formatter.field("ident", &self.ident); + formatter.field("generics", &self.generics); + formatter.field("data", &self.data); + formatter.finish() + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Expr { @@ -1244,6 +1303,21 @@ impl Debug for crate::FieldValue { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::FieldWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FieldWithDefault"); + formatter.field("attrs", &self.attrs); + formatter.field("vis", &self.vis); + formatter.field("mutability", &self.mutability); + formatter.field("ident", &self.ident); + formatter.field("colon_token", &self.colon_token); + formatter.field("ty", &self.ty); + formatter.field("default", &self.default); + formatter.finish() + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Fields { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Fields::")?; @@ -1272,6 +1346,16 @@ impl crate::FieldsNamed { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::FieldsNamedWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FieldsNamedWithDefault"); + formatter.field("brace_token", &self.brace_token); + formatter.field("named", &self.named); + formatter.finish() + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FieldsUnnamed { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "FieldsUnnamed") @@ -1286,6 +1370,36 @@ impl crate::FieldsUnnamed { formatter.finish() } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::FieldsUnnamedWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FieldsUnnamedWithDefault"); + formatter.field("paren_token", &self.paren_token); + formatter.field("unnamed", &self.unnamed); + formatter.finish() + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::FieldsWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("FieldsWithDefault::")?; + match self { + crate::FieldsWithDefault::Named(v0) => { + let mut formatter = formatter.debug_tuple("Named"); + formatter.field(v0); + formatter.finish() + } + crate::FieldsWithDefault::Unnamed(v0) => { + let mut formatter = formatter.debug_tuple("Unnamed"); + formatter.field(v0); + formatter.finish() + } + crate::FieldsWithDefault::Unit => formatter.write_str("Unit"), + } + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::File { @@ -1299,6 +1413,17 @@ impl Debug for crate::File { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::FileWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FileWithDefault"); + formatter.field("shebang", &self.shebang); + formatter.field("attrs", &self.attrs); + formatter.field("items", &self.items); + formatter.finish() + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FnArg { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("FnArg::")?; @@ -1681,6 +1806,21 @@ impl crate::ItemEnum { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::ItemEnumWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ItemEnumWithDefault"); + formatter.field("attrs", &self.attrs); + formatter.field("vis", &self.vis); + formatter.field("enum_token", &self.enum_token); + formatter.field("ident", &self.ident); + formatter.field("generics", &self.generics); + formatter.field("brace_token", &self.brace_token); + formatter.field("variants", &self.variants); + formatter.finish() + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemExternCrate { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemExternCrate") @@ -1801,6 +1941,21 @@ impl crate::ItemMod { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::ItemModWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ItemModWithDefault"); + formatter.field("attrs", &self.attrs); + formatter.field("vis", &self.vis); + formatter.field("unsafety", &self.unsafety); + formatter.field("mod_token", &self.mod_token); + formatter.field("ident", &self.ident); + formatter.field("content", &self.content); + formatter.field("semi", &self.semi); + formatter.finish() + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemStatic { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemStatic") @@ -1846,6 +2001,21 @@ impl crate::ItemStruct { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::ItemStructWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ItemStructWithDefault"); + formatter.field("attrs", &self.attrs); + formatter.field("vis", &self.vis); + formatter.field("struct_token", &self.struct_token); + formatter.field("ident", &self.ident); + formatter.field("generics", &self.generics); + formatter.field("fields", &self.fields); + formatter.field("semi_token", &self.semi_token); + formatter.finish() + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemTrait { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemTrait") @@ -1956,6 +2126,35 @@ impl crate::ItemUse { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::ItemWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("ItemWithDefault::")?; + match self { + crate::ItemWithDefault::StructWithDefault(v0) => { + let mut formatter = formatter.debug_tuple("StructWithDefault"); + formatter.field(v0); + formatter.finish() + } + crate::ItemWithDefault::EnumWithDefault(v0) => { + let mut formatter = formatter.debug_tuple("EnumWithDefault"); + formatter.field(v0); + formatter.finish() + } + crate::ItemWithDefault::ModWithDefault(v0) => { + let mut formatter = formatter.debug_tuple("ModWithDefault"); + formatter.field(v0); + formatter.finish() + } + crate::ItemWithDefault::Other(v0) => { + let mut formatter = formatter.debug_tuple("Other"); + formatter.field(v0); + formatter.finish() + } + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Label { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Label"); @@ -3175,6 +3374,18 @@ impl Debug for crate::Variant { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Debug for crate::VariantWithDefault { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("VariantWithDefault"); + formatter.field("attrs", &self.attrs); + formatter.field("ident", &self.ident); + formatter.field("fields", &self.fields); + formatter.field("discriminant", &self.discriminant); + formatter.finish() + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::VisRestricted { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "VisRestricted") diff --git a/src/gen/eq.rs b/src/gen/eq.rs index 128e8991ee..0caad375f8 100644 --- a/src/gen/eq.rs +++ b/src/gen/eq.rs @@ -228,6 +228,16 @@ impl PartialEq for crate::DataEnum { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::DataEnumWithDefault {} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::DataEnumWithDefault { + fn eq(&self, other: &Self) -> bool { + self.variants == other.variants + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DataStruct {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -238,6 +248,16 @@ impl PartialEq for crate::DataStruct { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::DataStructWithDefault {} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::DataStructWithDefault { + fn eq(&self, other: &Self) -> bool { + self.fields == other.fields && self.semi_token == other.semi_token + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DataUnion {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -248,6 +268,30 @@ impl PartialEq for crate::DataUnion { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::DataWithDefault {} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::DataWithDefault { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + crate::DataWithDefault::Struct(self0), + crate::DataWithDefault::Struct(other0), + ) => self0 == other0, + ( + crate::DataWithDefault::Enum(self0), + crate::DataWithDefault::Enum(other0), + ) => self0 == other0, + ( + crate::DataWithDefault::Union(self0), + crate::DataWithDefault::Union(other0), + ) => self0 == other0, + _ => false, + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DeriveInput {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -257,6 +301,17 @@ impl PartialEq for crate::DeriveInput { && self.generics == other.generics && self.data == other.data } } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::DeriveInputWithDefault {} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::DeriveInputWithDefault { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident + && self.generics == other.generics && self.data == other.data + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Expr {} @@ -806,6 +861,19 @@ impl PartialEq for crate::FieldValue { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::FieldWithDefault {} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::FieldWithDefault { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.vis == other.vis + && self.mutability == other.mutability && self.ident == other.ident + && self.colon_token == other.colon_token && self.ty == other.ty + && self.default == other.default + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Fields {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -835,6 +903,16 @@ impl PartialEq for crate::FieldsNamed { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::FieldsNamedWithDefault {} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::FieldsNamedWithDefault { + fn eq(&self, other: &Self) -> bool { + self.named == other.named + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FieldsUnnamed {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -843,6 +921,37 @@ impl PartialEq for crate::FieldsUnnamed { self.unnamed == other.unnamed } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::FieldsUnnamedWithDefault {} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::FieldsUnnamedWithDefault { + fn eq(&self, other: &Self) -> bool { + self.unnamed == other.unnamed + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::FieldsWithDefault {} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::FieldsWithDefault { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + crate::FieldsWithDefault::Named(self0), + crate::FieldsWithDefault::Named(other0), + ) => self0 == other0, + ( + crate::FieldsWithDefault::Unnamed(self0), + crate::FieldsWithDefault::Unnamed(other0), + ) => self0 == other0, + (crate::FieldsWithDefault::Unit, crate::FieldsWithDefault::Unit) => true, + _ => false, + } + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::File {} @@ -856,6 +965,17 @@ impl PartialEq for crate::File { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::FileWithDefault {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::FileWithDefault { + fn eq(&self, other: &Self) -> bool { + self.shebang == other.shebang && self.attrs == other.attrs + && self.items == other.items + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FnArg {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -1155,6 +1275,17 @@ impl PartialEq for crate::ItemEnum { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::ItemEnumWithDefault {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::ItemEnumWithDefault { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident + && self.generics == other.generics && self.variants == other.variants + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemExternCrate {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -1224,6 +1355,18 @@ impl PartialEq for crate::ItemMod { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::ItemModWithDefault {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::ItemModWithDefault { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.vis == other.vis + && self.unsafety == other.unsafety && self.ident == other.ident + && self.content == other.content && self.semi == other.semi + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemStatic {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -1248,6 +1391,18 @@ impl PartialEq for crate::ItemStruct { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::ItemStructWithDefault {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::ItemStructWithDefault { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident + && self.generics == other.generics && self.fields == other.fields + && self.semi_token == other.semi_token + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemTrait {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -1306,6 +1461,34 @@ impl PartialEq for crate::ItemUse { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::ItemWithDefault {} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::ItemWithDefault { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + ( + crate::ItemWithDefault::StructWithDefault(self0), + crate::ItemWithDefault::StructWithDefault(other0), + ) => self0 == other0, + ( + crate::ItemWithDefault::EnumWithDefault(self0), + crate::ItemWithDefault::EnumWithDefault(other0), + ) => self0 == other0, + ( + crate::ItemWithDefault::ModWithDefault(self0), + crate::ItemWithDefault::ModWithDefault(other0), + ) => self0 == other0, + ( + crate::ItemWithDefault::Other(self0), + crate::ItemWithDefault::Other(other0), + ) => self0 == other0, + _ => false, + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Label {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] @@ -2249,6 +2432,17 @@ impl PartialEq for crate::Variant { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Eq for crate::VariantWithDefault {} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl PartialEq for crate::VariantWithDefault { + fn eq(&self, other: &Self) -> bool { + self.attrs == other.attrs && self.ident == other.ident + && self.fields == other.fields && self.discriminant == other.discriminant + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::VisRestricted {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] diff --git a/src/gen/fold.rs b/src/gen/fold.rs index 1f0afd3191..5bd2fc68e3 100644 --- a/src/gen/fold.rs +++ b/src/gen/fold.rs @@ -123,19 +123,51 @@ pub trait Fold { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn fold_data_enum_with_default( + &mut self, + i: crate::DataEnumWithDefault, + ) -> crate::DataEnumWithDefault { + fold_data_enum_with_default(self, i) + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_data_struct(&mut self, i: crate::DataStruct) -> crate::DataStruct { fold_data_struct(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn fold_data_struct_with_default( + &mut self, + i: crate::DataStructWithDefault, + ) -> crate::DataStructWithDefault { + fold_data_struct_with_default(self, i) + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_data_union(&mut self, i: crate::DataUnion) -> crate::DataUnion { fold_data_union(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn fold_data_with_default( + &mut self, + i: crate::DataWithDefault, + ) -> crate::DataWithDefault { + fold_data_with_default(self, i) + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_derive_input(&mut self, i: crate::DeriveInput) -> crate::DeriveInput { fold_derive_input(self, i) } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn fold_derive_input_with_default( + &mut self, + i: crate::DeriveInputWithDefault, + ) -> crate::DeriveInputWithDefault { + fold_derive_input_with_default(self, i) + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr(&mut self, i: crate::Expr) -> crate::Expr { @@ -364,6 +396,14 @@ pub trait Fold { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn fold_field_with_default( + &mut self, + i: crate::FieldWithDefault, + ) -> crate::FieldWithDefault { + fold_field_with_default(self, i) + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_fields(&mut self, i: crate::Fields) -> crate::Fields { fold_fields(self, i) } @@ -374,9 +414,33 @@ pub trait Fold { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn fold_fields_named_with_default( + &mut self, + i: crate::FieldsNamedWithDefault, + ) -> crate::FieldsNamedWithDefault { + fold_fields_named_with_default(self, i) + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_fields_unnamed(&mut self, i: crate::FieldsUnnamed) -> crate::FieldsUnnamed { fold_fields_unnamed(self, i) } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn fold_fields_unnamed_with_default( + &mut self, + i: crate::FieldsUnnamedWithDefault, + ) -> crate::FieldsUnnamedWithDefault { + fold_fields_unnamed_with_default(self, i) + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn fold_fields_with_default( + &mut self, + i: crate::FieldsWithDefault, + ) -> crate::FieldsWithDefault { + fold_fields_with_default(self, i) + } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_file(&mut self, i: crate::File) -> crate::File { @@ -384,6 +448,14 @@ pub trait Fold { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_file_with_default( + &mut self, + i: crate::FileWithDefault, + ) -> crate::FileWithDefault { + fold_file_with_default(self, i) + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_fn_arg(&mut self, i: crate::FnArg) -> crate::FnArg { fold_fn_arg(self, i) } @@ -497,6 +569,14 @@ pub trait Fold { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_item_enum_with_default( + &mut self, + i: crate::ItemEnumWithDefault, + ) -> crate::ItemEnumWithDefault { + fold_item_enum_with_default(self, i) + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_extern_crate( &mut self, i: crate::ItemExternCrate, @@ -533,6 +613,14 @@ pub trait Fold { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_item_mod_with_default( + &mut self, + i: crate::ItemModWithDefault, + ) -> crate::ItemModWithDefault { + fold_item_mod_with_default(self, i) + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_static(&mut self, i: crate::ItemStatic) -> crate::ItemStatic { fold_item_static(self, i) } @@ -543,6 +631,14 @@ pub trait Fold { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_item_struct_with_default( + &mut self, + i: crate::ItemStructWithDefault, + ) -> crate::ItemStructWithDefault { + fold_item_struct_with_default(self, i) + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_trait(&mut self, i: crate::ItemTrait) -> crate::ItemTrait { fold_item_trait(self, i) } @@ -571,6 +667,14 @@ pub trait Fold { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn fold_item_with_default( + &mut self, + i: crate::ItemWithDefault, + ) -> crate::ItemWithDefault { + fold_item_with_default(self, i) + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_label(&mut self, i: crate::Label) -> crate::Label { fold_label(self, i) } @@ -1001,6 +1105,14 @@ pub trait Fold { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn fold_variant_with_default( + &mut self, + i: crate::VariantWithDefault, + ) -> crate::VariantWithDefault { + fold_variant_with_default(self, i) + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_vis_restricted(&mut self, i: crate::VisRestricted) -> crate::VisRestricted { fold_vis_restricted(self, i) } @@ -1281,6 +1393,21 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn fold_data_enum_with_default( + f: &mut F, + node: crate::DataEnumWithDefault, +) -> crate::DataEnumWithDefault +where + F: Fold + ?Sized, +{ + crate::DataEnumWithDefault { + enum_token: node.enum_token, + brace_token: node.brace_token, + variants: crate::punctuated::fold(node.variants, f, F::fold_variant_with_default), + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_data_struct(f: &mut F, node: crate::DataStruct) -> crate::DataStruct where F: Fold + ?Sized, @@ -1293,6 +1420,21 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn fold_data_struct_with_default( + f: &mut F, + node: crate::DataStructWithDefault, +) -> crate::DataStructWithDefault +where + F: Fold + ?Sized, +{ + crate::DataStructWithDefault { + struct_token: node.struct_token, + fields: f.fold_fields_with_default(node.fields), + semi_token: node.semi_token, + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_data_union(f: &mut F, node: crate::DataUnion) -> crate::DataUnion where F: Fold + ?Sized, @@ -1304,6 +1446,27 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn fold_data_with_default( + f: &mut F, + node: crate::DataWithDefault, +) -> crate::DataWithDefault +where + F: Fold + ?Sized, +{ + match node { + crate::DataWithDefault::Struct(_binding_0) => { + crate::DataWithDefault::Struct(f.fold_data_struct_with_default(_binding_0)) + } + crate::DataWithDefault::Enum(_binding_0) => { + crate::DataWithDefault::Enum(f.fold_data_enum_with_default(_binding_0)) + } + crate::DataWithDefault::Union(_binding_0) => { + crate::DataWithDefault::Union(f.fold_data_union(_binding_0)) + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_derive_input(f: &mut F, node: crate::DeriveInput) -> crate::DeriveInput where F: Fold + ?Sized, @@ -1316,6 +1479,23 @@ where data: f.fold_data(node.data), } } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn fold_derive_input_with_default( + f: &mut F, + node: crate::DeriveInputWithDefault, +) -> crate::DeriveInputWithDefault +where + F: Fold + ?Sized, +{ + crate::DeriveInputWithDefault { + attrs: f.fold_attributes(node.attrs), + vis: f.fold_visibility(node.vis), + ident: f.fold_ident(node.ident), + generics: f.fold_generics(node.generics), + data: f.fold_data_with_default(node.data), + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr(f: &mut F, node: crate::Expr) -> crate::Expr @@ -2011,6 +2191,25 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn fold_field_with_default( + f: &mut F, + node: crate::FieldWithDefault, +) -> crate::FieldWithDefault +where + F: Fold + ?Sized, +{ + crate::FieldWithDefault { + attrs: f.fold_attributes(node.attrs), + vis: f.fold_visibility(node.vis), + mutability: f.fold_field_mutability(node.mutability), + ident: (node.ident).map(|it| f.fold_ident(it)), + colon_token: node.colon_token, + ty: f.fold_type(node.ty), + default: (node.default).map(|it| ((it).0, f.fold_expr((it).1))), + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_fields(f: &mut F, node: crate::Fields) -> crate::Fields where F: Fold + ?Sized, @@ -2038,6 +2237,20 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn fold_fields_named_with_default( + f: &mut F, + node: crate::FieldsNamedWithDefault, +) -> crate::FieldsNamedWithDefault +where + F: Fold + ?Sized, +{ + crate::FieldsNamedWithDefault { + brace_token: node.brace_token, + named: crate::punctuated::fold(node.named, f, F::fold_field_with_default), + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_fields_unnamed( f: &mut F, node: crate::FieldsUnnamed, @@ -2050,6 +2263,41 @@ where unnamed: crate::punctuated::fold(node.unnamed, f, F::fold_field), } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn fold_fields_unnamed_with_default( + f: &mut F, + node: crate::FieldsUnnamedWithDefault, +) -> crate::FieldsUnnamedWithDefault +where + F: Fold + ?Sized, +{ + crate::FieldsUnnamedWithDefault { + paren_token: node.paren_token, + unnamed: crate::punctuated::fold(node.unnamed, f, F::fold_field_with_default), + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn fold_fields_with_default( + f: &mut F, + node: crate::FieldsWithDefault, +) -> crate::FieldsWithDefault +where + F: Fold + ?Sized, +{ + match node { + crate::FieldsWithDefault::Named(_binding_0) => { + crate::FieldsWithDefault::Named(f.fold_fields_named_with_default(_binding_0)) + } + crate::FieldsWithDefault::Unnamed(_binding_0) => { + crate::FieldsWithDefault::Unnamed( + f.fold_fields_unnamed_with_default(_binding_0), + ) + } + crate::FieldsWithDefault::Unit => crate::FieldsWithDefault::Unit, + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_file(f: &mut F, node: crate::File) -> crate::File @@ -2064,6 +2312,21 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_file_with_default( + f: &mut F, + node: crate::FileWithDefault, +) -> crate::FileWithDefault +where + F: Fold + ?Sized, +{ + crate::FileWithDefault { + shebang: node.shebang, + attrs: f.fold_attributes(node.attrs), + items: fold_vec(node.items, f, F::fold_item_with_default), + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_fn_arg(f: &mut F, node: crate::FnArg) -> crate::FnArg where F: Fold + ?Sized, @@ -2441,6 +2704,25 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_item_enum_with_default( + f: &mut F, + node: crate::ItemEnumWithDefault, +) -> crate::ItemEnumWithDefault +where + F: Fold + ?Sized, +{ + crate::ItemEnumWithDefault { + attrs: f.fold_attributes(node.attrs), + vis: f.fold_visibility(node.vis), + enum_token: node.enum_token, + ident: f.fold_ident(node.ident), + generics: f.fold_generics(node.generics), + brace_token: node.brace_token, + variants: crate::punctuated::fold(node.variants, f, F::fold_variant_with_default), + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_extern_crate( f: &mut F, node: crate::ItemExternCrate, @@ -2537,6 +2819,26 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_item_mod_with_default( + f: &mut F, + node: crate::ItemModWithDefault, +) -> crate::ItemModWithDefault +where + F: Fold + ?Sized, +{ + crate::ItemModWithDefault { + attrs: f.fold_attributes(node.attrs), + vis: f.fold_visibility(node.vis), + unsafety: node.unsafety, + mod_token: node.mod_token, + ident: f.fold_ident(node.ident), + content: (node.content) + .map(|it| ((it).0, fold_vec((it).1, f, F::fold_item_with_default))), + semi: node.semi, + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_static(f: &mut F, node: crate::ItemStatic) -> crate::ItemStatic where F: Fold + ?Sized, @@ -2572,6 +2874,25 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_item_struct_with_default( + f: &mut F, + node: crate::ItemStructWithDefault, +) -> crate::ItemStructWithDefault +where + F: Fold + ?Sized, +{ + crate::ItemStructWithDefault { + attrs: f.fold_attributes(node.attrs), + vis: f.fold_visibility(node.vis), + struct_token: node.struct_token, + ident: f.fold_ident(node.ident), + generics: f.fold_generics(node.generics), + fields: f.fold_fields_with_default(node.fields), + semi_token: node.semi_token, + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_trait(f: &mut F, node: crate::ItemTrait) -> crate::ItemTrait where F: Fold + ?Sized, @@ -2664,6 +2985,36 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn fold_item_with_default( + f: &mut F, + node: crate::ItemWithDefault, +) -> crate::ItemWithDefault +where + F: Fold + ?Sized, +{ + match node { + crate::ItemWithDefault::StructWithDefault(_binding_0) => { + crate::ItemWithDefault::StructWithDefault( + f.fold_item_struct_with_default(_binding_0), + ) + } + crate::ItemWithDefault::EnumWithDefault(_binding_0) => { + crate::ItemWithDefault::EnumWithDefault( + f.fold_item_enum_with_default(_binding_0), + ) + } + crate::ItemWithDefault::ModWithDefault(_binding_0) => { + crate::ItemWithDefault::ModWithDefault( + f.fold_item_mod_with_default(_binding_0), + ) + } + crate::ItemWithDefault::Other(_binding_0) => { + crate::ItemWithDefault::Other(f.fold_item(_binding_0)) + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_label(f: &mut F, node: crate::Label) -> crate::Label where F: Fold + ?Sized, @@ -3835,6 +4186,22 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn fold_variant_with_default( + f: &mut F, + node: crate::VariantWithDefault, +) -> crate::VariantWithDefault +where + F: Fold + ?Sized, +{ + crate::VariantWithDefault { + attrs: f.fold_attributes(node.attrs), + ident: f.fold_ident(node.ident), + fields: f.fold_fields_with_default(node.fields), + discriminant: (node.discriminant).map(|it| ((it).0, f.fold_expr((it).1))), + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_vis_restricted( f: &mut F, node: crate::VisRestricted, diff --git a/src/gen/hash.rs b/src/gen/hash.rs index 04f23453a1..79971a1fb7 100644 --- a/src/gen/hash.rs +++ b/src/gen/hash.rs @@ -310,6 +310,16 @@ impl Hash for crate::DataEnum { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::DataEnumWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.variants.hash(state); + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DataStruct { fn hash(&self, state: &mut H) where @@ -321,6 +331,17 @@ impl Hash for crate::DataStruct { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::DataStructWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.fields.hash(state); + self.semi_token.hash(state); + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DataUnion { fn hash(&self, state: &mut H) where @@ -331,6 +352,29 @@ impl Hash for crate::DataUnion { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::DataWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + match self { + crate::DataWithDefault::Struct(v0) => { + state.write_u8(0u8); + v0.hash(state); + } + crate::DataWithDefault::Enum(v0) => { + state.write_u8(1u8); + v0.hash(state); + } + crate::DataWithDefault::Union(v0) => { + state.write_u8(2u8); + v0.hash(state); + } + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DeriveInput { fn hash(&self, state: &mut H) where @@ -343,6 +387,20 @@ impl Hash for crate::DeriveInput { self.data.hash(state); } } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::DeriveInputWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.vis.hash(state); + self.ident.hash(state); + self.generics.hash(state); + self.data.hash(state); + } +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Expr { @@ -1066,6 +1124,22 @@ impl Hash for crate::FieldValue { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::FieldWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.vis.hash(state); + self.mutability.hash(state); + self.ident.hash(state); + self.colon_token.hash(state); + self.ty.hash(state); + self.default.hash(state); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Fields { fn hash(&self, state: &mut H) where @@ -1098,6 +1172,16 @@ impl Hash for crate::FieldsNamed { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::FieldsNamedWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.named.hash(state); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FieldsUnnamed { fn hash(&self, state: &mut H) where @@ -1106,6 +1190,38 @@ impl Hash for crate::FieldsUnnamed { self.unnamed.hash(state); } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::FieldsUnnamedWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.unnamed.hash(state); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::FieldsWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + match self { + crate::FieldsWithDefault::Named(v0) => { + state.write_u8(0u8); + v0.hash(state); + } + crate::FieldsWithDefault::Unnamed(v0) => { + state.write_u8(1u8); + v0.hash(state); + } + crate::FieldsWithDefault::Unit => { + state.write_u8(2u8); + } + } + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::File { @@ -1120,6 +1236,18 @@ impl Hash for crate::File { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::FileWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.shebang.hash(state); + self.attrs.hash(state); + self.items.hash(state); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FnArg { fn hash(&self, state: &mut H) where @@ -1494,6 +1622,20 @@ impl Hash for crate::ItemEnum { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::ItemEnumWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.vis.hash(state); + self.ident.hash(state); + self.generics.hash(state); + self.variants.hash(state); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemExternCrate { fn hash(&self, state: &mut H) where @@ -1577,6 +1719,21 @@ impl Hash for crate::ItemMod { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::ItemModWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.vis.hash(state); + self.unsafety.hash(state); + self.ident.hash(state); + self.content.hash(state); + self.semi.hash(state); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemStatic { fn hash(&self, state: &mut H) where @@ -1607,6 +1764,21 @@ impl Hash for crate::ItemStruct { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::ItemStructWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.vis.hash(state); + self.ident.hash(state); + self.generics.hash(state); + self.fields.hash(state); + self.semi_token.hash(state); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemTrait { fn hash(&self, state: &mut H) where @@ -1681,6 +1853,33 @@ impl Hash for crate::ItemUse { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::ItemWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + match self { + crate::ItemWithDefault::StructWithDefault(v0) => { + state.write_u8(0u8); + v0.hash(state); + } + crate::ItemWithDefault::EnumWithDefault(v0) => { + state.write_u8(1u8); + v0.hash(state); + } + crate::ItemWithDefault::ModWithDefault(v0) => { + state.write_u8(2u8); + v0.hash(state); + } + crate::ItemWithDefault::Other(v0) => { + state.write_u8(3u8); + v0.hash(state); + } + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Label { fn hash(&self, state: &mut H) where @@ -2815,6 +3014,19 @@ impl Hash for crate::Variant { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] +impl Hash for crate::VariantWithDefault { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.attrs.hash(state); + self.ident.hash(state); + self.fields.hash(state); + self.discriminant.hash(state); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::VisRestricted { fn hash(&self, state: &mut H) where diff --git a/src/gen/visit.rs b/src/gen/visit.rs index cd258fcde1..4525b60619 100644 --- a/src/gen/visit.rs +++ b/src/gen/visit.rs @@ -116,19 +116,42 @@ pub trait Visit<'ast> { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_data_enum_with_default(&mut self, i: &'ast crate::DataEnumWithDefault) { + visit_data_enum_with_default(self, i); + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_struct(&mut self, i: &'ast crate::DataStruct) { visit_data_struct(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_data_struct_with_default(&mut self, i: &'ast crate::DataStructWithDefault) { + visit_data_struct_with_default(self, i); + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_union(&mut self, i: &'ast crate::DataUnion) { visit_data_union(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_data_with_default(&mut self, i: &'ast crate::DataWithDefault) { + visit_data_with_default(self, i); + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_derive_input(&mut self, i: &'ast crate::DeriveInput) { visit_derive_input(self, i); } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_derive_input_with_default( + &mut self, + i: &'ast crate::DeriveInputWithDefault, + ) { + visit_derive_input_with_default(self, i); + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr(&mut self, i: &'ast crate::Expr) { @@ -351,6 +374,11 @@ pub trait Visit<'ast> { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_field_with_default(&mut self, i: &'ast crate::FieldWithDefault) { + visit_field_with_default(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields(&mut self, i: &'ast crate::Fields) { visit_fields(self, i); } @@ -361,9 +389,30 @@ pub trait Visit<'ast> { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_fields_named_with_default( + &mut self, + i: &'ast crate::FieldsNamedWithDefault, + ) { + visit_fields_named_with_default(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_unnamed(&mut self, i: &'ast crate::FieldsUnnamed) { visit_fields_unnamed(self, i); } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_fields_unnamed_with_default( + &mut self, + i: &'ast crate::FieldsUnnamedWithDefault, + ) { + visit_fields_unnamed_with_default(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_fields_with_default(&mut self, i: &'ast crate::FieldsWithDefault) { + visit_fields_with_default(self, i); + } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_file(&mut self, i: &'ast crate::File) { @@ -371,6 +420,11 @@ pub trait Visit<'ast> { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_file_with_default(&mut self, i: &'ast crate::FileWithDefault) { + visit_file_with_default(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_fn_arg(&mut self, i: &'ast crate::FnArg) { visit_fn_arg(self, i); } @@ -469,6 +523,11 @@ pub trait Visit<'ast> { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_enum_with_default(&mut self, i: &'ast crate::ItemEnumWithDefault) { + visit_item_enum_with_default(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_extern_crate(&mut self, i: &'ast crate::ItemExternCrate) { visit_item_extern_crate(self, i); } @@ -499,6 +558,11 @@ pub trait Visit<'ast> { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_mod_with_default(&mut self, i: &'ast crate::ItemModWithDefault) { + visit_item_mod_with_default(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_static(&mut self, i: &'ast crate::ItemStatic) { visit_item_static(self, i); } @@ -509,6 +573,11 @@ pub trait Visit<'ast> { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_struct_with_default(&mut self, i: &'ast crate::ItemStructWithDefault) { + visit_item_struct_with_default(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_trait(&mut self, i: &'ast crate::ItemTrait) { visit_item_trait(self, i); } @@ -534,6 +603,11 @@ pub trait Visit<'ast> { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_with_default(&mut self, i: &'ast crate::ItemWithDefault) { + visit_item_with_default(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_label(&mut self, i: &'ast crate::Label) { visit_label(self, i); } @@ -924,6 +998,11 @@ pub trait Visit<'ast> { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_variant_with_default(&mut self, i: &'ast crate::VariantWithDefault) { + visit_variant_with_default(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_vis_restricted(&mut self, i: &'ast crate::VisRestricted) { visit_vis_restricted(self, i); } @@ -1270,6 +1349,22 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_data_enum_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::DataEnumWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + skip!(node.enum_token); + skip!(node.brace_token); + for el in Punctuated::pairs(&node.variants) { + let it = el.value(); + v.visit_variant_with_default(it); + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_struct<'ast, V>(v: &mut V, node: &'ast crate::DataStruct) where V: Visit<'ast> + ?Sized, @@ -1280,6 +1375,19 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_data_struct_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::DataStructWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + skip!(node.struct_token); + v.visit_fields_with_default(&node.fields); + skip!(node.semi_token); +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_union<'ast, V>(v: &mut V, node: &'ast crate::DataUnion) where V: Visit<'ast> + ?Sized, @@ -1289,6 +1397,24 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_data_with_default<'ast, V>(v: &mut V, node: &'ast crate::DataWithDefault) +where + V: Visit<'ast> + ?Sized, +{ + match node { + crate::DataWithDefault::Struct(_binding_0) => { + v.visit_data_struct_with_default(_binding_0); + } + crate::DataWithDefault::Enum(_binding_0) => { + v.visit_data_enum_with_default(_binding_0); + } + crate::DataWithDefault::Union(_binding_0) => { + v.visit_data_union(_binding_0); + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_derive_input<'ast, V>(v: &mut V, node: &'ast crate::DeriveInput) where V: Visit<'ast> + ?Sized, @@ -1301,6 +1427,23 @@ where v.visit_generics(&node.generics); v.visit_data(&node.data); } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_derive_input_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::DeriveInputWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + v.visit_visibility(&node.vis); + v.visit_ident(&node.ident); + v.visit_generics(&node.generics); + v.visit_data_with_default(&node.data); +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr<'ast, V>(v: &mut V, node: &'ast crate::Expr) @@ -2049,6 +2192,27 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_field_with_default<'ast, V>(v: &mut V, node: &'ast crate::FieldWithDefault) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + v.visit_visibility(&node.vis); + v.visit_field_mutability(&node.mutability); + if let Some(it) = &node.ident { + v.visit_ident(it); + } + skip!(node.colon_token); + v.visit_type(&node.ty); + if let Some(it) = &node.default { + skip!((it).0); + v.visit_expr(&(it).1); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields<'ast, V>(v: &mut V, node: &'ast crate::Fields) where V: Visit<'ast> + ?Sized, @@ -2077,6 +2241,21 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_fields_named_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::FieldsNamedWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + skip!(node.brace_token); + for el in Punctuated::pairs(&node.named) { + let it = el.value(); + v.visit_field_with_default(it); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_unnamed<'ast, V>(v: &mut V, node: &'ast crate::FieldsUnnamed) where V: Visit<'ast> + ?Sized, @@ -2087,6 +2266,40 @@ where v.visit_field(it); } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_fields_unnamed_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::FieldsUnnamedWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + skip!(node.paren_token); + for el in Punctuated::pairs(&node.unnamed) { + let it = el.value(); + v.visit_field_with_default(it); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_fields_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::FieldsWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + match node { + crate::FieldsWithDefault::Named(_binding_0) => { + v.visit_fields_named_with_default(_binding_0); + } + crate::FieldsWithDefault::Unnamed(_binding_0) => { + v.visit_fields_unnamed_with_default(_binding_0); + } + crate::FieldsWithDefault::Unit => {} + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_file<'ast, V>(v: &mut V, node: &'ast crate::File) @@ -2103,6 +2316,20 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_file_with_default<'ast, V>(v: &mut V, node: &'ast crate::FileWithDefault) +where + V: Visit<'ast> + ?Sized, +{ + skip!(node.shebang); + for it in &node.attrs { + v.visit_attribute(it); + } + for it in &node.items { + v.visit_item_with_default(it); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_fn_arg<'ast, V>(v: &mut V, node: &'ast crate::FnArg) where V: Visit<'ast> + ?Sized, @@ -2469,6 +2696,28 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_enum_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::ItemEnumWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + v.visit_visibility(&node.vis); + skip!(node.enum_token); + v.visit_ident(&node.ident); + v.visit_generics(&node.generics); + skip!(node.brace_token); + for el in Punctuated::pairs(&node.variants) { + let it = el.value(); + v.visit_variant_with_default(it); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_extern_crate<'ast, V>(v: &mut V, node: &'ast crate::ItemExternCrate) where V: Visit<'ast> + ?Sized, @@ -2577,6 +2826,30 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_mod_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::ItemModWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + v.visit_visibility(&node.vis); + skip!(node.unsafety); + skip!(node.mod_token); + v.visit_ident(&node.ident); + if let Some(it) = &node.content { + skip!((it).0); + for it in &(it).1 { + v.visit_item_with_default(it); + } + } + skip!(node.semi); +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_static<'ast, V>(v: &mut V, node: &'ast crate::ItemStatic) where V: Visit<'ast> + ?Sized, @@ -2612,6 +2885,25 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_struct_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::ItemStructWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + v.visit_visibility(&node.vis); + skip!(node.struct_token); + v.visit_ident(&node.ident); + v.visit_generics(&node.generics); + v.visit_fields_with_default(&node.fields); + skip!(node.semi_token); +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_trait<'ast, V>(v: &mut V, node: &'ast crate::ItemTrait) where V: Visit<'ast> + ?Sized, @@ -2707,6 +2999,27 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_with_default<'ast, V>(v: &mut V, node: &'ast crate::ItemWithDefault) +where + V: Visit<'ast> + ?Sized, +{ + match node { + crate::ItemWithDefault::StructWithDefault(_binding_0) => { + v.visit_item_struct_with_default(_binding_0); + } + crate::ItemWithDefault::EnumWithDefault(_binding_0) => { + v.visit_item_enum_with_default(_binding_0); + } + crate::ItemWithDefault::ModWithDefault(_binding_0) => { + v.visit_item_mod_with_default(_binding_0); + } + crate::ItemWithDefault::Other(_binding_0) => { + v.visit_item(_binding_0); + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_label<'ast, V>(v: &mut V, node: &'ast crate::Label) where V: Visit<'ast> + ?Sized, @@ -3887,6 +4200,25 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_variant_with_default<'ast, V>( + v: &mut V, + node: &'ast crate::VariantWithDefault, +) +where + V: Visit<'ast> + ?Sized, +{ + for it in &node.attrs { + v.visit_attribute(it); + } + v.visit_ident(&node.ident); + v.visit_fields_with_default(&node.fields); + if let Some(it) = &node.discriminant { + skip!((it).0); + v.visit_expr(&(it).1); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_vis_restricted<'ast, V>(v: &mut V, node: &'ast crate::VisRestricted) where V: Visit<'ast> + ?Sized, diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs index 2bbd6895db..0138b769c5 100644 --- a/src/gen/visit_mut.rs +++ b/src/gen/visit_mut.rs @@ -124,19 +124,45 @@ pub trait VisitMut { } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_data_enum_with_default_mut(&mut self, i: &mut crate::DataEnumWithDefault) { + visit_data_enum_with_default_mut(self, i); + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_struct_mut(&mut self, i: &mut crate::DataStruct) { visit_data_struct_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_data_struct_with_default_mut( + &mut self, + i: &mut crate::DataStructWithDefault, + ) { + visit_data_struct_with_default_mut(self, i); + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_union_mut(&mut self, i: &mut crate::DataUnion) { visit_data_union_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_data_with_default_mut(&mut self, i: &mut crate::DataWithDefault) { + visit_data_with_default_mut(self, i); + } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_derive_input_mut(&mut self, i: &mut crate::DeriveInput) { visit_derive_input_mut(self, i); } + #[cfg(feature = "derive")] + #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] + fn visit_derive_input_with_default_mut( + &mut self, + i: &mut crate::DeriveInputWithDefault, + ) { + visit_derive_input_with_default_mut(self, i); + } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_mut(&mut self, i: &mut crate::Expr) { @@ -359,6 +385,11 @@ pub trait VisitMut { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_field_with_default_mut(&mut self, i: &mut crate::FieldWithDefault) { + visit_field_with_default_mut(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_mut(&mut self, i: &mut crate::Fields) { visit_fields_mut(self, i); } @@ -369,9 +400,30 @@ pub trait VisitMut { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_fields_named_with_default_mut( + &mut self, + i: &mut crate::FieldsNamedWithDefault, + ) { + visit_fields_named_with_default_mut(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_unnamed_mut(&mut self, i: &mut crate::FieldsUnnamed) { visit_fields_unnamed_mut(self, i); } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_fields_unnamed_with_default_mut( + &mut self, + i: &mut crate::FieldsUnnamedWithDefault, + ) { + visit_fields_unnamed_with_default_mut(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_fields_with_default_mut(&mut self, i: &mut crate::FieldsWithDefault) { + visit_fields_with_default_mut(self, i); + } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_file_mut(&mut self, i: &mut crate::File) { @@ -379,6 +431,11 @@ pub trait VisitMut { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_file_with_default_mut(&mut self, i: &mut crate::FileWithDefault) { + visit_file_with_default_mut(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_fn_arg_mut(&mut self, i: &mut crate::FnArg) { visit_fn_arg_mut(self, i); } @@ -477,6 +534,11 @@ pub trait VisitMut { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_enum_with_default_mut(&mut self, i: &mut crate::ItemEnumWithDefault) { + visit_item_enum_with_default_mut(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_extern_crate_mut(&mut self, i: &mut crate::ItemExternCrate) { visit_item_extern_crate_mut(self, i); } @@ -507,6 +569,11 @@ pub trait VisitMut { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_mod_with_default_mut(&mut self, i: &mut crate::ItemModWithDefault) { + visit_item_mod_with_default_mut(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_static_mut(&mut self, i: &mut crate::ItemStatic) { visit_item_static_mut(self, i); } @@ -517,6 +584,14 @@ pub trait VisitMut { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_struct_with_default_mut( + &mut self, + i: &mut crate::ItemStructWithDefault, + ) { + visit_item_struct_with_default_mut(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_trait_mut(&mut self, i: &mut crate::ItemTrait) { visit_item_trait_mut(self, i); } @@ -542,6 +617,11 @@ pub trait VisitMut { } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + fn visit_item_with_default_mut(&mut self, i: &mut crate::ItemWithDefault) { + visit_item_with_default_mut(self, i); + } + #[cfg(feature = "full")] + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_label_mut(&mut self, i: &mut crate::Label) { visit_label_mut(self, i); } @@ -932,6 +1012,11 @@ pub trait VisitMut { } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] + fn visit_variant_with_default_mut(&mut self, i: &mut crate::VariantWithDefault) { + visit_variant_with_default_mut(self, i); + } + #[cfg(any(feature = "derive", feature = "full"))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_vis_restricted_mut(&mut self, i: &mut crate::VisRestricted) { visit_vis_restricted_mut(self, i); } @@ -1270,6 +1355,22 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_data_enum_with_default_mut( + v: &mut V, + node: &mut crate::DataEnumWithDefault, +) +where + V: VisitMut + ?Sized, +{ + skip!(node.enum_token); + skip!(node.brace_token); + for mut el in Punctuated::pairs_mut(&mut node.variants) { + let it = el.value_mut(); + v.visit_variant_with_default_mut(it); + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_struct_mut(v: &mut V, node: &mut crate::DataStruct) where V: VisitMut + ?Sized, @@ -1280,6 +1381,19 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_data_struct_with_default_mut( + v: &mut V, + node: &mut crate::DataStructWithDefault, +) +where + V: VisitMut + ?Sized, +{ + skip!(node.struct_token); + v.visit_fields_with_default_mut(&mut node.fields); + skip!(node.semi_token); +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_union_mut(v: &mut V, node: &mut crate::DataUnion) where V: VisitMut + ?Sized, @@ -1289,6 +1403,24 @@ where } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_data_with_default_mut(v: &mut V, node: &mut crate::DataWithDefault) +where + V: VisitMut + ?Sized, +{ + match node { + crate::DataWithDefault::Struct(_binding_0) => { + v.visit_data_struct_with_default_mut(_binding_0); + } + crate::DataWithDefault::Enum(_binding_0) => { + v.visit_data_enum_with_default_mut(_binding_0); + } + crate::DataWithDefault::Union(_binding_0) => { + v.visit_data_union_mut(_binding_0); + } + } +} +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_derive_input_mut(v: &mut V, node: &mut crate::DeriveInput) where V: VisitMut + ?Sized, @@ -1299,6 +1431,21 @@ where v.visit_generics_mut(&mut node.generics); v.visit_data_mut(&mut node.data); } +#[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub fn visit_derive_input_with_default_mut( + v: &mut V, + node: &mut crate::DeriveInputWithDefault, +) +where + V: VisitMut + ?Sized, +{ + v.visit_attributes_mut(&mut node.attrs); + v.visit_visibility_mut(&mut node.vis); + v.visit_ident_mut(&mut node.ident); + v.visit_generics_mut(&mut node.generics); + v.visit_data_with_default_mut(&mut node.data); +} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_mut(v: &mut V, node: &mut crate::Expr) @@ -1963,6 +2110,25 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_field_with_default_mut(v: &mut V, node: &mut crate::FieldWithDefault) +where + V: VisitMut + ?Sized, +{ + v.visit_attributes_mut(&mut node.attrs); + v.visit_visibility_mut(&mut node.vis); + v.visit_field_mutability_mut(&mut node.mutability); + if let Some(it) = &mut node.ident { + v.visit_ident_mut(it); + } + skip!(node.colon_token); + v.visit_type_mut(&mut node.ty); + if let Some(it) = &mut node.default { + skip!((it).0); + v.visit_expr_mut(&mut (it).1); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_mut(v: &mut V, node: &mut crate::Fields) where V: VisitMut + ?Sized, @@ -1991,6 +2157,21 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_fields_named_with_default_mut( + v: &mut V, + node: &mut crate::FieldsNamedWithDefault, +) +where + V: VisitMut + ?Sized, +{ + skip!(node.brace_token); + for mut el in Punctuated::pairs_mut(&mut node.named) { + let it = el.value_mut(); + v.visit_field_with_default_mut(it); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_unnamed_mut(v: &mut V, node: &mut crate::FieldsUnnamed) where V: VisitMut + ?Sized, @@ -2001,6 +2182,37 @@ where v.visit_field_mut(it); } } +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_fields_unnamed_with_default_mut( + v: &mut V, + node: &mut crate::FieldsUnnamedWithDefault, +) +where + V: VisitMut + ?Sized, +{ + skip!(node.paren_token); + for mut el in Punctuated::pairs_mut(&mut node.unnamed) { + let it = el.value_mut(); + v.visit_field_with_default_mut(it); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_fields_with_default_mut(v: &mut V, node: &mut crate::FieldsWithDefault) +where + V: VisitMut + ?Sized, +{ + match node { + crate::FieldsWithDefault::Named(_binding_0) => { + v.visit_fields_named_with_default_mut(_binding_0); + } + crate::FieldsWithDefault::Unnamed(_binding_0) => { + v.visit_fields_unnamed_with_default_mut(_binding_0); + } + crate::FieldsWithDefault::Unit => {} + } +} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_file_mut(v: &mut V, node: &mut crate::File) @@ -2015,6 +2227,18 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_file_with_default_mut(v: &mut V, node: &mut crate::FileWithDefault) +where + V: VisitMut + ?Sized, +{ + skip!(node.shebang); + v.visit_attributes_mut(&mut node.attrs); + for it in &mut node.items { + v.visit_item_with_default_mut(it); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_fn_arg_mut(v: &mut V, node: &mut crate::FnArg) where V: VisitMut + ?Sized, @@ -2360,6 +2584,26 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_enum_with_default_mut( + v: &mut V, + node: &mut crate::ItemEnumWithDefault, +) +where + V: VisitMut + ?Sized, +{ + v.visit_attributes_mut(&mut node.attrs); + v.visit_visibility_mut(&mut node.vis); + skip!(node.enum_token); + v.visit_ident_mut(&mut node.ident); + v.visit_generics_mut(&mut node.generics); + skip!(node.brace_token); + for mut el in Punctuated::pairs_mut(&mut node.variants) { + let it = el.value_mut(); + v.visit_variant_with_default_mut(it); + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_extern_crate_mut(v: &mut V, node: &mut crate::ItemExternCrate) where V: VisitMut + ?Sized, @@ -2456,6 +2700,28 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_mod_with_default_mut( + v: &mut V, + node: &mut crate::ItemModWithDefault, +) +where + V: VisitMut + ?Sized, +{ + v.visit_attributes_mut(&mut node.attrs); + v.visit_visibility_mut(&mut node.vis); + skip!(node.unsafety); + skip!(node.mod_token); + v.visit_ident_mut(&mut node.ident); + if let Some(it) = &mut node.content { + skip!((it).0); + for it in &mut (it).1 { + v.visit_item_with_default_mut(it); + } + } + skip!(node.semi); +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_static_mut(v: &mut V, node: &mut crate::ItemStatic) where V: VisitMut + ?Sized, @@ -2487,6 +2753,23 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_struct_with_default_mut( + v: &mut V, + node: &mut crate::ItemStructWithDefault, +) +where + V: VisitMut + ?Sized, +{ + v.visit_attributes_mut(&mut node.attrs); + v.visit_visibility_mut(&mut node.vis); + skip!(node.struct_token); + v.visit_ident_mut(&mut node.ident); + v.visit_generics_mut(&mut node.generics); + v.visit_fields_with_default_mut(&mut node.fields); + skip!(node.semi_token); +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_trait_mut(v: &mut V, node: &mut crate::ItemTrait) where V: VisitMut + ?Sized, @@ -2572,6 +2855,27 @@ where } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] +pub fn visit_item_with_default_mut(v: &mut V, node: &mut crate::ItemWithDefault) +where + V: VisitMut + ?Sized, +{ + match node { + crate::ItemWithDefault::StructWithDefault(_binding_0) => { + v.visit_item_struct_with_default_mut(_binding_0); + } + crate::ItemWithDefault::EnumWithDefault(_binding_0) => { + v.visit_item_enum_with_default_mut(_binding_0); + } + crate::ItemWithDefault::ModWithDefault(_binding_0) => { + v.visit_item_mod_with_default_mut(_binding_0); + } + crate::ItemWithDefault::Other(_binding_0) => { + v.visit_item_mut(_binding_0); + } + } +} +#[cfg(feature = "full")] +#[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_label_mut(v: &mut V, node: &mut crate::Label) where V: VisitMut + ?Sized, @@ -3705,6 +4009,20 @@ where } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] +pub fn visit_variant_with_default_mut(v: &mut V, node: &mut crate::VariantWithDefault) +where + V: VisitMut + ?Sized, +{ + v.visit_attributes_mut(&mut node.attrs); + v.visit_ident_mut(&mut node.ident); + v.visit_fields_with_default_mut(&mut node.fields); + if let Some(it) = &mut node.discriminant { + skip!((it).0); + v.visit_expr_mut(&mut (it).1); + } +} +#[cfg(any(feature = "derive", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_vis_restricted_mut(v: &mut V, node: &mut crate::VisRestricted) where V: VisitMut + ?Sized, diff --git a/src/item.rs b/src/item.rs index 00beb0d368..b4dbb4d5ce 100644 --- a/src/item.rs +++ b/src/item.rs @@ -1,6 +1,11 @@ use crate::attr::Attribute; use crate::data::{Fields, FieldsNamed, Variant}; -use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; + +use crate::data::{FieldsWithDefault, VariantWithDefault}; +use crate::derive::{ + Data, DataEnum, DataEnumWithDefault, DataStruct, DataStructWithDefault, DataUnion, + DataWithDefault, DeriveInput, DeriveInputWithDefault, +}; use crate::expr::Expr; use crate::generics::{Generics, TypeParamBound}; use crate::ident::Ident; @@ -17,6 +22,17 @@ use proc_macro2::TokenStream; #[cfg(feature = "parsing")] use std::mem; +ast_enum_of_structs! { + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + #[non_exhaustive] + pub enum ItemWithDefault { + StructWithDefault(ItemStructWithDefault), + EnumWithDefault(ItemEnumWithDefault), + ModWithDefault(ItemModWithDefault), + Other(Item), + } +} + ast_enum_of_structs! { /// Things that can appear directly inside of a module or scope. /// @@ -129,6 +145,22 @@ ast_struct! { } } +ast_struct! { + /// An enum definition: `enum Foo { A(A), B(B) }`. + /// + /// The variants of this enum can have default field values. + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + pub struct ItemEnumWithDefault { + pub attrs: Vec, + pub vis: Visibility, + pub enum_token: Token![enum], + pub ident: Ident, + pub generics: Generics, + pub brace_token: token::Brace, + pub variants: Punctuated, + } +} + ast_struct! { /// An `extern crate` item: `extern crate serde`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] @@ -211,6 +243,20 @@ ast_struct! { } } +ast_struct! { + /// A module or module declaration: `mod m` or `mod m { ... }`. + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + pub struct ItemModWithDefault { + pub attrs: Vec, + pub vis: Visibility, + pub unsafety: Option, + pub mod_token: Token![mod], + pub ident: Ident, + pub content: Option<(token::Brace, Vec)>, + pub semi: Option, + } +} + ast_struct! { /// A static item: `static BIKE: Shed = Shed(42)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] @@ -242,6 +288,20 @@ ast_struct! { } } +ast_struct! { + /// A struct definition: `struct Foo { x: A }`. + #[cfg_attr(docsrs, doc(cfg(feature = "full")))] + pub struct ItemStructWithDefault { + pub attrs: Vec, + pub vis: Visibility, + pub struct_token: Token![struct], + pub ident: Ident, + pub generics: Generics, + pub fields: FieldsWithDefault, + pub semi_token: Option, + } +} + ast_struct! { /// A trait definition: `pub trait Iterator { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] @@ -421,6 +481,88 @@ impl From for DeriveInput { } } +impl From for ItemWithDefault { + fn from(input: DeriveInputWithDefault) -> ItemWithDefault { + match input.data { + DataWithDefault::Struct(data) => { + ItemWithDefault::StructWithDefault(ItemStructWithDefault { + attrs: input.attrs, + vis: input.vis, + struct_token: data.struct_token, + ident: input.ident, + generics: input.generics, + fields: data.fields, + semi_token: data.semi_token, + }) + } + DataWithDefault::Enum(data) => ItemWithDefault::EnumWithDefault(ItemEnumWithDefault { + attrs: input.attrs, + vis: input.vis, + enum_token: data.enum_token, + ident: input.ident, + generics: input.generics, + brace_token: data.brace_token, + variants: data.variants, + }), + DataWithDefault::Union(data) => ItemWithDefault::Other(Item::Union(ItemUnion { + attrs: input.attrs, + vis: input.vis, + union_token: data.union_token, + ident: input.ident, + generics: input.generics, + fields: data.fields, + })), + } + } +} + +impl From for DeriveInputWithDefault { + fn from(input: ItemStructWithDefault) -> DeriveInputWithDefault { + DeriveInputWithDefault { + attrs: input.attrs, + vis: input.vis, + ident: input.ident, + generics: input.generics, + data: DataWithDefault::Struct(DataStructWithDefault { + struct_token: input.struct_token, + fields: input.fields, + semi_token: input.semi_token, + }), + } + } +} + +impl From for DeriveInputWithDefault { + fn from(input: ItemEnumWithDefault) -> DeriveInputWithDefault { + DeriveInputWithDefault { + attrs: input.attrs, + vis: input.vis, + ident: input.ident, + generics: input.generics, + data: DataWithDefault::Enum(DataEnumWithDefault { + enum_token: input.enum_token, + brace_token: input.brace_token, + variants: input.variants, + }), + } + } +} + +impl From for DeriveInputWithDefault { + fn from(input: ItemUnion) -> DeriveInputWithDefault { + DeriveInputWithDefault { + attrs: input.attrs, + vis: input.vis, + ident: input.ident, + generics: input.generics, + data: DataWithDefault::Union(DataUnion { + union_token: input.union_token, + fields: input.fields, + }), + } + } +} + ast_enum_of_structs! { /// A suffix of an import tree in a `use` item: `Type as Renamed` or `*`. /// @@ -914,8 +1056,9 @@ pub(crate) mod parsing { use crate::item::{ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item, ItemConst, - ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, - ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, + ItemEnum, ItemEnumWithDefault, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, + ItemMacro, ItemMod, ItemModWithDefault, ItemStatic, ItemStruct, ItemStructWithDefault, + ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, ItemWithDefault, Receiver, Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic, }; @@ -943,6 +1086,47 @@ pub(crate) mod parsing { } } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for ItemWithDefault { + fn parse(input: ParseStream) -> Result { + let begin = input.fork(); + let attrs = input.call(Attribute::parse_outer)?; + parse_rest_of_item_with_default(begin, attrs, input) + } + } + + pub(crate) fn parse_rest_of_item_with_default( + begin: ParseBuffer, + mut attrs: Vec, + input: ParseStream, + ) -> Result { + let ahead = input.fork(); + let _vis: Visibility = ahead.parse()?; + + let lookahead = ahead.lookahead1(); + if lookahead.peek(Token![struct]) { + let mut item: ItemStructWithDefault = input.parse()?; + // This line is defensive; structs don't support inner attributes. + attrs.extend(item.attrs); + item.attrs = attrs; + Ok(ItemWithDefault::StructWithDefault(item)) + } else if lookahead.peek(Token![enum]) { + let mut item: ItemEnumWithDefault = input.parse()?; + // This line is defensive; enums don't support inner attributes. + attrs.extend(item.attrs); + item.attrs = attrs; + Ok(ItemWithDefault::EnumWithDefault(item)) + } else if lookahead.peek(Token![mod]) { + let mut item: ItemModWithDefault = input.parse()?; + // This line is *not* defensive; modules do support inner attributes! + attrs.extend(item.attrs); + item.attrs = attrs; + input.parse().map(ItemWithDefault::ModWithDefault) + } else { + parse_rest_of_item(begin, attrs, input).map(ItemWithDefault::Other) + } + } + pub(crate) fn parse_rest_of_item( begin: ParseBuffer, mut attrs: Vec, @@ -1764,19 +1948,62 @@ pub(crate) mod parsing { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemMod { fn parse(input: ParseStream) -> Result { - let mut attrs = input.call(Attribute::parse_outer)?; - let vis: Visibility = input.parse()?; - let unsafety: Option = input.parse()?; - let mod_token: Token![mod] = input.parse()?; - let ident: Ident = if input.peek(Token![try]) { - input.call(Ident::parse_any) - } else { - input.parse() - }?; + let (mut module, items) = parse_module(input)?; + module.content = items; + Ok(module) + } + } - let lookahead = input.lookahead1(); - if lookahead.peek(Token![;]) { - Ok(ItemMod { + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for ItemModWithDefault { + fn parse(input: ParseStream) -> Result { + let ( + ItemMod { + attrs, + vis, + unsafety, + mod_token, + ident, + semi, + content: _, + }, + items, + ) = parse_module(input)?; + Ok(ItemModWithDefault { + attrs, + vis, + unsafety, + mod_token, + ident, + content: items, + semi, + }) + } + } + + /// Attempt to parse a module declaration. + /// Parses the module's content as `Content`; this allows sharing the same code for default field values + /// internally, whilst still supporting all the properties of modules. + /// + /// The `content` field of the returned value will always be `None`. + #[allow(clippy::type_complexity)] + fn parse_module( + input: &ParseBuffer<'_>, + ) -> Result<(ItemMod, Option<(token::Brace, Vec)>)> { + let mut attrs = input.call(Attribute::parse_outer)?; + let vis: Visibility = input.parse()?; + let unsafety: Option = input.parse()?; + let mod_token: Token![mod] = input.parse()?; + let ident: Ident = if input.peek(Token![try]) { + input.call(Ident::parse_any) + } else { + input.parse() + }?; + + let lookahead = input.lookahead1(); + if lookahead.peek(Token![;]) { + Ok(( + ItemMod { attrs, vis, unsafety, @@ -1784,29 +2011,33 @@ pub(crate) mod parsing { ident, content: None, semi: Some(input.parse()?), - }) - } else if lookahead.peek(token::Brace) { - let content; - let brace_token = braced!(content in input); - attr::parsing::parse_inner(&content, &mut attrs)?; + }, + None, + )) + } else if lookahead.peek(token::Brace) { + let content; + let brace_token = braced!(content in input); + attr::parsing::parse_inner(&content, &mut attrs)?; - let mut items = Vec::new(); - while !content.is_empty() { - items.push(content.parse()?); - } + let mut items = Vec::new(); + while !content.is_empty() { + items.push(content.parse()?); + } - Ok(ItemMod { + Ok(( + ItemMod { attrs, vis, unsafety, mod_token, ident, - content: Some((brace_token, items)), + content: None, semi: None, - }) - } else { - Err(lookahead.error()) - } + }, + Some((brace_token, items)), + )) + } else { + Err(lookahead.error()) } } @@ -2111,6 +2342,30 @@ pub(crate) mod parsing { } } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for ItemStructWithDefault { + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let vis = input.parse::()?; + let struct_token = input.parse::()?; + let ident = input.parse::()?; + let generics = input.parse::()?; + let (where_clause, fields, semi_token) = derive::parsing::data_struct(input)?; + Ok(ItemStructWithDefault { + attrs, + vis, + struct_token, + ident, + generics: Generics { + where_clause, + ..generics + }, + fields, + semi_token, + }) + } + } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemEnum { fn parse(input: ParseStream) -> Result { @@ -2135,6 +2390,30 @@ pub(crate) mod parsing { } } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] + impl Parse for ItemEnumWithDefault { + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let vis = input.parse::()?; + let enum_token = input.parse::()?; + let ident = input.parse::()?; + let generics = input.parse::()?; + let (where_clause, brace_token, variants) = derive::parsing::data_enum(input)?; + Ok(ItemEnumWithDefault { + attrs, + vis, + enum_token, + ident, + generics: Generics { + where_clause, + ..generics + }, + brace_token, + variants, + }) + } + } + #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemUnion { fn parse(input: ParseStream) -> Result { @@ -2935,16 +3214,16 @@ mod printing { use crate::item::{ ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, ItemConst, ItemEnum, ItemExternCrate, ItemFn, - ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait, - ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, StaticMutability, - TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName, - UsePath, UseRename, Variadic, + ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemModWithDefault, ItemStatic, ItemStruct, + ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, + StaticMutability, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, + UseGroup, UseName, UsePath, UseRename, Variadic, }; use crate::mac::MacroDelimiter; - use crate::path; use crate::path::printing::PathStyle; use crate::print::TokensOrDefault; use crate::ty::Type; + use crate::{path, FieldsWithDefault, ItemEnumWithDefault, ItemStructWithDefault}; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt as _}; @@ -3039,6 +3318,25 @@ mod printing { } } + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for ItemModWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(self.attrs.outer()); + self.vis.to_tokens(tokens); + self.unsafety.to_tokens(tokens); + self.mod_token.to_tokens(tokens); + self.ident.to_tokens(tokens); + if let Some((brace, items)) = &self.content { + brace.surround(tokens, |tokens| { + tokens.append_all(self.attrs.inner()); + tokens.append_all(items); + }); + } else { + TokensOrDefault(&self.semi).to_tokens(tokens); + } + } + } + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemForeignMod { fn to_tokens(&self, tokens: &mut TokenStream) { @@ -3081,6 +3379,20 @@ mod printing { }); } } + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for ItemEnumWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(self.attrs.outer()); + self.vis.to_tokens(tokens); + self.enum_token.to_tokens(tokens); + self.ident.to_tokens(tokens); + self.generics.to_tokens(tokens); + self.generics.where_clause.to_tokens(tokens); + self.brace_token.surround(tokens, |tokens| { + self.variants.to_tokens(tokens); + }); + } + } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemStruct { @@ -3107,6 +3419,31 @@ mod printing { } } } + #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] + impl ToTokens for ItemStructWithDefault { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(self.attrs.outer()); + self.vis.to_tokens(tokens); + self.struct_token.to_tokens(tokens); + self.ident.to_tokens(tokens); + self.generics.to_tokens(tokens); + match &self.fields { + FieldsWithDefault::Named(fields) => { + self.generics.where_clause.to_tokens(tokens); + fields.to_tokens(tokens); + } + FieldsWithDefault::Unnamed(fields) => { + fields.to_tokens(tokens); + self.generics.where_clause.to_tokens(tokens); + TokensOrDefault(&self.semi_token).to_tokens(tokens); + } + FieldsWithDefault::Unit => { + self.generics.where_clause.to_tokens(tokens); + TokensOrDefault(&self.semi_token).to_tokens(tokens); + } + } + } + } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemUnion { diff --git a/src/lib.rs b/src/lib.rs index ef1d7034ed..2defad0f57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -203,6 +203,36 @@ //! //!
//! +//! # Default Field Values +//! +//! Syn has support for the `default_field_values` Rust feature ([rfcs#3681]). +//! However, adding the fields necessary for this directly to Syn was not possible without +//! breaking backwards compatibility. +//! As such, this support is instead only present in "version 2" of several major structs. +//! These are indicated with the `WithDefault` suffix. +//! For example, if you wish to use the a default field value in a derive macro, +//! you should use `DeriveInputWithDefault`. +//! +//! Note that even if your derive macro does not make use of default fields, they +//! will now be skipped in parsing, so existing macros do not need to update +//! for this feature. +//! However, this cannot be relied upon for attribute procedural macros, as +//! when you re-print the struct/enum, the default values may inadvertently +//! not be retained. +//! +//! In the hierarchy of items with default field values (e.g. [`ItemWithDefault`]), +//! structs defined within inner blocks currently do *not* support default field values. +//! That is, if you tried `fn x() { struct Y { x: u32 = 10 } }`, that would give a parse error. +//! This is done for simplicity of implementation, as it would otherwise require the parallel +//! hierarchy cover nearly all of Syn. +//! +//! We expect these types to be folded into their non-suffixed equivalents in the +//! next breaking release. +//! +//! [rfcs#3681]: https://github.com/rust-lang/rfcs/pull/3681 +//! +//!
+//! //! # Debugging //! //! When developing a procedural macro it can be helpful to look at what the @@ -351,13 +381,19 @@ mod custom_punctuation; mod data; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] -pub use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant}; +pub use crate::data::{ + Field, FieldWithDefault, Fields, FieldsNamed, FieldsNamedWithDefault, FieldsUnnamed, + FieldsUnnamedWithDefault, FieldsWithDefault, Variant, VariantWithDefault, +}; #[cfg(any(feature = "full", feature = "derive"))] mod derive; #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] -pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; +pub use crate::derive::{ + Data, DataEnum, DataEnumWithDefault, DataStruct, DataStructWithDefault, DataUnion, + DataWithDefault, DeriveInput, DeriveInputWithDefault, +}; mod drops; @@ -390,7 +426,7 @@ pub mod ext; mod file; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] -pub use crate::file::File; +pub use crate::file::{File, FileWithDefault}; #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] mod fixup; @@ -425,10 +461,11 @@ mod item; pub use crate::item::{ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, ImplRestriction, Item, - ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, - ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, - Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, - TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic, + ItemConst, ItemEnum, ItemEnumWithDefault, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, + ItemMacro, ItemMod, ItemModWithDefault, ItemStatic, ItemStruct, ItemStructWithDefault, + ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, ItemWithDefault, Receiver, Signature, + StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, + UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic, }; mod lifetime; @@ -1007,3 +1044,36 @@ pub fn parse_file(mut content: &str) -> Result { file.shebang = shebang; Ok(file) } + +/// Parse the content of a file of Rust code, with support for the default field values feature. +/// +/// See [`parse_file`] for full docs. +/// +/// Struct and enum items output by this function support having default field values set. +#[cfg(all(feature = "parsing", feature = "full"))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))] +pub fn parse_file_with_default(mut content: &str) -> Result { + // Strip the BOM if it is present + const BOM: &str = "\u{feff}"; + if content.starts_with(BOM) { + content = &content[BOM.len()..]; + } + + let mut shebang = None; + if content.starts_with("#!") { + let rest = whitespace::skip(&content[2..]); + if !rest.starts_with('[') { + if let Some(idx) = content.find('\n') { + shebang = Some(content[..idx].to_string()); + content = &content[idx..]; + } else { + shebang = Some(content.to_string()); + content = ""; + } + } + } + + let mut file: FileWithDefault = parse_str(content)?; + file.shebang = shebang; + Ok(file) +} diff --git a/syn.json b/syn.json index 5c8b2c400e..2eaff4de81 100644 --- a/syn.json +++ b/syn.json @@ -588,6 +588,30 @@ } } }, + { + "ident": "DataEnumWithDefault", + "features": { + "any": [ + "derive" + ] + }, + "fields": { + "enum_token": { + "token": "Enum" + }, + "brace_token": { + "group": "Brace" + }, + "variants": { + "punctuated": { + "element": { + "syn": "VariantWithDefault" + }, + "punct": "Comma" + } + } + } + }, { "ident": "DataStruct", "features": { @@ -609,6 +633,27 @@ } } }, + { + "ident": "DataStructWithDefault", + "features": { + "any": [ + "derive" + ] + }, + "fields": { + "struct_token": { + "token": "Struct" + }, + "fields": { + "syn": "FieldsWithDefault" + }, + "semi_token": { + "option": { + "token": "Semi" + } + } + } + }, { "ident": "DataUnion", "features": { @@ -625,6 +670,31 @@ } } }, + { + "ident": "DataWithDefault", + "features": { + "any": [ + "derive" + ] + }, + "variants": { + "Struct": [ + { + "syn": "DataStructWithDefault" + } + ], + "Enum": [ + { + "syn": "DataEnumWithDefault" + } + ], + "Union": [ + { + "syn": "DataUnion" + } + ] + } + }, { "ident": "DeriveInput", "features": { @@ -652,6 +722,33 @@ } } }, + { + "ident": "DeriveInputWithDefault", + "features": { + "any": [ + "derive" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "vis": { + "syn": "Visibility" + }, + "ident": { + "proc_macro2": "Ident" + }, + "generics": { + "syn": "Generics" + }, + "data": { + "syn": "DataWithDefault" + } + } + }, { "ident": "Expr", "features": { @@ -2081,6 +2178,53 @@ } } }, + { + "ident": "FieldWithDefault", + "features": { + "any": [ + "derive", + "full" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "vis": { + "syn": "Visibility" + }, + "mutability": { + "syn": "FieldMutability" + }, + "ident": { + "option": { + "proc_macro2": "Ident" + } + }, + "colon_token": { + "option": { + "token": "Colon" + } + }, + "ty": { + "syn": "Type" + }, + "default": { + "option": { + "tuple": [ + { + "token": "Eq" + }, + { + "syn": "Expr" + } + ] + } + } + } + }, { "ident": "Fields", "features": { @@ -2125,6 +2269,28 @@ } } }, + { + "ident": "FieldsNamedWithDefault", + "features": { + "any": [ + "derive", + "full" + ] + }, + "fields": { + "brace_token": { + "group": "Brace" + }, + "named": { + "punctuated": { + "element": { + "syn": "FieldWithDefault" + }, + "punct": "Comma" + } + } + } + }, { "ident": "FieldsUnnamed", "features": { @@ -2147,6 +2313,50 @@ } } }, + { + "ident": "FieldsUnnamedWithDefault", + "features": { + "any": [ + "derive", + "full" + ] + }, + "fields": { + "paren_token": { + "group": "Paren" + }, + "unnamed": { + "punctuated": { + "element": { + "syn": "FieldWithDefault" + }, + "punct": "Comma" + } + } + } + }, + { + "ident": "FieldsWithDefault", + "features": { + "any": [ + "derive", + "full" + ] + }, + "variants": { + "Named": [ + { + "syn": "FieldsNamedWithDefault" + } + ], + "Unnamed": [ + { + "syn": "FieldsUnnamedWithDefault" + } + ], + "Unit": [] + } + }, { "ident": "File", "features": { @@ -2172,6 +2382,31 @@ } } }, + { + "ident": "FileWithDefault", + "features": { + "any": [ + "full" + ] + }, + "fields": { + "shebang": { + "option": { + "std": "String" + } + }, + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "items": { + "vec": { + "syn": "ItemWithDefault" + } + } + } + }, { "ident": "FnArg", "features": { @@ -2823,6 +3058,44 @@ } } }, + { + "ident": "ItemEnumWithDefault", + "features": { + "any": [ + "full" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "vis": { + "syn": "Visibility" + }, + "enum_token": { + "token": "Enum" + }, + "ident": { + "proc_macro2": "Ident" + }, + "generics": { + "syn": "Generics" + }, + "brace_token": { + "group": "Brace" + }, + "variants": { + "punctuated": { + "element": { + "syn": "VariantWithDefault" + }, + "punct": "Comma" + } + } + } + }, { "ident": "ItemExternCrate", "features": { @@ -3059,6 +3332,54 @@ } } }, + { + "ident": "ItemModWithDefault", + "features": { + "any": [ + "full" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "vis": { + "syn": "Visibility" + }, + "unsafety": { + "option": { + "token": "Unsafe" + } + }, + "mod_token": { + "token": "Mod" + }, + "ident": { + "proc_macro2": "Ident" + }, + "content": { + "option": { + "tuple": [ + { + "group": "Brace" + }, + { + "vec": { + "syn": "ItemWithDefault" + } + } + ] + } + }, + "semi": { + "option": { + "token": "Semi" + } + } + } + }, { "ident": "ItemStatic", "features": { @@ -3140,6 +3461,41 @@ } } }, + { + "ident": "ItemStructWithDefault", + "features": { + "any": [ + "full" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "vis": { + "syn": "Visibility" + }, + "struct_token": { + "token": "Struct" + }, + "ident": { + "proc_macro2": "Ident" + }, + "generics": { + "syn": "Generics" + }, + "fields": { + "syn": "FieldsWithDefault" + }, + "semi_token": { + "option": { + "token": "Semi" + } + } + } + }, { "ident": "ItemTrait", "features": { @@ -3344,6 +3700,37 @@ } } }, + { + "ident": "ItemWithDefault", + "features": { + "any": [ + "full" + ] + }, + "variants": { + "StructWithDefault": [ + { + "syn": "ItemStructWithDefault" + } + ], + "EnumWithDefault": [ + { + "syn": "ItemEnumWithDefault" + } + ], + "ModWithDefault": [ + { + "syn": "ItemModWithDefault" + } + ], + "Other": [ + { + "syn": "Item" + } + ] + }, + "exhaustive": false + }, { "ident": "Label", "features": { @@ -5487,6 +5874,40 @@ } } }, + { + "ident": "VariantWithDefault", + "features": { + "any": [ + "derive", + "full" + ] + }, + "fields": { + "attrs": { + "vec": { + "syn": "Attribute" + } + }, + "ident": { + "proc_macro2": "Ident" + }, + "fields": { + "syn": "FieldsWithDefault" + }, + "discriminant": { + "option": { + "tuple": [ + { + "token": "Eq" + }, + { + "syn": "Expr" + } + ] + } + } + } + }, { "ident": "VisRestricted", "features": { diff --git a/tests/debug/gen.rs b/tests/debug/gen.rs index f91977a676..1805f2f198 100644 --- a/tests/debug/gen.rs +++ b/tests/debug/gen.rs @@ -422,6 +422,15 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("DataEnumWithDefault"); + if !self.value.variants.is_empty() { + formatter.field("variants", Lite(&self.value.variants)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DataStruct"); @@ -432,6 +441,16 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("DataStructWithDefault"); + formatter.field("fields", Lite(&self.value.fields)); + if self.value.semi_token.is_some() { + formatter.field("semi_token", &Present); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DataUnion"); @@ -439,6 +458,33 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.value { + syn::DataWithDefault::Struct(_val) => { + formatter.write_str("DataWithDefault::Struct")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::DataWithDefault::Enum(_val) => { + formatter.write_str("DataWithDefault::Enum")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::DataWithDefault::Union(_val) => { + formatter.write_str("DataWithDefault::Union")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + } + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DeriveInput"); @@ -452,6 +498,19 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("DeriveInputWithDefault"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("vis", Lite(&self.value.vis)); + formatter.field("ident", Lite(&self.value.ident)); + formatter.field("generics", Lite(&self.value.generics)); + formatter.field("data", Lite(&self.value.data)); + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { @@ -1816,6 +1875,54 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FieldWithDefault"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("vis", Lite(&self.value.vis)); + match self.value.mutability { + syn::FieldMutability::None => {} + _ => { + formatter.field("mutability", Lite(&self.value.mutability)); + } + } + if let Some(val) = &self.value.ident { + #[derive(RefCast)] + #[repr(transparent)] + struct Print(proc_macro2::Ident); + impl Debug for Print { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Some(")?; + Debug::fmt(Lite(&self.0), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + } + formatter.field("ident", Print::ref_cast(val)); + } + if self.value.colon_token.is_some() { + formatter.field("colon_token", &Present); + } + formatter.field("ty", Lite(&self.value.ty)); + if let Some(val) = &self.value.default { + #[derive(RefCast)] + #[repr(transparent)] + struct Print((syn::token::Eq, syn::Expr)); + impl Debug for Print { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Some(")?; + Debug::fmt(Lite(&self.0.1), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + } + formatter.field("default", Print::ref_cast(val)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { @@ -1846,6 +1953,15 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FieldsNamedWithDefault"); + if !self.value.named.is_empty() { + formatter.field("named", Lite(&self.value.named)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldsUnnamed"); @@ -1855,6 +1971,38 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FieldsUnnamedWithDefault"); + if !self.value.unnamed.is_empty() { + formatter.field("unnamed", Lite(&self.value.unnamed)); + } + formatter.finish() + } +} +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.value { + syn::FieldsWithDefault::Named(_val) => { + formatter.write_str("FieldsWithDefault::Named")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::FieldsWithDefault::Unnamed(_val) => { + formatter.write_str("FieldsWithDefault::Unnamed")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::FieldsWithDefault::Unit => { + formatter.write_str("FieldsWithDefault::Unit") + } + } + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("File"); @@ -1881,6 +2029,32 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("FileWithDefault"); + if let Some(val) = &self.value.shebang { + #[derive(RefCast)] + #[repr(transparent)] + struct Print(String); + impl Debug for Print { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Some(")?; + Debug::fmt(Lite(&self.0), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + } + formatter.field("shebang", Print::ref_cast(val)); + } + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + if !self.value.items.is_empty() { + formatter.field("items", Lite(&self.value.items)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { @@ -2586,6 +2760,21 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ItemEnumWithDefault"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("vis", Lite(&self.value.vis)); + formatter.field("ident", Lite(&self.value.ident)); + formatter.field("generics", Lite(&self.value.generics)); + if !self.value.variants.is_empty() { + formatter.field("variants", Lite(&self.value.variants)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemExternCrate"); @@ -2739,6 +2928,37 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ItemModWithDefault"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("vis", Lite(&self.value.vis)); + if self.value.unsafety.is_some() { + formatter.field("unsafety", &Present); + } + formatter.field("ident", Lite(&self.value.ident)); + if let Some(val) = &self.value.content { + #[derive(RefCast)] + #[repr(transparent)] + struct Print((syn::token::Brace, Vec)); + impl Debug for Print { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Some(")?; + Debug::fmt(Lite(&self.0.1), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + } + formatter.field("content", Print::ref_cast(val)); + } + if self.value.semi.is_some() { + formatter.field("semi", &Present); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemStatic"); @@ -2774,6 +2994,22 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("ItemStructWithDefault"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("vis", Lite(&self.value.vis)); + formatter.field("ident", Lite(&self.value.ident)); + formatter.field("generics", Lite(&self.value.generics)); + formatter.field("fields", Lite(&self.value.fields)); + if self.value.semi_token.is_some() { + formatter.field("semi_token", &Present); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemTrait"); @@ -2870,6 +3106,41 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.value { + syn::ItemWithDefault::StructWithDefault(_val) => { + formatter.write_str("ItemWithDefault::StructWithDefault")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::ItemWithDefault::EnumWithDefault(_val) => { + formatter.write_str("ItemWithDefault::EnumWithDefault")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::ItemWithDefault::ModWithDefault(_val) => { + formatter.write_str("ItemWithDefault::ModWithDefault")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + syn::ItemWithDefault::Other(_val) => { + formatter.write_str("ItemWithDefault::Other")?; + formatter.write_str("(")?; + Debug::fmt(Lite(_val), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + _ => unreachable!(), + } + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Label"); @@ -4678,6 +4949,31 @@ impl Debug for Lite { formatter.finish() } } +impl Debug for Lite { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let mut formatter = formatter.debug_struct("VariantWithDefault"); + if !self.value.attrs.is_empty() { + formatter.field("attrs", Lite(&self.value.attrs)); + } + formatter.field("ident", Lite(&self.value.ident)); + formatter.field("fields", Lite(&self.value.fields)); + if let Some(val) = &self.value.discriminant { + #[derive(RefCast)] + #[repr(transparent)] + struct Print((syn::token::Eq, syn::Expr)); + impl Debug for Print { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Some(")?; + Debug::fmt(Lite(&self.0.1), formatter)?; + formatter.write_str(")")?; + Ok(()) + } + } + formatter.field("discriminant", Print::ref_cast(val)); + } + formatter.finish() + } +} impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("VisRestricted"); diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs index 790e2792ad..b12df5e80e 100644 --- a/tests/test_derive_input.rs +++ b/tests/test_derive_input.rs @@ -1,3 +1,7 @@ +// These tests are also duplicated in "test_derive_input_with_default", but for the "default field values" version of the derive input +// If editing these tests, if there is an equivalent test in the other file, you should edit that too. +// If adding a new test, you should also add it to the other file. + #![allow( clippy::assertions_on_result_states, clippy::elidable_lifetime_names, diff --git a/tests/test_derive_input_with_default.rs b/tests/test_derive_input_with_default.rs new file mode 100644 index 0000000000..abb087d793 --- /dev/null +++ b/tests/test_derive_input_with_default.rs @@ -0,0 +1,900 @@ +#![allow( + clippy::assertions_on_result_states, + clippy::elidable_lifetime_names, + clippy::manual_let_else, + clippy::needless_lifetimes, + clippy::too_many_lines, + clippy::uninlined_format_args +)] + +#[macro_use] +mod snapshot; + +mod debug; + +use quote::quote; +use syn::{DataWithDefault, DeriveInputWithDefault}; + +#[test] +fn test_struct() { + let input = quote! { + #[derive(Debug, Clone)] + pub struct Item { + pub ident: Ident, + pub attrs: Vec = Vec::new() + } + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + attrs: [ + Attribute { + style: AttrStyle::Outer, + meta: Meta::List { + path: Path { + segments: [ + PathSegment { + ident: "derive", + }, + ], + }, + delimiter: MacroDelimiter::Paren, + tokens: TokenStream(`Debug , Clone`), + }, + }, + ], + vis: Visibility::Public, + ident: "Item", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Named(FieldsNamedWithDefault { + named: [ + FieldWithDefault { + vis: Visibility::Public, + ident: Some("ident"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "Ident", + }, + ], + }, + }, + }, + Token![,], + FieldWithDefault { + vis: Visibility::Public, + ident: Some("attrs"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "Vec", + arguments: PathArguments::AngleBracketed { + args: [ + GenericArgument::Type(Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "Attribute", + }, + ], + }, + }), + ], + }, + }, + ], + }, + }, + default: Some(Expr::Call { + func: Expr::Path { + path: Path { + segments: [ + PathSegment { + ident: "Vec", + }, + Token![::], + PathSegment { + ident: "new", + }, + ], + }, + }, + }), + }, + ], + }), + }), + } + "#); + + snapshot!(&input.attrs[0].meta, @r#" + Meta::List { + path: Path { + segments: [ + PathSegment { + ident: "derive", + }, + ], + }, + delimiter: MacroDelimiter::Paren, + tokens: TokenStream(`Debug , Clone`), + } + "#); +} + +#[test] +fn test_fields_on_named_struct() { + let input = quote! { + struct S { + foo: i32 = 10, + pub bar: String, + } + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Inherited, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Named(FieldsNamedWithDefault { + named: [ + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("foo"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + default: Some(Expr::Lit { + lit: 10, + }), + }, + Token![,], + FieldWithDefault { + vis: Visibility::Public, + ident: Some("bar"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "String", + }, + ], + }, + }, + }, + Token![,], + ], + }), + }), + } + "#); + + let data = match input.data { + DataWithDefault::Struct(data) => data, + _ => panic!("expected a struct"), + }; + + snapshot!(data.fields.into_iter().collect::>(), @r#" + [ + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("foo"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + default: Some(Expr::Lit { + lit: 10, + }), + }, + FieldWithDefault { + vis: Visibility::Public, + ident: Some("bar"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "String", + }, + ], + }, + }, + }, + ] + "#); +} + +#[test] +#[cfg(feature = "full")] +fn test_enum_fields() { + let input = quote! { + pub enum DefaultField { + Variant { + field: u32 = 10, + field_2: i32 + }, + Variant2 { + no_default_values: u8 + } + } + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Public, + ident: "DefaultField", + generics: Generics, + data: DataWithDefault::Enum(DataEnumWithDefault { + variants: [ + VariantWithDefault { + ident: "Variant", + fields: FieldsWithDefault::Named(FieldsNamedWithDefault { + named: [ + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("field"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "u32", + }, + ], + }, + }, + default: Some(Expr::Lit { + lit: 10, + }), + }, + Token![,], + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("field_2"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + }, + ], + }), + }, + Token![,], + VariantWithDefault { + ident: "Variant2", + fields: FieldsWithDefault::Named(FieldsNamedWithDefault { + named: [ + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("no_default_values"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "u8", + }, + ], + }, + }, + }, + ], + }), + }, + ], + }), + } + "#); +} + +// Even though the DeriveInputWithDefault shares most of the parsing code with the derive input feature, we duplicate +// all of the tests which don't use the feature, to ensure that the shared code is integrated properly +// These are duplicates of the tests in "test_derive_input" +// If editing these tests, if there is an equivalent test in the other file, you should edit that too. + +#[test] +fn test_unit() { + let input = quote! { + struct Unit; + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Inherited, + ident: "Unit", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unit, + semi_token: Some, + }), + } + "#); +} + +#[test] +fn test_union() { + let input = quote! { + union MaybeUninit { + uninit: (), + value: T + } + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Inherited, + ident: "MaybeUninit", + generics: Generics { + lt_token: Some, + params: [ + GenericParam::Type(TypeParam { + ident: "T", + }), + ], + gt_token: Some, + }, + data: DataWithDefault::Union(DataUnion { + fields: FieldsNamed { + named: [ + Field { + vis: Visibility::Inherited, + ident: Some("uninit"), + colon_token: Some, + ty: Type::Tuple, + }, + Token![,], + Field { + vis: Visibility::Inherited, + ident: Some("value"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "T", + }, + ], + }, + }, + }, + ], + }, + }), + } + "#); +} + +#[test] +#[cfg(feature = "full")] +fn test_enum() { + let input = quote! { + /// See the std::result module documentation for details. + #[must_use] + pub enum Result { + Ok(T), + Err(E), + Surprise = 0isize, + + // Smuggling data into a proc_macro_derive, + // in the style of https://github.com/dtolnay/proc-macro-hack + ProcMacroHack = (0, "data").0 + } + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + attrs: [ + Attribute { + style: AttrStyle::Outer, + meta: Meta::NameValue { + path: Path { + segments: [ + PathSegment { + ident: "doc", + }, + ], + }, + value: Expr::Lit { + lit: " See the std::result module documentation for details.", + }, + }, + }, + Attribute { + style: AttrStyle::Outer, + meta: Meta::Path { + segments: [ + PathSegment { + ident: "must_use", + }, + ], + }, + }, + ], + vis: Visibility::Public, + ident: "Result", + generics: Generics { + lt_token: Some, + params: [ + GenericParam::Type(TypeParam { + ident: "T", + }), + Token![,], + GenericParam::Type(TypeParam { + ident: "E", + }), + ], + gt_token: Some, + }, + data: DataWithDefault::Enum(DataEnumWithDefault { + variants: [ + VariantWithDefault { + ident: "Ok", + fields: FieldsWithDefault::Unnamed(FieldsUnnamedWithDefault { + unnamed: [ + FieldWithDefault { + vis: Visibility::Inherited, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "T", + }, + ], + }, + }, + }, + ], + }), + }, + Token![,], + VariantWithDefault { + ident: "Err", + fields: FieldsWithDefault::Unnamed(FieldsUnnamedWithDefault { + unnamed: [ + FieldWithDefault { + vis: Visibility::Inherited, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "E", + }, + ], + }, + }, + }, + ], + }), + }, + Token![,], + VariantWithDefault { + ident: "Surprise", + fields: FieldsWithDefault::Unit, + discriminant: Some(Expr::Lit { + lit: 0isize, + }), + }, + Token![,], + VariantWithDefault { + ident: "ProcMacroHack", + fields: FieldsWithDefault::Unit, + discriminant: Some(Expr::Field { + base: Expr::Tuple { + elems: [ + Expr::Lit { + lit: 0, + }, + Token![,], + Expr::Lit { + lit: "data", + }, + ], + }, + member: Member::Unnamed(Index { + index: 0, + }), + }), + }, + ], + }), + } + "#); + + let meta_items: Vec<_> = input.attrs.into_iter().map(|attr| attr.meta).collect(); + + snapshot!(meta_items, @r#" + [ + Meta::NameValue { + path: Path { + segments: [ + PathSegment { + ident: "doc", + }, + ], + }, + value: Expr::Lit { + lit: " See the std::result module documentation for details.", + }, + }, + Meta::Path { + segments: [ + PathSegment { + ident: "must_use", + }, + ], + }, + ] + "#); +} + +#[test] +fn test_attr_with_non_mod_style_path() { + let input = quote! { + #[inert ] + struct S; + }; + + syn::parse2::(input).unwrap_err(); +} + +#[test] +fn test_attr_with_mod_style_path_with_self() { + let input = quote! { + #[foo::self] + struct S; + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + attrs: [ + Attribute { + style: AttrStyle::Outer, + meta: Meta::Path { + segments: [ + PathSegment { + ident: "foo", + }, + Token![::], + PathSegment { + ident: "self", + }, + ], + }, + }, + ], + vis: Visibility::Inherited, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unit, + semi_token: Some, + }), + } + "#); + + snapshot!(&input.attrs[0].meta, @r#" + Meta::Path { + segments: [ + PathSegment { + ident: "foo", + }, + Token![::], + PathSegment { + ident: "self", + }, + ], + } + "#); +} + +#[test] +fn test_pub_restricted() { + // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs + let input = quote! { + pub(in m) struct Z(pub(in m::n) u8); + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Restricted { + in_token: Some, + path: Path { + segments: [ + PathSegment { + ident: "m", + }, + ], + }, + }, + ident: "Z", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unnamed(FieldsUnnamedWithDefault { + unnamed: [ + FieldWithDefault { + vis: Visibility::Restricted { + in_token: Some, + path: Path { + segments: [ + PathSegment { + ident: "m", + }, + Token![::], + PathSegment { + ident: "n", + }, + ], + }, + }, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "u8", + }, + ], + }, + }, + }, + ], + }), + semi_token: Some, + }), + } + "#); +} + +#[test] +fn test_pub_restricted_crate() { + let input = quote! { + pub(crate) struct S; + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Restricted { + path: Path { + segments: [ + PathSegment { + ident: "crate", + }, + ], + }, + }, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unit, + semi_token: Some, + }), + } + "#); +} + +#[test] +fn test_pub_restricted_super() { + let input = quote! { + pub(super) struct S; + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Restricted { + path: Path { + segments: [ + PathSegment { + ident: "super", + }, + ], + }, + }, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unit, + semi_token: Some, + }), + } + "#); +} + +#[test] +fn test_pub_restricted_in_super() { + let input = quote! { + pub(in super) struct S; + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Restricted { + in_token: Some, + path: Path { + segments: [ + PathSegment { + ident: "super", + }, + ], + }, + }, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unit, + semi_token: Some, + }), + } + "#); +} + +#[test] +fn test_fields_on_unit_struct() { + let input = quote! { + struct S; + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Inherited, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unit, + semi_token: Some, + }), + } + "#); + + let data = match input.data { + DataWithDefault::Struct(data) => data, + _ => panic!("expected a struct"), + }; + + assert_eq!(0, data.fields.iter().count()); +} + +#[test] +fn test_fields_on_tuple_struct() { + let input = quote! { + struct S(i32, pub String); + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Inherited, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unnamed(FieldsUnnamedWithDefault { + unnamed: [ + FieldWithDefault { + vis: Visibility::Inherited, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + }, + Token![,], + FieldWithDefault { + vis: Visibility::Public, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "String", + }, + ], + }, + }, + }, + ], + }), + semi_token: Some, + }), + } + "#); + + let data = match input.data { + DataWithDefault::Struct(data) => data, + _ => panic!("expected a struct"), + }; + + snapshot!(data.fields.iter().collect::>(), @r#" + [ + FieldWithDefault { + vis: Visibility::Inherited, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + }, + FieldWithDefault { + vis: Visibility::Public, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "String", + }, + ], + }, + }, + }, + ] + "#); +} + +#[test] +fn test_ambiguous_crate() { + let input = quote! { + // The field type is `(crate::X)` not `crate (::X)`. + struct S(crate::X); + }; + + snapshot!(input as DeriveInputWithDefault, @r#" + DeriveInputWithDefault { + vis: Visibility::Inherited, + ident: "S", + generics: Generics, + data: DataWithDefault::Struct(DataStructWithDefault { + fields: FieldsWithDefault::Unnamed(FieldsUnnamedWithDefault { + unnamed: [ + FieldWithDefault { + vis: Visibility::Inherited, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "crate", + }, + Token![::], + PathSegment { + ident: "X", + }, + ], + }, + }, + }, + ], + }), + semi_token: Some, + }), + } + "#); +} diff --git a/tests/test_item.rs b/tests/test_item.rs index d9a7b5b6b0..c10fdde35d 100644 --- a/tests/test_item.rs +++ b/tests/test_item.rs @@ -11,7 +11,7 @@ mod debug; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use quote::quote; -use syn::{Item, ItemTrait}; +use syn::{Item, ItemTrait, ItemWithDefault}; #[test] fn test_macro_variable_attr() { @@ -314,3 +314,95 @@ fn test_impl_trait_trailing_plus() { } "#); } + +#[test] +fn test_struct_default_field_values() { + let tokens = quote! { + struct Foo { + field: i32 = const { 42 }, + } + }; + snapshot!(tokens as ItemWithDefault, @r#" + ItemWithDefault::StructWithDefault(ItemStructWithDefault { + vis: Visibility::Inherited, + ident: "Foo", + generics: Generics, + fields: FieldsWithDefault::Named(FieldsNamedWithDefault { + named: [ + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("field"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + default: Some(Expr::Const { + block: Block { + stmts: [ + Stmt::Expr( + Expr::Lit { + lit: 42, + }, + None, + ), + ], + }, + }), + }, + Token![,], + ], + }), + }) + "#); +} + +#[test] +fn test_enum_default_field_values() { + let tokens = quote! { + enum Foo { + Bar { + field: i32 = 42, + } + } + }; + snapshot!(tokens as ItemWithDefault, @r#" + ItemWithDefault::EnumWithDefault(ItemEnumWithDefault { + vis: Visibility::Inherited, + ident: "Foo", + generics: Generics, + variants: [ + VariantWithDefault { + ident: "Bar", + fields: FieldsWithDefault::Named(FieldsNamedWithDefault { + named: [ + FieldWithDefault { + vis: Visibility::Inherited, + ident: Some("field"), + colon_token: Some, + ty: Type::Path { + path: Path { + segments: [ + PathSegment { + ident: "i32", + }, + ], + }, + }, + default: Some(Expr::Lit { + lit: 42, + }), + }, + Token![,], + ], + }), + }, + ], + }) + "#); +}