Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions components/salsa-macro-rules/src/macro_if.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ macro_rules! macro_if {
(if0 $n:literal { $($t:tt)* } else { $($f:tt)*}) => {
$($f)*
};

(iftt () { $($t:tt)* } else { $($f:tt)*}) => {
$($f)*
};

(iftt ($($tt:tt)+) { $($t:tt)* } else { $($f:tt)*}) => {
$($t)*
};
}
66 changes: 51 additions & 15 deletions components/salsa-macro-rules/src/setup_interned_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,22 +256,58 @@ macro_rules! setup_interned_struct {
)
}
)*
}

/// Default debug formatting for this struct (may be useful if you define your own `Debug` impl)
pub fn default_debug_fmt(this: Self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
$zalsa::with_attached_database(|db| {
let zalsa = db.zalsa();
let fields = $Configuration::ingredient(zalsa).fields(zalsa, this);
let mut f = f.debug_struct(stringify!($Struct));
$(
let f = f.field(stringify!($field_id), &fields.$field_index);
)*
f.finish()
}).unwrap_or_else(|| {
f.debug_tuple(stringify!($Struct))
.field(&$zalsa::AsId::as_id(&this))
.finish()
})
// Duplication can be dropped here once we no longer allow the `no_lifetime` hack
$zalsa::macro_if! {
iftt ($($db_lt_arg)?) {
impl $Struct<'_> {
Comment on lines +263 to +264
Copy link
Member

@ibraheemdev ibraheemdev Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't impl<$($db_lt_arg)?> $Struct<$($db_lt_arg)?> work? Why does this need a separate impl block at all?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That causes issues with the higher ranked where clauses due to lifetime shadowing unfortunately

/// Default debug formatting for this struct (may be useful if you define your own `Debug` impl)
pub fn default_debug_fmt(this: Self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
where
// rustc rejects trivial bounds, but it cannot see through higher-ranked bounds
// with its check :^)
$(for<$db_lt> $field_ty: std::fmt::Debug),*
{
$zalsa::with_attached_database(|db| {
let zalsa = db.zalsa();
let fields = $Configuration::ingredient(zalsa).fields(zalsa, this);
let mut f = f.debug_struct(stringify!($Struct));
$(
let f = f.field(stringify!($field_id), &fields.$field_index);
)*
f.finish()
}).unwrap_or_else(|| {
f.debug_tuple(stringify!($Struct))
.field(&$zalsa::AsId::as_id(&this))
.finish()
})
}
}
} else {
impl $Struct {
/// Default debug formatting for this struct (may be useful if you define your own `Debug` impl)
pub fn default_debug_fmt(this: Self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
where
// rustc rejects trivial bounds, but it cannot see through higher-ranked bounds
// with its check :^)
$(for<$db_lt> $field_ty: std::fmt::Debug),*
{
$zalsa::with_attached_database(|db| {
let zalsa = db.zalsa();
let fields = $Configuration::ingredient(zalsa).fields(zalsa, this);
let mut f = f.debug_struct(stringify!($Struct));
$(
let f = f.field(stringify!($field_id), &fields.$field_index);
)*
f.finish()
}).unwrap_or_else(|| {
f.debug_tuple(stringify!($Struct))
.field(&$zalsa::AsId::as_id(&this))
.finish()
})
}
}
}
}
};
Expand Down
51 changes: 51 additions & 0 deletions tests/debug_bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#![cfg(feature = "inventory")]

//! Test that debug and non-debug structs compile correctly

#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
struct NotDebug;
#[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash, Debug)]
struct Debug;

#[salsa::input(debug)]
struct DebugInput {
field: Debug,
}

#[salsa::input]
struct NotDebugInput {
field: NotDebug,
}

#[salsa::interned(debug)]
struct DebugInterned {
field: Debug,
}

#[salsa::interned]
struct NotDebugInterned {
field: NotDebug,
}

#[salsa::interned(no_lifetime, debug)]
struct DebugInternedNoLifetime {
field: Debug,
}

#[salsa::interned(no_lifetime)]
struct NotDebugInternedNoLifetime {
field: NotDebug,
}

#[salsa::tracked(debug)]
struct DebugTracked<'db> {
field: Debug,
}

#[salsa::tracked]
struct NotDebugTracked<'db> {
field: NotDebug,
}

#[test]
fn ok() {}