mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-22 12:56:33 +00:00
feature: add id paramater to interned structs
This commit is contained in:
parent
0f379579fc
commit
d4740ed72c
10 changed files with 71 additions and 10 deletions
|
@ -14,6 +14,9 @@ macro_rules! setup_interned_struct_sans_lifetime {
|
|||
// Name of the `'db` lifetime that the user gave
|
||||
db_lt: $db_lt:lifetime,
|
||||
|
||||
// the salsa ID
|
||||
id: $Id:path,
|
||||
|
||||
// Name user gave for `new`
|
||||
new_fn: $new_fn:ident,
|
||||
|
||||
|
@ -55,7 +58,7 @@ macro_rules! setup_interned_struct_sans_lifetime {
|
|||
$(#[$attr])*
|
||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
$vis struct $Struct(
|
||||
salsa::Id,
|
||||
$Id,
|
||||
std::marker::PhantomData < &'static salsa::plumbing::interned::Value < $Struct > >
|
||||
);
|
||||
|
||||
|
@ -96,10 +99,12 @@ macro_rules! setup_interned_struct_sans_lifetime {
|
|||
type Data<'a> = StructData<'a>;
|
||||
type Struct<'a> = $Struct;
|
||||
fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> {
|
||||
$Struct(id, std::marker::PhantomData)
|
||||
use $zalsa::FromId;
|
||||
$Struct(<$Id>::from_id(id), std::marker::PhantomData)
|
||||
}
|
||||
fn deref_struct(s: Self::Struct<'_>) -> salsa::Id {
|
||||
s.0
|
||||
use $zalsa::AsId;
|
||||
s.0.as_id()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,13 +123,13 @@ macro_rules! setup_interned_struct_sans_lifetime {
|
|||
|
||||
impl $zalsa::AsId for $Struct {
|
||||
fn as_id(&self) -> salsa::Id {
|
||||
self.0
|
||||
self.0.as_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl $zalsa::FromId for $Struct {
|
||||
fn from_id(id: salsa::Id) -> Self {
|
||||
Self(id, std::marker::PhantomData)
|
||||
Self(<$Id>::from_id(id), std::marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ impl AllowedOptions for Accumulator {
|
|||
const RECOVERY_FN: bool = false;
|
||||
const LRU: bool = false;
|
||||
const CONSTRUCTOR_NAME: bool = false;
|
||||
const ID: bool = true;
|
||||
}
|
||||
|
||||
struct StructMacro {
|
||||
|
|
|
@ -55,6 +55,8 @@ impl crate::options::AllowedOptions for InputStruct {
|
|||
const LRU: bool = false;
|
||||
|
||||
const CONSTRUCTOR_NAME: bool = true;
|
||||
|
||||
const ID: bool = true;
|
||||
}
|
||||
|
||||
impl SalsaStructAllowedOptions for InputStruct {
|
||||
|
|
|
@ -56,6 +56,8 @@ impl crate::options::AllowedOptions for InternedStruct {
|
|||
const LRU: bool = false;
|
||||
|
||||
const CONSTRUCTOR_NAME: bool = true;
|
||||
|
||||
const ID: bool = true;
|
||||
}
|
||||
|
||||
impl SalsaStructAllowedOptions for InternedStruct {
|
||||
|
|
|
@ -32,6 +32,7 @@ pub(crate) fn interned_sans_lifetime(
|
|||
|
||||
type InternedArgs = Options<InternedStruct>;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InternedStruct;
|
||||
|
||||
impl crate::options::AllowedOptions for InternedStruct {
|
||||
|
@ -56,6 +57,8 @@ impl crate::options::AllowedOptions for InternedStruct {
|
|||
const LRU: bool = false;
|
||||
|
||||
const CONSTRUCTOR_NAME: bool = true;
|
||||
|
||||
const ID: bool = true;
|
||||
}
|
||||
|
||||
impl SalsaStructAllowedOptions for InternedStruct {
|
||||
|
@ -93,6 +96,7 @@ impl Macro {
|
|||
let field_tys = salsa_struct.field_tys();
|
||||
let field_indexed_tys = salsa_struct.field_indexed_tys();
|
||||
let generate_debug_impl = salsa_struct.generate_debug_impl();
|
||||
let id = salsa_struct.id();
|
||||
|
||||
let zalsa = self.hygiene.ident("zalsa");
|
||||
let zalsa_struct = self.hygiene.ident("zalsa_struct");
|
||||
|
@ -108,6 +112,7 @@ impl Macro {
|
|||
vis: #vis,
|
||||
Struct: #struct_ident,
|
||||
db_lt: #db_lt,
|
||||
id: #id,
|
||||
new_fn: #new_fn,
|
||||
field_options: [#(#field_options),*],
|
||||
field_ids: [#(#field_ids),*],
|
||||
|
|
|
@ -7,6 +7,7 @@ use syn::{ext::IdentExt, spanned::Spanned};
|
|||
/// are required and trailing commas are permitted. The options accepted
|
||||
/// for any particular location are configured via the `AllowedOptions`
|
||||
/// trait.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Options<A: AllowedOptions> {
|
||||
/// The `return_ref` option is used to signal that field/return type is "by ref"
|
||||
///
|
||||
|
@ -66,6 +67,12 @@ pub(crate) struct Options<A: AllowedOptions> {
|
|||
/// If this is `Some`, the value is the `<ident>`.
|
||||
pub constructor_name: Option<syn::Ident>,
|
||||
|
||||
/// The `id = <path>` option is used to set a custom ID for interrned structs.
|
||||
///
|
||||
/// The custom ID needs to handle
|
||||
/// If this is `Some`, the value is the `<ident>`.
|
||||
pub id: Option<syn::Path>,
|
||||
|
||||
/// Remember the `A` parameter, which plays no role after parsing.
|
||||
phantom: PhantomData<A>,
|
||||
}
|
||||
|
@ -85,6 +92,7 @@ impl<A: AllowedOptions> Default for Options<A> {
|
|||
phantom: Default::default(),
|
||||
lru: Default::default(),
|
||||
singleton: Default::default(),
|
||||
id: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +110,7 @@ pub(crate) trait AllowedOptions {
|
|||
const RECOVERY_FN: bool;
|
||||
const LRU: bool;
|
||||
const CONSTRUCTOR_NAME: bool;
|
||||
const ID: bool;
|
||||
}
|
||||
|
||||
type Equals = syn::Token![=];
|
||||
|
@ -252,7 +261,7 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
|||
}
|
||||
} else if ident == "constructor" {
|
||||
if A::CONSTRUCTOR_NAME {
|
||||
let _eq = Equals::parse(input)?;
|
||||
let _eq: syn::token::Eq = Equals::parse(input)?;
|
||||
let ident = syn::Ident::parse(input)?;
|
||||
if let Some(old) = std::mem::replace(&mut options.constructor_name, Some(ident))
|
||||
{
|
||||
|
@ -267,6 +276,17 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
|||
"`constructor` option not allowed here",
|
||||
));
|
||||
}
|
||||
} else if ident == "id" {
|
||||
if A::ID {
|
||||
let _eq = Equals::parse(input)?;
|
||||
let path = syn::Path::parse(input)?;
|
||||
options.id = Some(path);
|
||||
} else {
|
||||
return Err(syn::Error::new(
|
||||
ident.span(),
|
||||
"`id` option not allowed here",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Err(syn::Error::new(
|
||||
ident.span(),
|
||||
|
|
|
@ -118,6 +118,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> syn::Path {
|
||||
match &self.args.id {
|
||||
Some(id) => id.clone(),
|
||||
None => parse_quote!(salsa::Id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Disallow `#[id]` attributes on the fields of this struct.
|
||||
///
|
||||
/// If an `#[id]` field is found, return an error.
|
||||
|
|
|
@ -44,6 +44,8 @@ impl crate::options::AllowedOptions for TrackedFn {
|
|||
const LRU: bool = true;
|
||||
|
||||
const CONSTRUCTOR_NAME: bool = false;
|
||||
|
||||
const ID: bool = true;
|
||||
}
|
||||
|
||||
struct Macro {
|
||||
|
|
|
@ -50,6 +50,8 @@ impl crate::options::AllowedOptions for TrackedStruct {
|
|||
const LRU: bool = false;
|
||||
|
||||
const CONSTRUCTOR_NAME: bool = true;
|
||||
|
||||
const ID: bool = true;
|
||||
}
|
||||
|
||||
impl SalsaStructAllowedOptions for TrackedStruct {
|
||||
|
|
|
@ -2,23 +2,38 @@ use expect_test::expect;
|
|||
use std::path::{Path, PathBuf};
|
||||
use test_log::test;
|
||||
|
||||
#[salsa::interned_sans_lifetime]
|
||||
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct CustomSalsaIdWrapper(salsa::Id);
|
||||
|
||||
impl salsa::plumbing::AsId for CustomSalsaIdWrapper {
|
||||
fn as_id(&self) -> salsa::Id {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::plumbing::FromId for CustomSalsaIdWrapper {
|
||||
fn from_id(id: salsa::Id) -> Self {
|
||||
CustomSalsaIdWrapper(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||
struct InternedString {
|
||||
data: String,
|
||||
}
|
||||
|
||||
#[salsa::interned_sans_lifetime]
|
||||
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||
struct InternedPair {
|
||||
data: (InternedString, InternedString),
|
||||
}
|
||||
|
||||
#[salsa::interned_sans_lifetime]
|
||||
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||
struct InternedTwoFields {
|
||||
data1: String,
|
||||
data2: String,
|
||||
}
|
||||
|
||||
#[salsa::interned_sans_lifetime]
|
||||
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||
struct InternedVec {
|
||||
data1: Vec<String>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue