diff --git a/components/salsa-macro-rules/src/setup_fn.rs b/components/salsa-macro-rules/src/setup_fn.rs index a59158a1..cf254fa6 100644 --- a/components/salsa-macro-rules/src/setup_fn.rs +++ b/components/salsa-macro-rules/src/setup_fn.rs @@ -92,7 +92,7 @@ macro_rules! setup_fn { #[derive(Copy, Clone)] struct $InternedData<$db_lt>( std::ptr::NonNull<$zalsa::interned::Value<$Configuration>>, - std::marker::PhantomData<&'db $zalsa::interned::Value<$Configuration>>, + std::marker::PhantomData<&$db_lt $zalsa::interned::Value<$Configuration>>, ); static $INTERN_CACHE: $zalsa::IngredientCache<$zalsa::interned::IngredientImpl<$Configuration>> = @@ -109,9 +109,9 @@ macro_rules! setup_fn { type Struct<$db_lt> = $InternedData<$db_lt>; - unsafe fn struct_from_raw<'db>( + unsafe fn struct_from_raw<$db_lt>( ptr: std::ptr::NonNull<$zalsa::interned::Value>, - ) -> Self::Struct<'db> { + ) -> Self::Struct<$db_lt> { $InternedData(ptr, std::marker::PhantomData) } @@ -163,21 +163,21 @@ macro_rules! setup_fn { $zalsa::should_backdate_value(old_value, new_value) } - fn execute<'db>($db: &'db Self::DbView, ($($input_id),*): ($($input_ty),*)) -> Self::Output<'db> { + fn execute<$db_lt>($db: &$db_lt Self::DbView, ($($input_id),*): ($($input_ty),*)) -> Self::Output<$db_lt> { $inner_fn $inner($db, $($input_id),*) } - fn recover_from_cycle<'db>( + fn recover_from_cycle<$db_lt>( db: &$db_lt dyn $Db, cycle: &$zalsa::Cycle, ($($input_id),*): ($($input_ty),*) - ) -> Self::Output<'db> { + ) -> Self::Output<$db_lt> { $($cycle_recovery_fn)*(db, cycle, $($input_id),*) } - fn id_to_input<'db>(db: &'db Self::DbView, key: salsa::Id) -> Self::Input<'db> { + fn id_to_input<$db_lt>(db: &$db_lt Self::DbView, key: salsa::Id) -> Self::Input<$db_lt> { $zalsa::macro_if! { if $needs_interner { $Configuration::intern_ingredient(db).data(key).clone() diff --git a/components/salsa-macro-rules/src/setup_method_body.rs b/components/salsa-macro-rules/src/setup_method_body.rs index 6760b95a..3d900b2f 100644 --- a/components/salsa-macro-rules/src/setup_method_body.rs +++ b/components/salsa-macro-rules/src/setup_method_body.rs @@ -25,7 +25,7 @@ macro_rules! setup_method_body { fn $inner_fn_name($self, db: $($db_ty)*, $($input_id: $input_ty),*) -> $output_ty; } - impl $InnerTrait<$($db_lt)?> for $self_ty { + impl<$($db_lt)?> $InnerTrait<$($db_lt)?> for $self_ty { $inner_fn } diff --git a/components/salsa-macro-rules/src/setup_tracked_struct.rs b/components/salsa-macro-rules/src/setup_tracked_struct.rs index 937fca52..e85777a3 100644 --- a/components/salsa-macro-rules/src/setup_tracked_struct.rs +++ b/components/salsa-macro-rules/src/setup_tracked_struct.rs @@ -11,7 +11,7 @@ macro_rules! setup_tracked_struct { // Name of the struct Struct: $Struct:ident, - // Name of the `$db_lt` lifetime that the user gave + // Name of the `'db` lifetime that the user gave db_lt: $db_lt:lifetime, // Name user gave for `new` diff --git a/components/salsa-macros/src/tracked_impl.rs b/components/salsa-macros/src/tracked_impl.rs index 5bbbc504..19663df3 100644 --- a/components/salsa-macros/src/tracked_impl.rs +++ b/components/salsa-macros/src/tracked_impl.rs @@ -16,7 +16,8 @@ pub(crate) fn tracked_impl( let hygiene = Hygiene::from2(&item); let _: Nothing = syn::parse(args)?; let m = Macro { hygiene }; - m.try_generate(item) + let generated = m.try_generate(item)?; + Ok(generated) } struct Macro { @@ -64,7 +65,10 @@ impl Macro { }; let salsa_tracked_attr = fn_item.attrs.remove(tracked_attr_index); - let args: FnArgs = salsa_tracked_attr.parse_args()?; + let args: FnArgs = match &salsa_tracked_attr.meta { + syn::Meta::Path(..) => Default::default(), + _ => salsa_tracked_attr.parse_args()?, + }; let InnerTrait = self.hygiene.ident("InnerTrait"); let inner_fn_name = self.hygiene.ident("inner_fn_name"); diff --git a/src/lib.rs b/src/lib.rs index f3a378fb..745ef786 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,21 @@ pub use salsa_macros::interned; pub use salsa_macros::tracked; pub use salsa_macros::Update; +pub fn default_database() -> impl Database { + use crate as salsa; + + #[crate::db] + #[derive(Default)] + struct DefaultDatabase { + storage: Storage, + } + + #[crate::db] + impl Database for DefaultDatabase {} + + DefaultDatabase::default() +} + pub mod prelude { pub use crate::Accumulator; pub use crate::Setter; diff --git a/tests/tracked_method_on_tracked_struct.rs b/tests/tracked_method_on_tracked_struct.rs new file mode 100644 index 00000000..b50bd9d6 --- /dev/null +++ b/tests/tracked_method_on_tracked_struct.rs @@ -0,0 +1,66 @@ +use salsa::Database; + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Item {} + +#[salsa::input] +pub struct Input { + name: String, +} + +#[salsa::tracked] +impl Input { + #[salsa::tracked] + pub fn source_tree(self, db: &dyn Database) -> SourceTree<'_> { + SourceTree::new(db, self.name(db).clone()) + } +} + +#[salsa::tracked] +pub struct SourceTree<'db> { + name: String, +} + +#[salsa::tracked] +impl<'db1> SourceTree<'db1> { + #[salsa::tracked(return_ref)] + pub fn inherent_item_name(self, db: &'db1 dyn Database) -> String { + self.name(db) + } +} + +trait ItemName<'db1> { + fn trait_item_name(self, db: &'db1 dyn Database) -> &'db1 String; +} + +#[salsa::tracked] +impl<'db1> ItemName<'db1> for SourceTree<'db1> { + #[salsa::tracked(return_ref)] + fn trait_item_name(self, db: &'db1 dyn Database) -> String { + self.name(db) + } +} + +#[test] +fn test_inherent() { + salsa::default_database().attach(|db| { + let input = Input::new(db, "foo".to_string()); + let source_tree = input.source_tree(db); + expect_test::expect![[r#" + "foo" + "#]] + .assert_debug_eq(source_tree.inherent_item_name(db)); + }) +} + +#[test] +fn test_trait() { + salsa::default_database().attach(|db| { + let input = Input::new(db, "foo".to_string()); + let source_tree = input.source_tree(db); + expect_test::expect![[r#" + "foo" + "#]] + .assert_debug_eq(source_tree.trait_item_name(db)); + }) +}