mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 05:07:27 +00:00
introduce IdLookup trait
We are going to need it for tracked functions.
This commit is contained in:
parent
8d0f8fccbf
commit
cf2fa671f5
4 changed files with 89 additions and 1 deletions
|
@ -64,6 +64,7 @@ impl TrackedStruct {
|
||||||
let tracked_struct_in_db_impl = self.tracked_struct_in_db_impl();
|
let tracked_struct_in_db_impl = self.tracked_struct_in_db_impl();
|
||||||
let update_impl = self.update_impl();
|
let update_impl = self.update_impl();
|
||||||
let as_id_impl = self.as_id_impl();
|
let as_id_impl = self.as_id_impl();
|
||||||
|
let id_lookup_impl = self.id_lookup_impl();
|
||||||
let as_debug_with_db_impl = self.as_debug_with_db_impl();
|
let as_debug_with_db_impl = self.as_debug_with_db_impl();
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#config_struct
|
#config_struct
|
||||||
|
@ -75,6 +76,7 @@ impl TrackedStruct {
|
||||||
#tracked_struct_in_db_impl
|
#tracked_struct_in_db_impl
|
||||||
#update_impl
|
#update_impl
|
||||||
#as_id_impl
|
#as_id_impl
|
||||||
|
#id_lookup_impl
|
||||||
#as_debug_with_db_impl
|
#as_debug_with_db_impl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -327,6 +329,37 @@ impl TrackedStruct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implementation of `IdLookup`.
|
||||||
|
pub(crate) fn id_lookup_impl(&self) -> Option<syn::ItemImpl> {
|
||||||
|
match self.the_struct_kind() {
|
||||||
|
TheStructKind::Id => None,
|
||||||
|
TheStructKind::Pointer(db_lt) => {
|
||||||
|
let (ident, parameters, _, type_generics, where_clause) =
|
||||||
|
self.the_ident_and_generics();
|
||||||
|
let db = syn::Ident::new("DB", ident.span());
|
||||||
|
let jar_ty = self.jar_ty();
|
||||||
|
let tracked_struct_ingredient = self.tracked_struct_ingredient_index();
|
||||||
|
Some(parse_quote_spanned! { ident.span() =>
|
||||||
|
impl<#db, #parameters> salsa::id::IdLookup<& #db_lt #db> for #ident #type_generics
|
||||||
|
where
|
||||||
|
#db: ?Sized + salsa::DbWithJar<#jar_ty>,
|
||||||
|
#where_clause
|
||||||
|
{
|
||||||
|
fn into_id(self) -> salsa::Id {
|
||||||
|
unsafe { &*self.0 }.id()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_id(id: salsa::Id, db: & #db_lt DB) -> Self {
|
||||||
|
let (jar, runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar(db);
|
||||||
|
let ingredients = <#jar_ty as salsa::storage::HasIngredientsFor<#ident #type_generics>>::ingredient(jar);
|
||||||
|
Self(ingredients.#tracked_struct_ingredient.lookup_struct(runtime, id), std::marker::PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Implementation of `SalsaStructInDb`.
|
/// Implementation of `SalsaStructInDb`.
|
||||||
fn salsa_struct_in_db_impl(&self) -> syn::ItemImpl {
|
fn salsa_struct_in_db_impl(&self) -> syn::ItemImpl {
|
||||||
let (ident, parameters, _, type_generics, where_clause) = self.the_ident_and_generics();
|
let (ident, parameters, _, type_generics, where_clause) = self.the_ident_and_generics();
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl From<Id> for usize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for types that can be interconverted to a salsa Id;
|
/// Internal Salsa trait for types that can be interconverted to a salsa Id;
|
||||||
pub trait AsId: Sized + Copy + Eq + Hash + Debug {
|
pub trait AsId: Sized + Copy + Eq + Hash + Debug {
|
||||||
fn as_id(self) -> Id;
|
fn as_id(self) -> Id;
|
||||||
fn from_id(id: Id) -> Self;
|
fn from_id(id: Id) -> Self;
|
||||||
|
@ -92,3 +92,38 @@ impl AsId for () {
|
||||||
assert_eq!(0, id.as_u32());
|
assert_eq!(0, id.as_u32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal Salsa trait for types that have a salsa id but require looking
|
||||||
|
/// up in the database to find it. This is different from
|
||||||
|
/// [`AsId`][] where what we have is literally a *newtype*
|
||||||
|
/// for an `Id`.
|
||||||
|
pub trait IdLookup<DB> {
|
||||||
|
/// Convert to an `Id`
|
||||||
|
fn into_id(self) -> Id;
|
||||||
|
|
||||||
|
/// Lookup from an `Id` to get an instance of the type.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This fn may panic if the value with this id has not been
|
||||||
|
/// produced in this revision already (e.g., for a tracked
|
||||||
|
/// struct, the function will panic if the tracked struct
|
||||||
|
/// has not yet been created in this revision). Salsa's
|
||||||
|
/// dependency tracking typically ensures this does not
|
||||||
|
/// occur, but it is possible for a user to violate this
|
||||||
|
/// rule.
|
||||||
|
fn lookup_id(id: Id, db: DB) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<DB, ID> IdLookup<DB> for ID
|
||||||
|
where
|
||||||
|
ID: AsId,
|
||||||
|
{
|
||||||
|
fn into_id(self) -> Id {
|
||||||
|
self.as_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_id(id: Id, _db: DB) -> Self {
|
||||||
|
Self::from_id(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -341,6 +341,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given the id of a tracked struct created in this revision,
|
||||||
|
/// returns a pointer to the struct.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// If the struct has not been created in this revision.
|
||||||
|
pub fn lookup_struct<'db>(&'db self, runtime: &'db Runtime, id: Id) -> &'db ValueStruct<C> {
|
||||||
|
self.struct_map.get(runtime, id)
|
||||||
|
}
|
||||||
|
|
||||||
/// Deletes the given entities. This is used after a query `Q` executes and we can compare
|
/// Deletes the given entities. This is used after a query `Q` executes and we can compare
|
||||||
/// the entities `E_now` that it produced in this revision vs the entities
|
/// the entities `E_now` that it produced in this revision vs the entities
|
||||||
/// `E_prev` it produced in the last revision. Any missing entities `E_prev - E_new` can be
|
/// `E_prev` it produced in the last revision. Any missing entities `E_prev - E_new` can be
|
||||||
|
|
|
@ -148,6 +148,16 @@ where
|
||||||
Update::Outdated(UpdateRef { guard: data })
|
Update::Outdated(UpdateRef { guard: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lookup an existing tracked struct from the map.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// * If the value is not present in the map.
|
||||||
|
/// * If the value has not been updated in this revision.
|
||||||
|
pub fn get<'db>(&'db self, runtime: &'db Runtime, id: Id) -> &'db ValueStruct<C> {
|
||||||
|
Self::get_from_map(&self.map, runtime, id)
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function, provides shared functionality for [`StructMapView`][]
|
/// Helper function, provides shared functionality for [`StructMapView`][]
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
|
Loading…
Reference in a new issue