reduce amount of generated code for DebugWithDb

by moving part of it to `salsa-2022`
This commit is contained in:
Bernardo Uriarte 2022-08-30 18:03:18 +02:00
parent 1cabfdb077
commit fd71561981
2 changed files with 48 additions and 30 deletions

View file

@ -284,41 +284,33 @@ impl<A: AllowedOptions> SalsaStruct<A> {
let db_type = self.db_dyn_ty(); let db_type = self.db_dyn_ty();
let ident_string = ident.to_string(); let ident_string = ident.to_string();
let fields = self.all_fields().map(|field| { // `::salsa::debug::helper::SalsaDebug` will use `DebugWithDb` or fallbak to `Debug`
let field_name_string = field.name().to_string(); let fields = self
let field_getter = field.get_name(); .all_fields()
let field_ty = field.ty(); .map(|field| {
// If the field type implements DebugWithDb, use that. let field_name_string = field.name().to_string();
// Otherwise, use Debug. let field_getter = field.get_name();
// That's the "has impl" trick (https://github.com/nvzqz/impls#how-it-works) let field_ty = field.ty();
parse_quote_spanned! {field.field.span()=>
.field(#field_name_string, {
struct Test<T, Db: ?Sized>(::core::marker::PhantomData<T>, ::core::marker::PhantomData<Db>);
#[allow(dead_code)] parse_quote_spanned! {field.field.span() =>
impl<T: ::salsa::debug::DebugWithDb<Db>, Db: ?Sized> Test<T, Db> { .field(
fn salsa_debug<'a, 'b: 'a>(a: &'a T, db: &'b Db) -> ::salsa::debug::DebugWith<'a, Db> { #field_name_string,
a.debug(db) &::salsa::debug::helper::SalsaDebug::<#field_ty, #db_type>::salsa_debug(
} #[allow(clippy::needless_borrow)]
} &self.#field_getter(_db),
_db
trait Fallback<T: ::core::fmt::Debug, Db: ?Sized> { )
fn salsa_debug<'a, 'b>(a: &'a T, _db: &'b Db) -> &'a dyn ::core::fmt::Debug { )
a }
} })
} .collect::<Vec<TokenStream>>();
impl<Everything, Db: ?Sized, T: ::core::fmt::Debug> Fallback<T, Db> for Everything {}
#[allow(clippy::needless_borrow)]
&Test::<#field_ty, #db_type>::salsa_debug(&self.#field_getter(_db), _db)
})
}
}).collect::<Vec<TokenStream>>();
// `use ::salsa::debug::helper::Fallback` is needed for the fallback to `Debug` impl
parse_quote_spanned! {ident.span()=> parse_quote_spanned! {ident.span()=>
impl ::salsa::DebugWithDb<#db_type> for #ident { impl ::salsa::DebugWithDb<#db_type> for #ident {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>, _db: &#db_type) -> ::std::fmt::Result { 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) f.debug_struct(#ident_string)
.field("[salsa id]", &self.0.as_u32()) .field("[salsa id]", &self.0.as_u32())
#(#fields)* #(#fields)*

View file

@ -159,3 +159,29 @@ where
f.debug_list().entries(elements).finish() 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<T: fmt::Debug, Db: ?Sized> {
fn salsa_debug<'a, 'b>(a: &'a T, _db: &'b Db) -> &'a dyn fmt::Debug {
a
}
}
pub struct SalsaDebug<T, Db: ?Sized>(PhantomData<T>, PhantomData<Db>);
impl<T: DebugWithDb<Db>, Db: ?Sized> SalsaDebug<T, Db> {
#[allow(dead_code)]
pub fn salsa_debug<'a, 'b: 'a>(a: &'a T, db: &'b Db) -> DebugWith<'a, Db> {
a.debug(db)
}
}
impl<Everything, Db: ?Sized, T: fmt::Debug> Fallback<T, Db> for Everything {}
}