You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was thinking about how this enum will use 2 words and not 1 and I realized that, given that each variant is just storing an Id, and that we can go from an Id to an IngredientIndex (it's stored on the page), we could have a proc-macro that takes such an enum and returns a special struct that just stores a single Id. It could then be converted into an enum readily enough. You also downcast it.
I'm imagining the following:
First, add two methods to salsa::Id, fn is<S>(self, db: &dyn Database) -> bool and fn downcast<S>(self, db: &dyn Database) -> Option<S>, where S: SalsaStructInDb<'_>. These methods can lookup the id in db.table, identify the ingredient index on the from the Page, compare that to the ingredient index for S, and then do the appropriate thing. (We might also want to tweak the FromId or other traits in a similar-ish way.)
Next, create a proc macro named supertype (bikeshed) which expects an enum with one lifetime argument and where each variant has a single argument:
// A struct to store the id itself#[derive(Copy,Clone, ...)]structFoo<'db>{id:Id}// Original enum, but with a tweaked name (should be configurable)enumFooVariants<'db>{A(Bar<'db>),
...
Z(Baz<'db>),}// From impls to "upcast" into the struct; these just take the `id`impl<'db>From<Bar<'db>>forFoo<'db>{ ... }// From impls to "upcast" into the enum; these pick the appropriate variantimpl<'db>From<Bar<'db>>forFooVariants<'db>{ ... }// From impls from the variants structimpl<'db>From<FooVariants<'db>>forFoo<'db>{ ... }implFoo<'db>{// A method to convert from the struct into the variants fnvariants(self,db:&dyn salsa::Database) -> FooVariants<'db>{ifletSome(v) = self.id.downcast::<Foo<'db>>(db){return v.into();}// ...ifletSome(v) = self.id.downcast::<Bar<'db>>(db){return v.into();}unreachable!()}// Convenient downcast methods for each of the optionsfna(self) -> Option<Foo<'db>>{self.id.downcast()}fnz(self) -> Option<Bar<'db>>{self.id.downcast()}}
The text was updated successfully, but these errors were encountered:
We will need to add an accessor get_ingredient(&self, id: Id) -> IngredientIndex to Table, kind of like get, which gets the ingredient index for a given Id. It should call split_id and just take the first page (the page). It can then check self.pages.get(id) -- note that it should not call self.page::<T> because we don't know the T -- and invoke the method you added in the previous step.
Then we add inherent methods to Id, is and downcast. This is the trickiest part because I think we want to tweak the traits. I would start by modifying SalsaStructInDb -- probably rename it to SalsaStruct<'db> and add some methods like fn ingredient_index(db: &'db dyn salsa::Database) -> IngredientIndex and fn new(db: &'db dyn salsa::Database, id: Id) -> Self. We'll need to tweak the implementations created in the various macros in salsa-macro-rules and get everything to build. The ingredient_index method should invoke the existing ingredient method, which already has caching. The new method should probably assert! (maybe debug_assert!) that the ingredient for id matches Self::ingredient_index.
Once the previous step is done, is can be implemented by comparing S::ingredient_index() with the result of db.table.ingredient_index(id). Downcasting can be implemented by checking is and then invoking new.
Alternatively, you could name the methods in SalsaStructInDb something like is and downcast and just have salsa::Id forward to them.
Proc macro
Add a proc macro to salsa-macros crate, sort of like this one
That proc macro should parse the enum, check various criteria, and generate a salsa::plumbing::setup_supertype! macro invocation.
Add setup_supertype! to the salsa-macro-rules crate, sort of like this. That will generate the actual code.
I've noticed that I often have an enum whose variants are all different salsa structs:
I was thinking about how this enum will use 2 words and not 1 and I realized that, given that each variant is just storing an
Id
, and that we can go from anId
to anIngredientIndex
(it's stored on the page), we could have a proc-macro that takes such an enum and returns a special struct that just stores a singleId
. It could then be converted into an enum readily enough. You also downcast it.I'm imagining the following:
First, add two methods to
salsa::Id
,fn is<S>(self, db: &dyn Database) -> bool
andfn downcast<S>(self, db: &dyn Database) -> Option<S>
, whereS: SalsaStructInDb<'_>
. These methods can lookup the id indb.table
, identify the ingredient index on the from thePage
, compare that to the ingredient index forS
, and then do the appropriate thing. (We might also want to tweak theFromId
or other traits in a similar-ish way.)Next, create a proc macro named
supertype
(bikeshed) which expects an enum with one lifetime argument and where each variant has a single argument:we generate the following:
The text was updated successfully, but these errors were encountered: