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
|
// Name of the `'db` lifetime that the user gave
|
||||||
db_lt: $db_lt:lifetime,
|
db_lt: $db_lt:lifetime,
|
||||||
|
|
||||||
|
// the salsa ID
|
||||||
|
id: $Id:path,
|
||||||
|
|
||||||
// Name user gave for `new`
|
// Name user gave for `new`
|
||||||
new_fn: $new_fn:ident,
|
new_fn: $new_fn:ident,
|
||||||
|
|
||||||
|
@ -55,7 +58,7 @@ macro_rules! setup_interned_struct_sans_lifetime {
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
$vis struct $Struct(
|
$vis struct $Struct(
|
||||||
salsa::Id,
|
$Id,
|
||||||
std::marker::PhantomData < &'static salsa::plumbing::interned::Value < $Struct > >
|
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 Data<'a> = StructData<'a>;
|
||||||
type Struct<'a> = $Struct;
|
type Struct<'a> = $Struct;
|
||||||
fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> {
|
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 {
|
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 {
|
impl $zalsa::AsId for $Struct {
|
||||||
fn as_id(&self) -> salsa::Id {
|
fn as_id(&self) -> salsa::Id {
|
||||||
self.0
|
self.0.as_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $zalsa::FromId for $Struct {
|
impl $zalsa::FromId for $Struct {
|
||||||
fn from_id(id: salsa::Id) -> Self {
|
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 RECOVERY_FN: bool = false;
|
||||||
const LRU: bool = false;
|
const LRU: bool = false;
|
||||||
const CONSTRUCTOR_NAME: bool = false;
|
const CONSTRUCTOR_NAME: bool = false;
|
||||||
|
const ID: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StructMacro {
|
struct StructMacro {
|
||||||
|
|
|
@ -55,6 +55,8 @@ impl crate::options::AllowedOptions for InputStruct {
|
||||||
const LRU: bool = false;
|
const LRU: bool = false;
|
||||||
|
|
||||||
const CONSTRUCTOR_NAME: bool = true;
|
const CONSTRUCTOR_NAME: bool = true;
|
||||||
|
|
||||||
|
const ID: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for InputStruct {
|
impl SalsaStructAllowedOptions for InputStruct {
|
||||||
|
|
|
@ -56,6 +56,8 @@ impl crate::options::AllowedOptions for InternedStruct {
|
||||||
const LRU: bool = false;
|
const LRU: bool = false;
|
||||||
|
|
||||||
const CONSTRUCTOR_NAME: bool = true;
|
const CONSTRUCTOR_NAME: bool = true;
|
||||||
|
|
||||||
|
const ID: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for InternedStruct {
|
impl SalsaStructAllowedOptions for InternedStruct {
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub(crate) fn interned_sans_lifetime(
|
||||||
|
|
||||||
type InternedArgs = Options<InternedStruct>;
|
type InternedArgs = Options<InternedStruct>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct InternedStruct;
|
struct InternedStruct;
|
||||||
|
|
||||||
impl crate::options::AllowedOptions for InternedStruct {
|
impl crate::options::AllowedOptions for InternedStruct {
|
||||||
|
@ -56,6 +57,8 @@ impl crate::options::AllowedOptions for InternedStruct {
|
||||||
const LRU: bool = false;
|
const LRU: bool = false;
|
||||||
|
|
||||||
const CONSTRUCTOR_NAME: bool = true;
|
const CONSTRUCTOR_NAME: bool = true;
|
||||||
|
|
||||||
|
const ID: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for InternedStruct {
|
impl SalsaStructAllowedOptions for InternedStruct {
|
||||||
|
@ -93,6 +96,7 @@ impl Macro {
|
||||||
let field_tys = salsa_struct.field_tys();
|
let field_tys = salsa_struct.field_tys();
|
||||||
let field_indexed_tys = salsa_struct.field_indexed_tys();
|
let field_indexed_tys = salsa_struct.field_indexed_tys();
|
||||||
let generate_debug_impl = salsa_struct.generate_debug_impl();
|
let generate_debug_impl = salsa_struct.generate_debug_impl();
|
||||||
|
let id = salsa_struct.id();
|
||||||
|
|
||||||
let zalsa = self.hygiene.ident("zalsa");
|
let zalsa = self.hygiene.ident("zalsa");
|
||||||
let zalsa_struct = self.hygiene.ident("zalsa_struct");
|
let zalsa_struct = self.hygiene.ident("zalsa_struct");
|
||||||
|
@ -108,6 +112,7 @@ impl Macro {
|
||||||
vis: #vis,
|
vis: #vis,
|
||||||
Struct: #struct_ident,
|
Struct: #struct_ident,
|
||||||
db_lt: #db_lt,
|
db_lt: #db_lt,
|
||||||
|
id: #id,
|
||||||
new_fn: #new_fn,
|
new_fn: #new_fn,
|
||||||
field_options: [#(#field_options),*],
|
field_options: [#(#field_options),*],
|
||||||
field_ids: [#(#field_ids),*],
|
field_ids: [#(#field_ids),*],
|
||||||
|
|
|
@ -7,6 +7,7 @@ use syn::{ext::IdentExt, spanned::Spanned};
|
||||||
/// are required and trailing commas are permitted. The options accepted
|
/// are required and trailing commas are permitted. The options accepted
|
||||||
/// for any particular location are configured via the `AllowedOptions`
|
/// for any particular location are configured via the `AllowedOptions`
|
||||||
/// trait.
|
/// trait.
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) struct Options<A: AllowedOptions> {
|
pub(crate) struct Options<A: AllowedOptions> {
|
||||||
/// The `return_ref` option is used to signal that field/return type is "by ref"
|
/// 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>`.
|
/// If this is `Some`, the value is the `<ident>`.
|
||||||
pub constructor_name: Option<syn::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.
|
/// Remember the `A` parameter, which plays no role after parsing.
|
||||||
phantom: PhantomData<A>,
|
phantom: PhantomData<A>,
|
||||||
}
|
}
|
||||||
|
@ -85,6 +92,7 @@ impl<A: AllowedOptions> Default for Options<A> {
|
||||||
phantom: Default::default(),
|
phantom: Default::default(),
|
||||||
lru: Default::default(),
|
lru: Default::default(),
|
||||||
singleton: Default::default(),
|
singleton: Default::default(),
|
||||||
|
id: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +110,7 @@ pub(crate) trait AllowedOptions {
|
||||||
const RECOVERY_FN: bool;
|
const RECOVERY_FN: bool;
|
||||||
const LRU: bool;
|
const LRU: bool;
|
||||||
const CONSTRUCTOR_NAME: bool;
|
const CONSTRUCTOR_NAME: bool;
|
||||||
|
const ID: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Equals = syn::Token![=];
|
type Equals = syn::Token![=];
|
||||||
|
@ -252,7 +261,7 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
||||||
}
|
}
|
||||||
} else if ident == "constructor" {
|
} else if ident == "constructor" {
|
||||||
if A::CONSTRUCTOR_NAME {
|
if A::CONSTRUCTOR_NAME {
|
||||||
let _eq = Equals::parse(input)?;
|
let _eq: syn::token::Eq = Equals::parse(input)?;
|
||||||
let ident = syn::Ident::parse(input)?;
|
let ident = syn::Ident::parse(input)?;
|
||||||
if let Some(old) = std::mem::replace(&mut options.constructor_name, Some(ident))
|
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",
|
"`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 {
|
} else {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
ident.span(),
|
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.
|
/// Disallow `#[id]` attributes on the fields of this struct.
|
||||||
///
|
///
|
||||||
/// If an `#[id]` field is found, return an error.
|
/// If an `#[id]` field is found, return an error.
|
||||||
|
|
|
@ -44,6 +44,8 @@ impl crate::options::AllowedOptions for TrackedFn {
|
||||||
const LRU: bool = true;
|
const LRU: bool = true;
|
||||||
|
|
||||||
const CONSTRUCTOR_NAME: bool = false;
|
const CONSTRUCTOR_NAME: bool = false;
|
||||||
|
|
||||||
|
const ID: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Macro {
|
struct Macro {
|
||||||
|
|
|
@ -50,6 +50,8 @@ impl crate::options::AllowedOptions for TrackedStruct {
|
||||||
const LRU: bool = false;
|
const LRU: bool = false;
|
||||||
|
|
||||||
const CONSTRUCTOR_NAME: bool = true;
|
const CONSTRUCTOR_NAME: bool = true;
|
||||||
|
|
||||||
|
const ID: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for TrackedStruct {
|
impl SalsaStructAllowedOptions for TrackedStruct {
|
||||||
|
|
|
@ -2,23 +2,38 @@ use expect_test::expect;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use test_log::test;
|
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 {
|
struct InternedString {
|
||||||
data: String,
|
data: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::interned_sans_lifetime]
|
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||||
struct InternedPair {
|
struct InternedPair {
|
||||||
data: (InternedString, InternedString),
|
data: (InternedString, InternedString),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::interned_sans_lifetime]
|
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||||
struct InternedTwoFields {
|
struct InternedTwoFields {
|
||||||
data1: String,
|
data1: String,
|
||||||
data2: String,
|
data2: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::interned_sans_lifetime]
|
#[salsa::interned_sans_lifetime(id = CustomSalsaIdWrapper)]
|
||||||
struct InternedVec {
|
struct InternedVec {
|
||||||
data1: Vec<String>,
|
data1: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue