diff options
Diffstat (limited to 'vendor/serde_derive')
-rw-r--r-- | vendor/serde_derive/.cargo-checksum.json | 2 | ||||
-rw-r--r-- | vendor/serde_derive/Cargo.toml | 2 | ||||
-rw-r--r-- | vendor/serde_derive/build.rs | 38 | ||||
-rw-r--r-- | vendor/serde_derive/src/de.rs | 92 | ||||
-rw-r--r-- | vendor/serde_derive/src/dummy.rs | 22 | ||||
-rw-r--r-- | vendor/serde_derive/src/internals/ast.rs | 17 | ||||
-rw-r--r-- | vendor/serde_derive/src/internals/attr.rs | 9 | ||||
-rw-r--r-- | vendor/serde_derive/src/internals/ctxt.rs | 17 | ||||
-rw-r--r-- | vendor/serde_derive/src/lib.rs | 11 | ||||
-rw-r--r-- | vendor/serde_derive/src/pretend.rs | 29 | ||||
-rw-r--r-- | vendor/serde_derive/src/ser.rs | 18 |
11 files changed, 113 insertions, 144 deletions
diff --git a/vendor/serde_derive/.cargo-checksum.json b/vendor/serde_derive/.cargo-checksum.json index 888714371..44476cfe8 100644 --- a/vendor/serde_derive/.cargo-checksum.json +++ b/vendor/serde_derive/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"d4c79a251c1bd0ed40ec6f4d8d06940542e54876e2327233a3e4737ab31d0860","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"13c66875efb67f64fdec817725f34ceb07913e1ebea4adc240868d2ed581d3da","build.rs":"d9a0df0c4dd552ff7fd0c3b3828cb1fff4fc4ab15bd98539881929b76b98003b","crates-io.md":"ee22254ee64c3189eef3e707c8d75dc66a8df2a7ee9e518d95238950780ec387","src/bound.rs":"9211d852730380be8e0af9ed5daa52e61563e598eef458739025551ba76aa7c6","src/de.rs":"4dde42292a4476f71b3790156fb2fbfbdba88ebad28c129065890d0f1470ff5d","src/dummy.rs":"31e02c3313d12c88b3b26baa49a9cb143440804b557b5255aad9a9b80b8ea1c6","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"7407c6e85afd197bdbf715bd681bd171db37b2264f617e148ca340817f56e684","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"0449cc7653fc9e596f65028835bbb7d1545c10002c79c7608547f45a722c0040","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"6b016351b8294539039095863d8c99e81dd4530d7f769003d12d4ca73cca172c","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"2bf0287da64d28da7e8673af60f66aaf6b29efe33131e56b24d6fa55edb533ad","src/lib.rs":"0ed50d02eb095af7a0a57f571734f2c1ac0a704b498b88be3710f14335bd0f92","src/pretend.rs":"4aa53bf6c1350fbcfc8c4997f720cde61a8eb3aab73bb8c101b0f0a74901892b","src/ser.rs":"803f522d313e52eece8a91babfad9d35734d0bf04b042cf24d781294674ba8b3","src/this.rs":"a2c128955324c2994ed7cdc3fe4eeceb7ad8a0f9d071665a8378c85c8df64ce2","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"}
\ No newline at end of file +{"files":{"Cargo.toml":"57006278b8f645cedd47b3c0c7af2343388f43a6473c2f039e783c02ca030fc8","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"13c66875efb67f64fdec817725f34ceb07913e1ebea4adc240868d2ed581d3da","crates-io.md":"ee22254ee64c3189eef3e707c8d75dc66a8df2a7ee9e518d95238950780ec387","src/bound.rs":"9211d852730380be8e0af9ed5daa52e61563e598eef458739025551ba76aa7c6","src/de.rs":"240926ab4ea76bfe883e93d2b6ff252cfdbc46ae98fff1a64664e22bcac78daa","src/dummy.rs":"1b7de5bfe1158ea7e70d668d4f76fdccf7f63144ac7869e82e8bf1e7ea0db13c","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"07dfd9a789cd6268c2cff2889e738193d24e68c93873792a0548d5e6b3c94ca4","src/internals/attr.rs":"b9f7a99895f4e9dbec433e14f647eb9ac1457ed7eb47180aaac3b4e8c6420be3","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"0449cc7653fc9e596f65028835bbb7d1545c10002c79c7608547f45a722c0040","src/internals/ctxt.rs":"c403db8260a533e58af06e8d0a2bb962edb13a250424ab1f1fd2719902affc37","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"6b016351b8294539039095863d8c99e81dd4530d7f769003d12d4ca73cca172c","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"2bf0287da64d28da7e8673af60f66aaf6b29efe33131e56b24d6fa55edb533ad","src/lib.rs":"fa8c851c7b681e0662bde69f7b03a3dfc3b32dc94e1687cadd57d95cfbba4d4e","src/pretend.rs":"0e570faf787015535ea6b6683ebc271633c1ca945d3ee1d072c497a1a920c380","src/ser.rs":"e435dc7ef8ee9dca02913f43b4162d22c664061510089745b6278a63df7d30fe","src/this.rs":"a2c128955324c2994ed7cdc3fe4eeceb7ad8a0f9d071665a8378c85c8df64ce2","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"}
\ No newline at end of file diff --git a/vendor/serde_derive/Cargo.toml b/vendor/serde_derive/Cargo.toml index a607f0428..e2865f5c6 100644 --- a/vendor/serde_derive/Cargo.toml +++ b/vendor/serde_derive/Cargo.toml @@ -12,7 +12,7 @@ [package] rust-version = "1.56" name = "serde_derive" -version = "1.0.160" +version = "1.0.164" authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>", diff --git a/vendor/serde_derive/build.rs b/vendor/serde_derive/build.rs deleted file mode 100644 index 1249dab59..000000000 --- a/vendor/serde_derive/build.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::env; -use std::process::Command; -use std::str; - -// The rustc-cfg strings below are *not* public API. Please let us know by -// opening a GitHub issue if your build environment requires some way to enable -// these cfgs other than by executing our build script. -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - - let minor = match rustc_minor_version() { - Some(minor) => minor, - None => return, - }; - - // Underscore const names stabilized in Rust 1.37: - // https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html#using-unnamed-const-items-for-macros - if minor < 37 { - println!("cargo:rustc-cfg=no_underscore_consts"); - } - - // The ptr::addr_of! macro stabilized in Rust 1.51: - // https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis - if minor < 51 { - println!("cargo:rustc-cfg=no_ptr_addr_of"); - } -} - -fn rustc_minor_version() -> Option<u32> { - let rustc = env::var_os("RUSTC")?; - let output = Command::new(rustc).arg("--version").output().ok()?; - let version = str::from_utf8(&output.stdout).ok()?; - let mut pieces = version.split('.'); - if pieces.next() != Some("rustc 1") { - return None; - } - pieces.next()?.parse().ok() -} diff --git a/vendor/serde_derive/src/de.rs b/vendor/serde_derive/src/de.rs index 4d60d5a6f..a834a736e 100644 --- a/vendor/serde_derive/src/de.rs +++ b/vendor/serde_derive/src/de.rs @@ -15,9 +15,7 @@ use this; use std::collections::BTreeSet; use std::ptr; -pub fn expand_derive_deserialize( - input: &mut syn::DeriveInput, -) -> Result<TokenStream, Vec<syn::Error>> { +pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> { replace_receiver(input); let ctxt = Ctxt::new(); @@ -69,8 +67,6 @@ pub fn expand_derive_deserialize( Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), - "DESERIALIZE", - ident, impl_block, )) } @@ -1171,6 +1167,22 @@ fn deserialize_enum( variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { + // The variants have already been checked (in ast.rs) that all untagged variants appear at the end + match variants.iter().position(|var| var.attrs.untagged()) { + Some(variant_idx) => { + let (tagged, untagged) = variants.split_at(variant_idx); + let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs)); + deserialize_untagged_enum_after(params, untagged, cattrs, Some(tagged_frag)) + } + None => deserialize_homogeneous_enum(params, variants, cattrs), + } +} + +fn deserialize_homogeneous_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, +) -> Fragment { match cattrs.tag() { attr::TagType::External => deserialize_externally_tagged_enum(params, variants, cattrs), attr::TagType::Internal { tag } => { @@ -1671,6 +1683,16 @@ fn deserialize_untagged_enum( variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { + let first_attempt = None; + deserialize_untagged_enum_after(params, variants, cattrs, first_attempt) +} + +fn deserialize_untagged_enum_after( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, + first_attempt: Option<Expr>, +) -> Fragment { let attempts = variants .iter() .filter(|variant| !variant.attrs.skip_deserializing()) @@ -1679,12 +1701,10 @@ fn deserialize_untagged_enum( params, variant, cattrs, - quote!( - _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content) - ), + quote!(__deserializer), )) }); - + let attempts = first_attempt.into_iter().chain(attempts); // TODO this message could be better by saving the errors from the failed // attempts. The heuristic used by TOML was to count the number of fields // processed before an error, and use the error that happened after the @@ -1699,6 +1719,7 @@ fn deserialize_untagged_enum( quote_block! { let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)); + let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); #( if let _serde::__private::Ok(__ok) = #attempts { @@ -3086,23 +3107,31 @@ struct DeTypeGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceTypeGenerics<'a>(&'a Parameters); +fn de_type_generics_to_tokens( + mut generics: syn::Generics, + borrowed: &BorrowedLifetimes, + tokens: &mut TokenStream, +) { + if borrowed.de_lifetime_param().is_some() { + let def = syn::LifetimeParam { + attrs: Vec::new(), + lifetime: syn::Lifetime::new("'de", Span::call_site()), + colon_token: None, + bounds: Punctuated::new(), + }; + // Prepend 'de lifetime to list of generics + generics.params = Some(syn::GenericParam::Lifetime(def)) + .into_iter() + .chain(generics.params) + .collect(); + } + let (_, ty_generics, _) = generics.split_for_impl(); + ty_generics.to_tokens(tokens); +} + impl<'a> ToTokens for DeTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { - let mut generics = self.0.generics.clone(); - if self.0.borrowed.de_lifetime_param().is_some() { - let def = syn::LifetimeParam { - attrs: Vec::new(), - lifetime: syn::Lifetime::new("'de", Span::call_site()), - colon_token: None, - bounds: Punctuated::new(), - }; - generics.params = Some(syn::GenericParam::Lifetime(def)) - .into_iter() - .chain(generics.params) - .collect(); - } - let (_, ty_generics, _) = generics.split_for_impl(); - ty_generics.to_tokens(tokens); + de_type_generics_to_tokens(self.0.generics.clone(), &self.0.borrowed, tokens); } } @@ -3115,20 +3144,7 @@ impl<'a> ToTokens for InPlaceTypeGenerics<'a> { .chain(generics.params) .collect(); - if self.0.borrowed.de_lifetime_param().is_some() { - let def = syn::LifetimeParam { - attrs: Vec::new(), - lifetime: syn::Lifetime::new("'de", Span::call_site()), - colon_token: None, - bounds: Punctuated::new(), - }; - generics.params = Some(syn::GenericParam::Lifetime(def)) - .into_iter() - .chain(generics.params) - .collect(); - } - let (_, ty_generics, _) = generics.split_for_impl(); - ty_generics.to_tokens(tokens); + de_type_generics_to_tokens(generics, &self.0.borrowed, tokens); } } diff --git a/vendor/serde_derive/src/dummy.rs b/vendor/serde_derive/src/dummy.rs index 2be502713..57e8eabf2 100644 --- a/vendor/serde_derive/src/dummy.rs +++ b/vendor/serde_derive/src/dummy.rs @@ -1,23 +1,11 @@ -use proc_macro2::{Ident, TokenStream}; -use quote::format_ident; +use proc_macro2::TokenStream; use syn; use try; -pub fn wrap_in_const( - serde_path: Option<&syn::Path>, - trait_: &str, - ty: &Ident, - code: TokenStream, -) -> TokenStream { +pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream { let try_replacement = try::replacement(); - let dummy_const = if cfg!(no_underscore_consts) { - format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty)) - } else { - format_ident!("_") - }; - let use_serde = match serde_path { Some(path) => quote! { use #path as _serde; @@ -31,14 +19,10 @@ pub fn wrap_in_const( quote! { #[doc(hidden)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const #dummy_const: () = { + const _: () = { #use_serde #try_replacement #code }; } } - -fn unraw(ident: &Ident) -> String { - ident.to_string().trim_start_matches("r#").to_owned() -} diff --git a/vendor/serde_derive/src/internals/ast.rs b/vendor/serde_derive/src/internals/ast.rs index 2a6950b2a..8bcb0ecd1 100644 --- a/vendor/serde_derive/src/internals/ast.rs +++ b/vendor/serde_derive/src/internals/ast.rs @@ -140,7 +140,7 @@ fn enum_from_ast<'a>( variants: &'a Punctuated<syn::Variant, Token![,]>, container_default: &attr::Default, ) -> Vec<Variant<'a>> { - variants + let variants: Vec<Variant> = variants .iter() .map(|variant| { let attrs = attr::Variant::from_ast(cx, variant); @@ -154,7 +154,20 @@ fn enum_from_ast<'a>( original: variant, } }) - .collect() + .collect(); + + let index_of_last_tagged_variant = variants + .iter() + .rposition(|variant| !variant.attrs.untagged()); + if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant { + for variant in &variants[..index_of_last_tagged_variant] { + if variant.attrs.untagged() { + cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum"); + } + } + } + + variants } fn struct_from_ast<'a>( diff --git a/vendor/serde_derive/src/internals/attr.rs b/vendor/serde_derive/src/internals/attr.rs index b0a7d08a2..bff82191b 100644 --- a/vendor/serde_derive/src/internals/attr.rs +++ b/vendor/serde_derive/src/internals/attr.rs @@ -740,6 +740,7 @@ pub struct Variant { serialize_with: Option<syn::ExprPath>, deserialize_with: Option<syn::ExprPath>, borrow: Option<BorrowAttribute>, + untagged: bool, } struct BorrowAttribute { @@ -762,6 +763,7 @@ impl Variant { let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); let mut borrow = Attr::none(cx, BORROW); + let mut untagged = BoolAttr::none(cx, UNTAGGED); for attr in &variant.attrs { if attr.path() != SERDE { @@ -879,6 +881,8 @@ impl Variant { cx.error_spanned_by(variant, msg); } } + } else if meta.path == UNTAGGED { + untagged.set_true(&meta.path); } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( @@ -905,6 +909,7 @@ impl Variant { serialize_with: serialize_with.get(), deserialize_with: deserialize_with.get(), borrow: borrow.get(), + untagged: untagged.get(), } } @@ -956,6 +961,10 @@ impl Variant { pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { self.deserialize_with.as_ref() } + + pub fn untagged(&self) -> bool { + self.untagged + } } /// Represents field attribute information diff --git a/vendor/serde_derive/src/internals/ctxt.rs b/vendor/serde_derive/src/internals/ctxt.rs index d692c2a44..707bed90e 100644 --- a/vendor/serde_derive/src/internals/ctxt.rs +++ b/vendor/serde_derive/src/internals/ctxt.rs @@ -44,12 +44,19 @@ impl Ctxt { } /// Consume this object, producing a formatted error string if there are errors. - pub fn check(self) -> Result<(), Vec<syn::Error>> { - let errors = self.errors.borrow_mut().take().unwrap(); - match errors.len() { - 0 => Ok(()), - _ => Err(errors), + pub fn check(self) -> syn::Result<()> { + let mut errors = self.errors.borrow_mut().take().unwrap().into_iter(); + + let mut combined = match errors.next() { + Some(first) => first, + None => return Ok(()), + }; + + for rest in errors { + combined.combine(rest); } + + Err(combined) } } diff --git a/vendor/serde_derive/src/lib.rs b/vendor/serde_derive/src/lib.rs index 947033b78..e632cc9f5 100644 --- a/vendor/serde_derive/src/lib.rs +++ b/vendor/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.160")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.164")] #![allow(unknown_lints, bare_trait_objects)] // Ignored clippy lints #![allow( @@ -92,7 +92,7 @@ mod try; pub fn derive_serialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); ser::expand_derive_serialize(&mut input) - .unwrap_or_else(to_compile_errors) + .unwrap_or_else(syn::Error::into_compile_error) .into() } @@ -100,11 +100,6 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream { pub fn derive_deserialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); de::expand_derive_deserialize(&mut input) - .unwrap_or_else(to_compile_errors) + .unwrap_or_else(syn::Error::into_compile_error) .into() } - -fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream { - let compile_errors = errors.iter().map(syn::Error::to_compile_error); - quote!(#(#compile_errors)*) -} diff --git a/vendor/serde_derive/src/pretend.rs b/vendor/serde_derive/src/pretend.rs index d7b953d63..7decbaa52 100644 --- a/vendor/serde_derive/src/pretend.rs +++ b/vendor/serde_derive/src/pretend.rs @@ -97,29 +97,14 @@ fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> Toke let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>(); - #[cfg(not(no_ptr_addr_of))] - { - quote! { - match _serde::__private::None::<&#type_ident #ty_generics> { - _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => { - #( - let _ = _serde::__private::ptr::addr_of!(__v.#members); - )* - } - _ => {} - } - } - } - - #[cfg(no_ptr_addr_of)] - { - let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); - - quote! { - match _serde::__private::None::<#type_ident #ty_generics> { - _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {} - _ => {} + quote! { + match _serde::__private::None::<&#type_ident #ty_generics> { + _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => { + #( + let _ = _serde::__private::ptr::addr_of!(__v.#members); + )* } + _ => {} } } } diff --git a/vendor/serde_derive/src/ser.rs b/vendor/serde_derive/src/ser.rs index f223f713a..b9a9dce21 100644 --- a/vendor/serde_derive/src/ser.rs +++ b/vendor/serde_derive/src/ser.rs @@ -10,9 +10,7 @@ use internals::{attr, replace_receiver, Ctxt, Derive}; use pretend; use this; -pub fn expand_derive_serialize( - input: &mut syn::DeriveInput, -) -> Result<TokenStream, Vec<syn::Error>> { +pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> { replace_receiver(input); let ctxt = Ctxt::new(); @@ -59,8 +57,6 @@ pub fn expand_derive_serialize( Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), - "SERIALIZE", - ident, impl_block, )) } @@ -477,17 +473,19 @@ fn serialize_variant( } }; - let body = Match(match cattrs.tag() { - attr::TagType::External => { + let body = Match(match (cattrs.tag(), variant.attrs.untagged()) { + (attr::TagType::External, false) => { serialize_externally_tagged_variant(params, variant, variant_index, cattrs) } - attr::TagType::Internal { tag } => { + (attr::TagType::Internal { tag }, false) => { serialize_internally_tagged_variant(params, variant, cattrs, tag) } - attr::TagType::Adjacent { tag, content } => { + (attr::TagType::Adjacent { tag, content }, false) => { serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content) } - attr::TagType::None => serialize_untagged_variant(params, variant, cattrs), + (attr::TagType::None, _) | (_, true) => { + serialize_untagged_variant(params, variant, cattrs) + } }); quote! { |