Skip to content

Commit

Permalink
feature: add id paramater to interned structs
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbarsky committed Dec 17, 2024
1 parent 60ca556 commit 3b42b9c
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down Expand Up @@ -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 > >
);

Expand Down Expand Up @@ -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()
}
}

Expand All @@ -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)
}
}

Expand Down
1 change: 1 addition & 0 deletions components/salsa-macros/src/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/interned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions components/salsa-macros/src/interned_sans_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) fn interned_sans_lifetime(

type InternedArgs = Options<InternedStruct>;

#[derive(Debug)]
struct InternedStruct;

impl crate::options::AllowedOptions for InternedStruct {
Expand All @@ -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 {
Expand Down Expand Up @@ -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");
Expand All @@ -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),*],
Expand Down
22 changes: 21 additions & 1 deletion components/salsa-macros/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
///
Expand Down Expand Up @@ -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>,
}
Expand All @@ -85,6 +92,7 @@ impl<A: AllowedOptions> Default for Options<A> {
phantom: Default::default(),
lru: Default::default(),
singleton: Default::default(),
id: Default::default(),
}
}
}
Expand All @@ -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![=];
Expand Down Expand Up @@ -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))
{
Expand All @@ -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(),
Expand Down
7 changes: 7 additions & 0 deletions components/salsa-macros/src/salsa_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/tracked_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/tracked_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
23 changes: 19 additions & 4 deletions tests/interned-sans-lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
}
Expand Down

0 comments on commit 3b42b9c

Please sign in to comment.