summaryrefslogtreecommitdiffstats
path: root/vendor/derivative/src/debug.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /vendor/derivative/src/debug.rs
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/derivative/src/debug.rs')
-rw-r--r--vendor/derivative/src/debug.rs225
1 files changed, 225 insertions, 0 deletions
diff --git a/vendor/derivative/src/debug.rs b/vendor/derivative/src/debug.rs
new file mode 100644
index 000000000..ed667c1d7
--- /dev/null
+++ b/vendor/derivative/src/debug.rs
@@ -0,0 +1,225 @@
+use proc_macro2;
+
+use ast;
+use attr;
+use matcher;
+use syn;
+use syn::spanned::Spanned;
+use utils;
+
+pub fn derive(input: &ast::Input) -> proc_macro2::TokenStream {
+ let debug_trait_path = debug_trait_path();
+ let fmt_path = fmt_path();
+
+ let formatter = quote_spanned! {input.span=> __f};
+
+ let body = matcher::Matcher::new(matcher::BindingStyle::Ref, input.attrs.is_packed)
+ .with_field_filter(|f: &ast::Field| !f.attrs.ignore_debug())
+ .build_arms(input, "__arg", |_, _, arm_name, style, attrs, bis| {
+ let field_prints = bis.iter().filter_map(|bi| {
+ if bi.field.attrs.ignore_debug() {
+ return None;
+ }
+
+ if attrs.debug_transparent() {
+ return Some(quote_spanned! {arm_name.span()=>
+ #debug_trait_path::fmt(__arg_0, #formatter)
+ });
+ }
+
+ let arg_expr = &bi.expr;
+ let arg_ident = &bi.ident;
+
+ let dummy_debug = bi.field.attrs.debug_format_with().map(|format_fn| {
+ format_with(
+ bi.field,
+ &input.attrs.debug_bound(),
+ &arg_expr,
+ &arg_ident,
+ format_fn,
+ input.generics.clone(),
+ )
+ });
+ let expr = if bi.field.attrs.debug_format_with().is_some() {
+ quote_spanned! {arm_name.span()=>
+ &#arg_ident
+ }
+ } else {
+ quote_spanned! {arm_name.span()=>
+ &&#arg_expr
+ }
+ };
+
+ let builder = if let Some(ref name) = bi.field.ident {
+ let name = name.to_string();
+ quote_spanned! {arm_name.span()=>
+ #dummy_debug
+ let _ = __debug_trait_builder.field(#name, #expr);
+ }
+ } else {
+ quote_spanned! {arm_name.span()=>
+ #dummy_debug
+ let _ = __debug_trait_builder.field(#expr);
+ }
+ };
+
+ Some(builder)
+ });
+
+ let method = match style {
+ ast::Style::Struct => "debug_struct",
+ ast::Style::Tuple | ast::Style::Unit => "debug_tuple",
+ };
+ let method = syn::Ident::new(method, proc_macro2::Span::call_site());
+
+ if attrs.debug_transparent() {
+ quote_spanned! {arm_name.span()=>
+ #(#field_prints)*
+ }
+ } else {
+ let name = arm_name.to_string();
+ quote_spanned! {arm_name.span()=>
+ let mut __debug_trait_builder = #formatter.#method(#name);
+ #(#field_prints)*
+ __debug_trait_builder.finish()
+ }
+ }
+ });
+
+ let name = &input.ident;
+
+ let generics = utils::build_impl_generics(
+ input,
+ &debug_trait_path,
+ needs_debug_bound,
+ |field| field.debug_bound(),
+ |input| input.debug_bound(),
+ );
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ // don't attach a span to prevent issue #58
+ let match_self = quote!(match *self);
+ quote_spanned! {input.span=>
+ #[allow(unused_qualifications)]
+ #[allow(clippy::unneeded_field_pattern)]
+ impl #impl_generics #debug_trait_path for #name #ty_generics #where_clause {
+ fn fmt(&self, #formatter: &mut #fmt_path::Formatter) -> #fmt_path::Result {
+ #match_self {
+ #body
+ }
+ }
+ }
+ }
+}
+
+fn needs_debug_bound(attrs: &attr::Field) -> bool {
+ !attrs.ignore_debug() && attrs.debug_bound().is_none()
+}
+
+/// Return the path of the `Debug` trait, that is `::std::fmt::Debug`.
+fn debug_trait_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::fmt::Debug)
+ } else {
+ parse_quote!(::std::fmt::Debug)
+ }
+}
+
+/// Return the path of the `fmt` module, that is `::std::fmt`.
+fn fmt_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::fmt)
+ } else {
+ parse_quote!(::std::fmt)
+ }
+}
+
+/// Return the path of the `PhantomData` type, that is `::std::marker::PhantomData`.
+fn phantom_path() -> syn::Path {
+ if cfg!(feature = "use_core") {
+ parse_quote!(::core::marker::PhantomData)
+ } else {
+ parse_quote!(::std::marker::PhantomData)
+ }
+}
+
+fn format_with(
+ f: &ast::Field,
+ bounds: &Option<&[syn::WherePredicate]>,
+ arg_expr: &proc_macro2::TokenStream,
+ arg_ident: &syn::Ident,
+ format_fn: &syn::Path,
+ mut generics: syn::Generics,
+) -> proc_macro2::TokenStream {
+ let debug_trait_path = debug_trait_path();
+ let fmt_path = fmt_path();
+ let phantom_path = phantom_path();
+
+ generics
+ .make_where_clause()
+ .predicates
+ .extend(f.attrs.debug_bound().unwrap_or(&[]).iter().cloned());
+
+ generics
+ .params
+ .push(syn::GenericParam::Lifetime(syn::LifetimeDef::new(
+ parse_quote!('_derivative),
+ )));
+ let where_predicates = generics
+ .type_params()
+ .map(|ty| {
+ let mut bounds = syn::punctuated::Punctuated::new();
+ bounds.push(syn::TypeParamBound::Lifetime(syn::Lifetime::new(
+ "'_derivative",
+ proc_macro2::Span::call_site(),
+ )));
+
+ let path = syn::Path::from(syn::PathSegment::from(ty.ident.clone()));
+
+ syn::WherePredicate::Type(syn::PredicateType {
+ lifetimes: None,
+ bounded_ty: syn::Type::Path(syn::TypePath { qself: None, path }),
+ colon_token: Default::default(),
+ bounds,
+ })
+ })
+ .chain(bounds.iter().flat_map(|b| b.iter().cloned()))
+ .collect::<Vec<_>>();
+ generics
+ .make_where_clause()
+ .predicates
+ .extend(where_predicates);
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let ty = f.ty;
+
+ // Leave off the type parameter bounds, defaults, and attributes
+ let phantom = generics.type_params().map(|tp| &tp.ident);
+
+ let mut ctor_generics = generics.clone();
+ *ctor_generics
+ .lifetimes_mut()
+ .last()
+ .expect("There must be a '_derivative lifetime") = syn::LifetimeDef::new(parse_quote!('_));
+ let (_, ctor_ty_generics, _) = ctor_generics.split_for_impl();
+ let ctor_ty_generics = ctor_ty_generics.as_turbofish();
+
+ // don't attach a span to prevent issue #58
+ let match_self = quote!(match self.0);
+ quote_spanned!(format_fn.span()=>
+ let #arg_ident = {
+ struct Dummy #impl_generics (&'_derivative #ty, #phantom_path <(#(#phantom,)*)>) #where_clause;
+
+ impl #impl_generics #debug_trait_path for Dummy #ty_generics #where_clause {
+ fn fmt(&self, __f: &mut #fmt_path::Formatter) -> #fmt_path::Result {
+ #match_self {
+ this => #format_fn(this, __f)
+ }
+ }
+ }
+
+ Dummy #ctor_ty_generics (&&#arg_expr, #phantom_path)
+ };
+ )
+}