Open gavrilikhin-d opened 5 months ago
Haha, I already add this trait in my personal customized version of salsa
@xiyuzhai how did you do it? I have troubles with references lifetimes
https://github.com/xiyuzhai-husky-lang/husky/blob/main/crates/abstractions/salsa/src/display.rs
I imitated DebugWithDb's implementation. However, my implementation differs from salsa in that I remove the generic parameter Db, and use a single Db type for the whole workspace to save compilation time significantly.
pub trait DisplayWithDb {
fn display<'me, 'db>(&'me self, db: &'me Db) -> DisplayWith<'me>
where
Self: Sized + 'me,
{
DisplayWith {
value: BoxRef::Ref(self),
db,
}
}
fn display_with<'me, 'db>(&'me self, db: &'me Db) -> DisplayWith<'me>
where
Self: Sized + 'me,
{
DisplayWith {
value: BoxRef::Ref(self),
db,
}
}
/// if `level` is `false` only identity fields should be read, which means:
/// - for [#\[salsa::input\]](salsa_macros::input) no fields
/// - for [#\[salsa::tracked\]](salsa_macros::tracked) only fields with `#[id]` attribute
/// - for [#\[salsa::interned\]](salsa_macros::interned) any field
fn display_fmt_with_db(&self, f: &mut fmt::Formatter<'_>, db: &Db) -> fmt::Result;
}
I came up with something like this at the end:
use std::fmt::{self, Display, Formatter, FormatterFn};
pub trait DisplayWithDb<'me, DB: ?Sized + 'me> {
fn fmt_with(&self, db: &DB, f: &mut Formatter<'_>) -> fmt::Result;
fn display_with(&self, db: &DB) -> FormatterFn<impl Fn(&mut Formatter<'_>) -> fmt::Result> {
FormatterFn(|f| self.fmt_with(db, f)) // Unstable rust. Write a struct wrapper, if you want to use stable rust
}
fn to_string_with(&self, db: &DB) -> String {
self.display_with(db).to_string()
}
}
impl<'me, DB: ?Sized + 'me, D: Display> DisplayWithDb<'me, DB> for D {
fn fmt_with(&self, _db: &DB, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self, f)
}
}
Implement it like this:
#[salsa::interned]
pub struct Typename {
#[return_ref]
pub text: String,
}
impl<'me> DisplayWithDb<'me, dyn Db + 'me> for Typename {
fn fmt_with(&self, db: &dyn Db, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.text(db))
}
}
There is something tricky with dyn Db
lifetimes that forces me to specify them explicitly
Add trait to Display items with database