From fd715619813f634fa07952f0d1b3d3a18b68fd65 Mon Sep 17 00:00:00 2001 From: Bernardo Uriarte Date: Tue, 30 Aug 2022 18:03:18 +0200 Subject: [PATCH] reduce amount of generated code for `DebugWithDb` by moving part of it to `salsa-2022` --- .../salsa-2022-macros/src/salsa_struct.rs | 52 ++++++++----------- components/salsa-2022/src/debug.rs | 26 ++++++++++ 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/components/salsa-2022-macros/src/salsa_struct.rs b/components/salsa-2022-macros/src/salsa_struct.rs index 4374f2f..420cfcd 100644 --- a/components/salsa-2022-macros/src/salsa_struct.rs +++ b/components/salsa-2022-macros/src/salsa_struct.rs @@ -284,41 +284,33 @@ impl SalsaStruct { let db_type = self.db_dyn_ty(); let ident_string = ident.to_string(); - let fields = self.all_fields().map(|field| { - let field_name_string = field.name().to_string(); - let field_getter = field.get_name(); - let field_ty = field.ty(); - // If the field type implements DebugWithDb, use that. - // Otherwise, use Debug. - // That's the "has impl" trick (https://github.com/nvzqz/impls#how-it-works) - parse_quote_spanned! {field.field.span()=> - .field(#field_name_string, { - struct Test(::core::marker::PhantomData, ::core::marker::PhantomData); + // `::salsa::debug::helper::SalsaDebug` will use `DebugWithDb` or fallbak to `Debug` + let fields = self + .all_fields() + .map(|field| { + let field_name_string = field.name().to_string(); + let field_getter = field.get_name(); + let field_ty = field.ty(); - #[allow(dead_code)] - impl, Db: ?Sized> Test { - fn salsa_debug<'a, 'b: 'a>(a: &'a T, db: &'b Db) -> ::salsa::debug::DebugWith<'a, Db> { - a.debug(db) - } - } - - trait Fallback { - fn salsa_debug<'a, 'b>(a: &'a T, _db: &'b Db) -> &'a dyn ::core::fmt::Debug { - a - } - } - - impl Fallback for Everything {} - - #[allow(clippy::needless_borrow)] - &Test::<#field_ty, #db_type>::salsa_debug(&self.#field_getter(_db), _db) - }) - } - }).collect::>(); + parse_quote_spanned! {field.field.span() => + .field( + #field_name_string, + &::salsa::debug::helper::SalsaDebug::<#field_ty, #db_type>::salsa_debug( + #[allow(clippy::needless_borrow)] + &self.#field_getter(_db), + _db + ) + ) + } + }) + .collect::>(); + // `use ::salsa::debug::helper::Fallback` is needed for the fallback to `Debug` impl parse_quote_spanned! {ident.span()=> impl ::salsa::DebugWithDb<#db_type> for #ident { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>, _db: &#db_type) -> ::std::fmt::Result { + #[allow(unused_imports)] + use ::salsa::debug::helper::Fallback; f.debug_struct(#ident_string) .field("[salsa id]", &self.0.as_u32()) #(#fields)* diff --git a/components/salsa-2022/src/debug.rs b/components/salsa-2022/src/debug.rs index a32daac..26f22b1 100644 --- a/components/salsa-2022/src/debug.rs +++ b/components/salsa-2022/src/debug.rs @@ -159,3 +159,29 @@ where f.debug_list().entries(elements).finish() } } + +/// This is used by the macro generated code. +/// If the field type implements `DebugWithDb`, uses that, otherwise, uses `Debug`. +/// That's the "has impl" trick (https://github.com/nvzqz/impls#how-it-works) +#[doc(hidden)] +pub mod helper { + use super::{DebugWith, DebugWithDb}; + use std::{fmt, marker::PhantomData}; + + pub trait Fallback { + fn salsa_debug<'a, 'b>(a: &'a T, _db: &'b Db) -> &'a dyn fmt::Debug { + a + } + } + + pub struct SalsaDebug(PhantomData, PhantomData); + + impl, Db: ?Sized> SalsaDebug { + #[allow(dead_code)] + pub fn salsa_debug<'a, 'b: 'a>(a: &'a T, db: &'b Db) -> DebugWith<'a, Db> { + a.debug(db) + } + } + + impl Fallback for Everything {} +}