From b8b094d6766fec6da793d7d919d07f3ca3be9306 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Fri, 29 Mar 2024 19:04:47 +0100 Subject: [PATCH] Use re-exported ::core from musli --- crates/musli-macros/src/de.rs | 107 +++++++++++--------- crates/musli-macros/src/en.rs | 59 ++++++----- crates/musli-macros/src/expander.rs | 2 + crates/musli-macros/src/internals/build.rs | 2 + crates/musli-macros/src/internals/ctxt.rs | 11 +- crates/musli-macros/src/internals/tokens.rs | 29 ++---- crates/musli/src/lib.rs | 17 ++++ 7 files changed, 125 insertions(+), 102 deletions(-) diff --git a/crates/musli-macros/src/de.rs b/crates/musli-macros/src/de.rs index 6f466ab39..0ddf4c79a 100644 --- a/crates/musli-macros/src/de.rs +++ b/crates/musli-macros/src/de.rs @@ -84,23 +84,25 @@ pub(crate) fn expand_decode_entry(e: Build<'_>) -> Result { let (_, type_generics, _) = e.input.generics.split_for_impl(); Ok(quote! { - #[automatically_derived] - #[allow(clippy::init_numbered_fields)] - #[allow(clippy::let_unit_value)] - impl #impl_generics #decode_t<#lt, #mode_ident> for #type_ident #type_generics #where_clause { - #[inline] - fn decode<#d_param>(#ctx_var: &#d_param::Cx, #root_decoder_var: #d_param) -> #result::Error> - where - #d_param: #decoder_t<#lt, Mode = #mode_ident>, - { - #body + const _: () = { + #[automatically_derived] + #[allow(clippy::init_numbered_fields)] + #[allow(clippy::let_unit_value)] + impl #impl_generics #decode_t<#lt, #mode_ident> for #type_ident #type_generics #where_clause { + #[inline] + fn decode<#d_param>(#ctx_var: &#d_param::Cx, #root_decoder_var: #d_param) -> #result::Error> + where + #d_param: #decoder_t<#lt, Mode = #mode_ident>, + { + #body + } } - } + }; }) } fn decode_struct(cx: &Ctxt<'_>, e: &Build<'_>, st: &Body<'_>) -> Result { - let Tokens { result, .. } = e.tokens; + let Tokens { result_ok, .. } = e.tokens; let body = match st.packing { Packing::Tagged => decode_tagged(cx, e, st, None)?, @@ -108,7 +110,7 @@ fn decode_struct(cx: &Ctxt<'_>, e: &Build<'_>, st: &Body<'_>) -> Result decode_transparent(cx, e, st)?, }; - Ok(quote!(#result::Ok({ #body }))) + Ok(quote!(#result_ok({ #body }))) } fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { @@ -127,7 +129,8 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { fmt, option_none, option_some, - result, + result_err, + result_ok, skip, str_ty, struct_decoder_t, @@ -146,7 +149,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { // Trying to decode an uninhabitable type. if en.variants.is_empty() { - return Ok(quote!(#result::Err(#context_t::uninhabitable(#ctx_var, #type_name)))); + return Ok(quote!(#result_err(#context_t::uninhabitable(#ctx_var, #type_name)))); } let body_decoder_var = e.cx.ident("body_decoder"); @@ -167,14 +170,14 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { Some(ident) => { quote! {{ if #skip::is_unsupported(#decoder_t::try_skip(#variant_decoder_t::decode_value(#variant_decoder_var)?)?) { - return #result::Err(#context_t::invalid_variant_tag(#ctx_var, #type_name, #variant_tag_var)); + return #result_err(#context_t::invalid_variant_tag(#ctx_var, #type_name, #variant_tag_var)); } Self::#ident {} }} } None => quote! { - return #result::Err(#context_t::invalid_variant_tag(#ctx_var, #type_name, #variant_tag_var)) + return #result_err(#context_t::invalid_variant_tag(#ctx_var, #type_name, #variant_tag_var)) }, }; @@ -199,17 +202,17 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { variant_alloc = Some(quote! { let #option_some(mut #variant_alloc_var) = #context_t::alloc(#ctx_var) else { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); }; }); decode_tag = quote! { #decoder_t::decode_string(#variant_decoder_var, #visit_owned_fn("a string variant tag", |string: &str| { - #result::Ok(match string { + #result_ok(match string { #(#arms,)* string => { if !#buf_t::write(&mut #variant_alloc_var, #str_ty::as_bytes(string)) { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); } #option_none @@ -332,7 +335,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { #fallback }; - #result::Ok(#output_var) + #result_ok(#output_var) })?; #leave @@ -398,13 +401,13 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { field_alloc = Some(quote! { let #option_some(mut #field_alloc_var) = #context_t::alloc(#ctx_var) else { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); }; }); let decode_outcome = quote! { #decoder_t::decode_string(decoder, #visit_owned_fn("a string field tag", |string: &str| { - #result::Ok(match string { + #result_ok(match string { #field_tag => Outcome::Tag, string => { if !#buf_t::write(&mut #field_alloc_var, #str_ty::as_bytes(string)) { @@ -423,11 +426,11 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { break #struct_field_decoder_t::decode_field_value(#entry_var)?; } Outcome::AllocErr => { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); } Outcome::Err => { if #skip::is_unsupported(#decoder_t::try_skip(#struct_field_decoder_t::decode_field_value(#entry_var)?)?) { - return #result::Err(#context_t::invalid_field_string_tag(#ctx_var, #type_name, #field_alloc_var)); + return #result_err(#context_t::invalid_field_string_tag(#ctx_var, #type_name, #field_alloc_var)); } } } @@ -443,7 +446,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { } field => { if #skip::is_unsupported(#decoder_t::try_skip(#struct_field_decoder_t::decode_field_value(#entry_var)?)?) { - return #result::Err(#context_t::invalid_field_tag(#ctx_var, #type_name, field)); + return #result_err(#context_t::invalid_field_tag(#ctx_var, #type_name, field)); } } } @@ -475,7 +478,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { let #variant_tag_var #name_type = { let #variant_decoder_var = loop { let #option_some(mut #entry_var) = #struct_decoder_t::decode_field(st)? else { - return #result::Err(#context_t::missing_variant_field(#ctx_var, #type_name, #field_tag)); + return #result_err(#context_t::missing_variant_field(#ctx_var, #type_name, #field_tag)); }; let decoder = #struct_field_decoder_t::decode_field_name(&mut #entry_var)?; @@ -488,7 +491,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { #decode_tag }; - #result::Ok(#variant_tag_var) + #result_ok(#variant_tag_var) })?; let #output_var = match #variant_tag_var { @@ -497,7 +500,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { }; #leave - #result::Ok(#output_var) + #result_ok(#output_var) }}) } EnumTagging::Adjacent { @@ -554,13 +557,13 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { field_alloc = Some(quote! { let #option_some(mut #field_alloc_var) = #context_t::alloc(#ctx_var) else { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); }; }); decode_match = quote! { let outcome = #decoder_t::decode_string(decoder, #visit_owned_fn("a string field tag", |string: &str| { - #result::Ok(match string { + #result_ok(match string { #tag => Outcome::Tag, #content => Outcome::Content, string => { @@ -581,22 +584,22 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { } Outcome::Content => { let #option_some(#variant_tag_var #name_type) = #tag_var else { - return #result::Err(#context_t::invalid_field_tag(#ctx_var, #type_name, #tag)); + return #result_err(#context_t::invalid_field_tag(#ctx_var, #type_name, #tag)); }; let #body_decoder_var = #struct_field_decoder_t::decode_field_value(#entry_var)?; - break #result::Ok(match #variant_tag_var { + break #result_ok(match #variant_tag_var { #(#patterns,)* #fallback }); } Outcome::AllocErr => { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); } Outcome::Err => { if #skip::is_unsupported(#decoder_t::try_skip(#struct_field_decoder_t::decode_field_value(#entry_var)?)?) { - return #result::Err(#context_t::invalid_field_string_tag(#ctx_var, #type_name, #field_alloc_var)); + return #result_err(#context_t::invalid_field_string_tag(#ctx_var, #type_name, #field_alloc_var)); } } } @@ -614,19 +617,19 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { } #content => { let #option_some(#variant_tag_var #name_type) = #tag_var else { - return #result::Err(#context_t::invalid_field_tag(#ctx_var, #type_name, #tag)); + return #result_err(#context_t::invalid_field_tag(#ctx_var, #type_name, #tag)); }; let #body_decoder_var = #struct_field_decoder_t::decode_field_value(#entry_var)?; - break #result::Ok(match #variant_tag_var { + break #result_ok(match #variant_tag_var { #(#patterns,)* #fallback }); } field => { if #skip::is_unsupported(#decoder_t::try_skip(#struct_field_decoder_t::decode_field_value(#entry_var)?)?) { - return #result::Err(#context_t::invalid_field_tag(#ctx_var, #type_name, field)); + return #result_err(#context_t::invalid_field_tag(#ctx_var, #type_name, field)); } } } @@ -657,7 +660,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { let #output_var = loop { let #option_some(mut #entry_var) = #struct_decoder_t::decode_field(#struct_decoder_var)? else { - return #result::Err(#context_t::invalid_field_tag(#ctx_var, #type_name, "other")); + return #result_err(#context_t::invalid_field_tag(#ctx_var, #type_name, "other")); }; let decoder = #struct_field_decoder_t::decode_field_name(&mut #entry_var)?; @@ -667,7 +670,7 @@ fn decode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum) -> Result { }; #leave - #result::Ok(#output_var) + #result_ok(#output_var) })? }}) } @@ -720,7 +723,9 @@ fn decode_tagged( fmt, option_none, option_some, - result, + option, + result_err, + result_ok, skip, struct_decoder_t, struct_field_decoder_t, @@ -781,7 +786,7 @@ fn decode_tagged( quote!(#default_function()) } else { quote! { - return #result::Err(#context_t::expected_tag(#ctx_var, #type_name, #tag)) + return #result_err(#context_t::expected_tag(#ctx_var, #type_name, #tag)) } }; @@ -822,17 +827,17 @@ fn decode_tagged( field_alloc = Some(quote! { let #option_some(mut #field_alloc_var) = #context_t::alloc(#ctx_var) else { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); }; }); decode_tag = quote! { #decoder_t::decode_string(#struct_decoder_var, #visit_owned_fn("a string variant tag", |string: &str| { - #result::Ok(match string { + #result_ok(match string { #(#patterns,)* string => { if !#buf_t::write(&mut #field_alloc_var, #str_ty::as_bytes(string)) { - return #result::Err(#context_t::alloc_failed(#ctx_var)); + return #result_err(#context_t::alloc_failed(#ctx_var)); } #option_none @@ -911,7 +916,7 @@ fn decode_tagged( let mut body = quote! { if #skip::is_unsupported(#decoder_t::try_skip(#struct_field_decoder_t::decode_field_value(#struct_decoder_var)?)?) { - return #result::Err(#unsupported); + return #result_err(#unsupported); } }; @@ -949,7 +954,7 @@ fn decode_tagged( let decls = st .fields .iter() - .map(|Field { var, .. }| quote!(let mut #var = #option_none;)); + .map(|Field { var, ty, .. }| quote!(let mut #var: #option<#ty> = #option_none;)); let enter = (cx.trace && cx.trace_body).then(|| { quote! { @@ -976,7 +981,7 @@ fn decode_tagged( } #leave - #result::Ok(#path { #assigns }) + #result_ok(#path { #assigns }) })? }}) } @@ -1044,6 +1049,7 @@ fn decode_packed(cx: &Ctxt<'_>, e: &Build<'_>, st_: &Body<'_>) -> Result, e: &Build<'_>, st_: &Body<'_>) -> Result) -> Result { let (_, type_generics, _) = e.input.generics.split_for_impl(); Ok(quote! { - #[automatically_derived] - impl #impl_generics #encode_t<#mode_ident> for #type_ident #type_generics #where_clause { - #[inline] - fn encode<#e_param>(&self, #ctx_var: &#e_param::Cx, #encoder_var: #e_param) -> #result<<#e_param as #encoder_t>::Ok, <#e_param as #encoder_t>::Error> - where - #e_param: #encoder_t, - { - #body + const _: () = { + #[automatically_derived] + impl #impl_generics #encode_t<#mode_ident> for #type_ident #type_generics #where_clause { + #[inline] + fn encode<#e_param>(&self, #ctx_var: &#e_param::Cx, #encoder_var: #e_param) -> #result<<#e_param as #encoder_t>::Ok, <#e_param as #encoder_t>::Error> + where + #e_param: #encoder_t, + { + #body + } } - } + }; }) } @@ -86,7 +88,7 @@ fn encode_struct(cx: &Ctxt<'_>, e: &Build<'_>, st: &Body<'_>) -> Result, e: &Build<'_>, st: &Body<'_>) -> Result, e: &Build<'_>, st: &Body<'_>) -> Result, e: &Build<'_>, st: &Body<'_>) -> Result { @@ -180,7 +182,8 @@ fn insert_fields<'st>( let Tokens { context_t, pack_encoder_t, - result, + result_ok, + struct_encoder_t, struct_field_encoder_t, .. @@ -238,7 +241,7 @@ fn insert_fields<'st>( #encode_t_encode(&#tag, #ctx_var, #field_encoder_var)?; let #value_encoder_var = #struct_field_encoder_t::encode_field_value(#pair_encoder_var)?; #encode_path(#access, #ctx_var, #value_encoder_var)?; - #result::Ok(()) + #result_ok(()) })?; #leave @@ -281,7 +284,7 @@ fn encode_enum(cx: &Ctxt<'_>, e: &Build<'_>, en: &Enum<'_>) -> Result, e: &Build<'_>, en: &Enum<'_>) -> Result { pub(crate) name: Option, pub(crate) attr: attr::Field, pub(crate) ident: Option<&'a syn::Ident>, + pub(crate) ty: &'a syn::Type, } pub(crate) struct StructData<'a> { @@ -81,6 +82,7 @@ impl<'a> Expander<'a> { .map(|ident| syn::LitStr::new(&ident.to_string(), ident.span())), attr: attr::field_attrs(cx, &field.attrs), ident: field.ident.as_ref(), + ty: &field.ty, }) .collect() } diff --git a/crates/musli-macros/src/internals/build.rs b/crates/musli-macros/src/internals/build.rs index cf5e9dd07..2c3b307f2 100644 --- a/crates/musli-macros/src/internals/build.rs +++ b/crates/musli-macros/src/internals/build.rs @@ -173,6 +173,7 @@ pub(crate) struct Field<'a> { pub(crate) member: syn::Member, pub(crate) packing: Packing, pub(crate) var: syn::Ident, + pub(crate) ty: &'a syn::Type, } /// Setup a build. @@ -477,6 +478,7 @@ fn setup_field<'a>( member, packing, var, + ty: data.ty, }) } diff --git a/crates/musli-macros/src/internals/ctxt.rs b/crates/musli-macros/src/internals/ctxt.rs index 22380dd55..3c22287d2 100644 --- a/crates/musli-macros/src/internals/ctxt.rs +++ b/crates/musli-macros/src/internals/ctxt.rs @@ -90,13 +90,13 @@ impl Ctxt { #[cfg(not(feature = "verbose"))] { - _ = write!(inner.b1, "_{extra}{index}"); + _ = write!(inner.b1, "_{index}{extra}"); } #[cfg(feature = "verbose")] { let name = name.strip_prefix("_").unwrap_or(name); - _ = write!(inner.b1, "_{extra}{name}"); + _ = write!(inner.b1, "_{name}{extra}"); } let ident = syn::Ident::new(&inner.b1, span); @@ -106,7 +106,10 @@ impl Ctxt { /// Build a type identifier with a span. pub(crate) fn type_with_span(&self, name: &str, span: Span) -> syn::Ident { - let name = format!("T{name}"); - syn::Ident::new(&name, span) + let mut inner = self.inner.borrow_mut(); + _ = write!(inner.b1, "__{name}"); + let ident = syn::Ident::new(&inner.b1, span); + inner.b1.clear(); + ident } } diff --git a/crates/musli-macros/src/internals/tokens.rs b/crates/musli-macros/src/internals/tokens.rs index 8d9d5ca09..877ef6d34 100644 --- a/crates/musli-macros/src/internals/tokens.rs +++ b/crates/musli-macros/src/internals/tokens.rs @@ -1,5 +1,4 @@ use proc_macro2::Span; -use syn::Token; pub(crate) struct Tokens { pub(crate) as_decoder_t: syn::Path, @@ -14,11 +13,14 @@ pub(crate) struct Tokens { pub(crate) encode_t: syn::Path, pub(crate) encoder_t: syn::Path, pub(crate) fmt: syn::Path, + pub(crate) option: syn::Path, pub(crate) option_none: syn::Path, pub(crate) option_some: syn::Path, pub(crate) pack_decoder_t: syn::Path, pub(crate) pack_encoder_t: syn::Path, pub(crate) result: syn::Path, + pub(crate) result_ok: syn::Path, + pub(crate) result_err: syn::Path, pub(crate) skip: syn::Path, pub(crate) str_ty: syn::Path, pub(crate) struct_decoder_t: syn::Path, @@ -41,21 +43,24 @@ impl Tokens { decode_t: path(span, prefix, ["de", "Decode"]), decode_bytes_t: path(span, prefix, ["de", "DecodeBytes"]), decoder_t: path(span, prefix, ["de", "Decoder"]), - default_function: core(span, ["default", "Default", "default"]), + default_function: path(span, prefix, ["__priv", "default"]), default_mode: path(span, prefix, ["mode", "DefaultMode"]), encode_t: path(span, prefix, ["en", "Encode"]), encode_bytes_t: path(span, prefix, ["en", "EncodeBytes"]), encoder_t: path(span, prefix, ["en", "Encoder"]), - fmt: core(span, ["fmt"]), - option_none: core(span, ["option", "Option", "None"]), - option_some: core(span, ["option", "Option", "Some"]), + fmt: path(span, prefix, ["__priv", "fmt"]), + option: path(span, prefix, ["__priv", "Option"]), + option_none: path(span, prefix, ["__priv", "None"]), + option_some: path(span, prefix, ["__priv", "Some"]), pack_decoder_t: path(span, prefix, ["de", "PackDecoder"]), str_ty: primitive(span, "str"), struct_decoder_t: path(span, prefix, ["de", "StructDecoder"]), struct_field_decoder_t: path(span, prefix, ["de", "StructFieldDecoder"]), struct_encoder_t: path(span, prefix, ["en", "StructEncoder"]), struct_field_encoder_t: path(span, prefix, ["en", "StructFieldEncoder"]), - result: core(span, ["result", "Result"]), + result: path(span, prefix, ["__priv", "Result"]), + result_ok: path(span, prefix, ["__priv", "Ok"]), + result_err: path(span, prefix, ["__priv", "Err"]), skip: path(span, prefix, ["de", "Skip"]), pack_encoder_t: path(span, prefix, ["en", "PackEncoder"]), trace_decode_t: path(span, prefix, ["de", "TraceDecode"]), @@ -77,18 +82,6 @@ fn path(span: Span, prefix: &syn::Path, segments: [&'static str; path } -fn core(span: Span, segments: [&'static str; N]) -> syn::Path { - let core = syn::Ident::new("core", span); - let mut path = syn::Path::from(core); - path.leading_colon = Some(::default()); - - for segment in segments { - path.segments.push(syn::Ident::new(segment, span).into()); - } - - path -} - fn primitive(span: Span, primitive: &'static str) -> syn::Path { let core = syn::Ident::new(primitive, span); syn::Path::from(core) diff --git a/crates/musli/src/lib.rs b/crates/musli/src/lib.rs index 05f7fa637..67dcca60c 100644 --- a/crates/musli/src/lib.rs +++ b/crates/musli/src/lib.rs @@ -575,3 +575,20 @@ pub use musli_macros::decoder; /// ``` #[doc(inline)] pub use musli_macros::visitor; + +/// Internal implementation details of musli. +/// +/// Using these directly is not supported. +#[doc(hidden)] +pub mod __priv { + pub use ::core::option::Option; + pub use ::core::result::Result; + pub use ::core::fmt; + + pub fn default() -> T where T: ::core::default::Default { + ::core::default::Default::default() + } + + pub use Option::{None, Some}; + pub use Result::{Ok, Err}; +}