mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-07-07 21:35:17 +00:00
Emit self ty for query debug name of assoc function queries (#927)
This commit is contained in:
parent
d44f638408
commit
f384ab538e
10 changed files with 133 additions and 7 deletions
|
@ -66,6 +66,8 @@ macro_rules! setup_tracked_fn {
|
||||||
|
|
||||||
assert_return_type_is_update: {$($assert_return_type_is_update:tt)*},
|
assert_return_type_is_update: {$($assert_return_type_is_update:tt)*},
|
||||||
|
|
||||||
|
$(self_ty: $self_ty:ty,)?
|
||||||
|
|
||||||
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
|
||||||
// We have the procedural macro generate names for those items that are
|
// We have the procedural macro generate names for those items that are
|
||||||
// not used elsewhere in the user's code.
|
// not used elsewhere in the user's code.
|
||||||
|
@ -139,7 +141,7 @@ macro_rules! setup_tracked_fn {
|
||||||
file: file!(),
|
file: file!(),
|
||||||
line: line!(),
|
line: line!(),
|
||||||
};
|
};
|
||||||
const DEBUG_NAME: &'static str = concat!(stringify!($fn_name), "::interned_arguments");
|
const DEBUG_NAME: &'static str = concat!($(stringify!($self_ty), "::",)? stringify!($fn_name), "::interned_arguments");
|
||||||
|
|
||||||
type Fields<$db_lt> = ($($interned_input_ty),*);
|
type Fields<$db_lt> = ($($interned_input_ty),*);
|
||||||
|
|
||||||
|
@ -194,7 +196,7 @@ macro_rules! setup_tracked_fn {
|
||||||
file: file!(),
|
file: file!(),
|
||||||
line: line!(),
|
line: line!(),
|
||||||
};
|
};
|
||||||
const DEBUG_NAME: &'static str = stringify!($fn_name);
|
const DEBUG_NAME: &'static str = concat!($(stringify!($self_ty), "::", )? stringify!($fn_name));
|
||||||
|
|
||||||
type DbView = dyn $Db;
|
type DbView = dyn $Db;
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ impl AllowedOptions for Accumulator {
|
||||||
const ID: bool = false;
|
const ID: bool = false;
|
||||||
const REVISIONS: bool = false;
|
const REVISIONS: bool = false;
|
||||||
const HEAP_SIZE: bool = false;
|
const HEAP_SIZE: bool = false;
|
||||||
|
const SELF_TY: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StructMacro {
|
struct StructMacro {
|
||||||
|
|
|
@ -66,6 +66,8 @@ impl crate::options::AllowedOptions for InputStruct {
|
||||||
const REVISIONS: bool = false;
|
const REVISIONS: bool = false;
|
||||||
|
|
||||||
const HEAP_SIZE: bool = false;
|
const HEAP_SIZE: bool = false;
|
||||||
|
|
||||||
|
const SELF_TY: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for InputStruct {
|
impl SalsaStructAllowedOptions for InputStruct {
|
||||||
|
|
|
@ -66,6 +66,8 @@ impl crate::options::AllowedOptions for InternedStruct {
|
||||||
const REVISIONS: bool = true;
|
const REVISIONS: bool = true;
|
||||||
|
|
||||||
const HEAP_SIZE: bool = false;
|
const HEAP_SIZE: bool = false;
|
||||||
|
|
||||||
|
const SELF_TY: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for InternedStruct {
|
impl SalsaStructAllowedOptions for InternedStruct {
|
||||||
|
|
|
@ -105,6 +105,10 @@ pub(crate) struct Options<A: AllowedOptions> {
|
||||||
/// If this is `Some`, the value is the provided `heap_size` function.
|
/// If this is `Some`, the value is the provided `heap_size` function.
|
||||||
pub heap_size_fn: Option<syn::Path>,
|
pub heap_size_fn: Option<syn::Path>,
|
||||||
|
|
||||||
|
/// The `self_ty = <Ty>` option is used to set the the self type of the tracked impl for tracked
|
||||||
|
/// functions. This is merely used to refine the query name.
|
||||||
|
pub self_ty: Option<syn::Type>,
|
||||||
|
|
||||||
/// 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>,
|
||||||
}
|
}
|
||||||
|
@ -130,6 +134,7 @@ impl<A: AllowedOptions> Default for Options<A> {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
revisions: Default::default(),
|
revisions: Default::default(),
|
||||||
heap_size_fn: Default::default(),
|
heap_size_fn: Default::default(),
|
||||||
|
self_ty: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,6 +158,7 @@ pub(crate) trait AllowedOptions {
|
||||||
const ID: bool;
|
const ID: bool;
|
||||||
const REVISIONS: bool;
|
const REVISIONS: bool;
|
||||||
const HEAP_SIZE: bool;
|
const HEAP_SIZE: bool;
|
||||||
|
const SELF_TY: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Equals = syn::Token![=];
|
type Equals = syn::Token![=];
|
||||||
|
@ -416,6 +422,22 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
||||||
"`heap_size` option not allowed here",
|
"`heap_size` option not allowed here",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
} else if ident == "self_ty" {
|
||||||
|
if A::SELF_TY {
|
||||||
|
let _eq = Equals::parse(input)?;
|
||||||
|
let ty = syn::Type::parse(input)?;
|
||||||
|
if let Some(old) = options.self_ty.replace(ty) {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
old.span(),
|
||||||
|
"option `self_ty` provided twice",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
ident.span(),
|
||||||
|
"`self_ty` option not allowed here",
|
||||||
|
));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
ident.span(),
|
ident.span(),
|
||||||
|
@ -433,3 +455,82 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
||||||
Ok(options)
|
Ok(options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<A: AllowedOptions> quote::ToTokens for Options<A> {
|
||||||
|
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||||
|
let Self {
|
||||||
|
returns,
|
||||||
|
no_eq,
|
||||||
|
debug,
|
||||||
|
no_lifetime,
|
||||||
|
singleton,
|
||||||
|
specify,
|
||||||
|
non_update_return_type,
|
||||||
|
db_path,
|
||||||
|
cycle_fn,
|
||||||
|
cycle_initial,
|
||||||
|
cycle_result,
|
||||||
|
data,
|
||||||
|
lru,
|
||||||
|
constructor_name,
|
||||||
|
id,
|
||||||
|
revisions,
|
||||||
|
heap_size_fn,
|
||||||
|
self_ty,
|
||||||
|
phantom: _,
|
||||||
|
} = self;
|
||||||
|
if let Some(returns) = returns {
|
||||||
|
tokens.extend(quote::quote! { returns(#returns), });
|
||||||
|
};
|
||||||
|
if no_eq.is_some() {
|
||||||
|
tokens.extend(quote::quote! { no_eq, });
|
||||||
|
}
|
||||||
|
if debug.is_some() {
|
||||||
|
tokens.extend(quote::quote! { debug, });
|
||||||
|
}
|
||||||
|
if no_lifetime.is_some() {
|
||||||
|
tokens.extend(quote::quote! { no_lifetime, });
|
||||||
|
}
|
||||||
|
if singleton.is_some() {
|
||||||
|
tokens.extend(quote::quote! { singleton, });
|
||||||
|
}
|
||||||
|
if specify.is_some() {
|
||||||
|
tokens.extend(quote::quote! { specify, });
|
||||||
|
}
|
||||||
|
if non_update_return_type.is_some() {
|
||||||
|
tokens.extend(quote::quote! { unsafe(non_update_return_type), });
|
||||||
|
}
|
||||||
|
if let Some(db_path) = db_path {
|
||||||
|
tokens.extend(quote::quote! { db = #db_path, });
|
||||||
|
}
|
||||||
|
if let Some(cycle_fn) = cycle_fn {
|
||||||
|
tokens.extend(quote::quote! { cycle_fn = #cycle_fn, });
|
||||||
|
}
|
||||||
|
if let Some(cycle_initial) = cycle_initial {
|
||||||
|
tokens.extend(quote::quote! { cycle_initial = #cycle_initial, });
|
||||||
|
}
|
||||||
|
if let Some(cycle_result) = cycle_result {
|
||||||
|
tokens.extend(quote::quote! { cycle_result = #cycle_result, });
|
||||||
|
}
|
||||||
|
if let Some(data) = data {
|
||||||
|
tokens.extend(quote::quote! { data = #data, });
|
||||||
|
}
|
||||||
|
if let Some(lru) = lru {
|
||||||
|
tokens.extend(quote::quote! { lru = #lru, });
|
||||||
|
}
|
||||||
|
if let Some(constructor_name) = constructor_name {
|
||||||
|
tokens.extend(quote::quote! { constructor = #constructor_name, });
|
||||||
|
}
|
||||||
|
if let Some(id) = id {
|
||||||
|
tokens.extend(quote::quote! { id = #id, });
|
||||||
|
}
|
||||||
|
if let Some(revisions) = revisions {
|
||||||
|
tokens.extend(quote::quote! { revisions = #revisions, });
|
||||||
|
}
|
||||||
|
if let Some(heap_size_fn) = heap_size_fn {
|
||||||
|
tokens.extend(quote::quote! { heap_size_fn = #heap_size_fn, });
|
||||||
|
}
|
||||||
|
if let Some(self_ty) = self_ty {
|
||||||
|
tokens.extend(quote::quote! { self_ty = #self_ty, });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ impl crate::options::AllowedOptions for TrackedFn {
|
||||||
const REVISIONS: bool = false;
|
const REVISIONS: bool = false;
|
||||||
|
|
||||||
const HEAP_SIZE: bool = true;
|
const HEAP_SIZE: bool = true;
|
||||||
|
|
||||||
|
const SELF_TY: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Macro {
|
struct Macro {
|
||||||
|
@ -199,6 +201,10 @@ impl Macro {
|
||||||
} else {
|
} else {
|
||||||
quote! {}
|
quote! {}
|
||||||
};
|
};
|
||||||
|
let self_ty = match &self.args.self_ty {
|
||||||
|
Some(ty) => quote! { self_ty: #ty, },
|
||||||
|
None => quote! {},
|
||||||
|
};
|
||||||
|
|
||||||
Ok(crate::debug::dump_tokens(
|
Ok(crate::debug::dump_tokens(
|
||||||
fn_name,
|
fn_name,
|
||||||
|
@ -224,6 +230,7 @@ impl Macro {
|
||||||
lru: #lru,
|
lru: #lru,
|
||||||
return_mode: #return_mode,
|
return_mode: #return_mode,
|
||||||
assert_return_type_is_update: { #assert_return_type_is_update },
|
assert_return_type_is_update: { #assert_return_type_is_update },
|
||||||
|
#self_ty
|
||||||
unused_names: [
|
unused_names: [
|
||||||
#zalsa,
|
#zalsa,
|
||||||
#Configuration,
|
#Configuration,
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl Macro {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let self_ty = &impl_item.self_ty;
|
let self_ty = &*impl_item.self_ty;
|
||||||
|
|
||||||
let Some(tracked_attr_index) = fn_item.attrs.iter().position(|a| self.is_tracked_attr(a))
|
let Some(tracked_attr_index) = fn_item.attrs.iter().position(|a| self.is_tracked_attr(a))
|
||||||
else {
|
else {
|
||||||
|
@ -83,11 +83,20 @@ impl Macro {
|
||||||
let mut change = ChangeSelfPath::new(self_ty, trait_);
|
let mut change = ChangeSelfPath::new(self_ty, trait_);
|
||||||
change.visit_impl_item_fn_mut(fn_item);
|
change.visit_impl_item_fn_mut(fn_item);
|
||||||
|
|
||||||
let salsa_tracked_attr = fn_item.attrs.remove(tracked_attr_index);
|
let mut salsa_tracked_attr = fn_item.attrs.remove(tracked_attr_index);
|
||||||
let args: FnArgs = match &salsa_tracked_attr.meta {
|
let mut args: FnArgs = match &salsa_tracked_attr.meta {
|
||||||
syn::Meta::Path(..) => Default::default(),
|
syn::Meta::Path(..) => Default::default(),
|
||||||
_ => salsa_tracked_attr.parse_args()?,
|
_ => salsa_tracked_attr.parse_args()?,
|
||||||
};
|
};
|
||||||
|
if args.self_ty.is_none() {
|
||||||
|
// If the user did not specify a self_ty, we use the impl's self_ty
|
||||||
|
args.self_ty = Some(self_ty.clone());
|
||||||
|
}
|
||||||
|
salsa_tracked_attr.meta = syn::Meta::List(syn::MetaList {
|
||||||
|
path: salsa_tracked_attr.path().clone(),
|
||||||
|
delimiter: syn::MacroDelimiter::Paren(syn::token::Paren::default()),
|
||||||
|
tokens: quote! {#args},
|
||||||
|
});
|
||||||
|
|
||||||
let InnerTrait = self.hygiene.ident("InnerTrait");
|
let InnerTrait = self.hygiene.ident("InnerTrait");
|
||||||
let inner_fn_name = self.hygiene.ident(&fn_item.sig.ident.to_string());
|
let inner_fn_name = self.hygiene.ident(&fn_item.sig.ident.to_string());
|
||||||
|
|
|
@ -62,6 +62,8 @@ impl crate::options::AllowedOptions for TrackedStruct {
|
||||||
const REVISIONS: bool = false;
|
const REVISIONS: bool = false;
|
||||||
|
|
||||||
const HEAP_SIZE: bool = false;
|
const HEAP_SIZE: bool = false;
|
||||||
|
|
||||||
|
const SELF_TY: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SalsaStructAllowedOptions for TrackedStruct {
|
impl SalsaStructAllowedOptions for TrackedStruct {
|
||||||
|
|
|
@ -80,6 +80,6 @@ fn debug_name() {
|
||||||
assert_eq!(output.field(&db), 88);
|
assert_eq!(output.field(&db), 88);
|
||||||
db.assert_logs(expect![[r#"
|
db.assert_logs(expect![[r#"
|
||||||
[
|
[
|
||||||
"salsa_event(WillExecute { database_key: tracked_trait_fn_(Id(0)) })",
|
"salsa_event(WillExecute { database_key: MyOutput < 'db >::tracked_trait_fn_(Id(0)) })",
|
||||||
]"#]]);
|
]"#]]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,6 @@ fn debug_name() {
|
||||||
assert_eq!(object.tracked_trait_fn(&db), 88);
|
assert_eq!(object.tracked_trait_fn(&db), 88);
|
||||||
db.assert_logs(expect![[r#"
|
db.assert_logs(expect![[r#"
|
||||||
[
|
[
|
||||||
"salsa_event(WillExecute { database_key: tracked_trait_fn_(Id(0)) })",
|
"salsa_event(WillExecute { database_key: MyInput::tracked_trait_fn_(Id(0)) })",
|
||||||
]"#]]);
|
]"#]]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue