mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-07-07 13:25: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)*},
|
||||
|
||||
$(self_ty: $self_ty:ty,)?
|
||||
|
||||
// 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
|
||||
// not used elsewhere in the user's code.
|
||||
|
@ -139,7 +141,7 @@ macro_rules! setup_tracked_fn {
|
|||
file: file!(),
|
||||
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),*);
|
||||
|
||||
|
@ -194,7 +196,7 @@ macro_rules! setup_tracked_fn {
|
|||
file: file!(),
|
||||
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;
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ impl AllowedOptions for Accumulator {
|
|||
const ID: bool = false;
|
||||
const REVISIONS: bool = false;
|
||||
const HEAP_SIZE: bool = false;
|
||||
const SELF_TY: bool = false;
|
||||
}
|
||||
|
||||
struct StructMacro {
|
||||
|
|
|
@ -66,6 +66,8 @@ impl crate::options::AllowedOptions for InputStruct {
|
|||
const REVISIONS: bool = false;
|
||||
|
||||
const HEAP_SIZE: bool = false;
|
||||
|
||||
const SELF_TY: bool = false;
|
||||
}
|
||||
|
||||
impl SalsaStructAllowedOptions for InputStruct {
|
||||
|
|
|
@ -66,6 +66,8 @@ impl crate::options::AllowedOptions for InternedStruct {
|
|||
const REVISIONS: bool = true;
|
||||
|
||||
const HEAP_SIZE: bool = false;
|
||||
|
||||
const SELF_TY: bool = false;
|
||||
}
|
||||
|
||||
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.
|
||||
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.
|
||||
phantom: PhantomData<A>,
|
||||
}
|
||||
|
@ -130,6 +134,7 @@ impl<A: AllowedOptions> Default for Options<A> {
|
|||
id: Default::default(),
|
||||
revisions: Default::default(),
|
||||
heap_size_fn: Default::default(),
|
||||
self_ty: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +158,7 @@ pub(crate) trait AllowedOptions {
|
|||
const ID: bool;
|
||||
const REVISIONS: bool;
|
||||
const HEAP_SIZE: bool;
|
||||
const SELF_TY: bool;
|
||||
}
|
||||
|
||||
type Equals = syn::Token![=];
|
||||
|
@ -416,6 +422,22 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
|||
"`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 {
|
||||
return Err(syn::Error::new(
|
||||
ident.span(),
|
||||
|
@ -433,3 +455,82 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
|
|||
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 HEAP_SIZE: bool = true;
|
||||
|
||||
const SELF_TY: bool = true;
|
||||
}
|
||||
|
||||
struct Macro {
|
||||
|
@ -199,6 +201,10 @@ impl Macro {
|
|||
} else {
|
||||
quote! {}
|
||||
};
|
||||
let self_ty = match &self.args.self_ty {
|
||||
Some(ty) => quote! { self_ty: #ty, },
|
||||
None => quote! {},
|
||||
};
|
||||
|
||||
Ok(crate::debug::dump_tokens(
|
||||
fn_name,
|
||||
|
@ -224,6 +230,7 @@ impl Macro {
|
|||
lru: #lru,
|
||||
return_mode: #return_mode,
|
||||
assert_return_type_is_update: { #assert_return_type_is_update },
|
||||
#self_ty
|
||||
unused_names: [
|
||||
#zalsa,
|
||||
#Configuration,
|
||||
|
|
|
@ -69,7 +69,7 @@ impl Macro {
|
|||
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))
|
||||
else {
|
||||
|
@ -83,11 +83,20 @@ impl Macro {
|
|||
let mut change = ChangeSelfPath::new(self_ty, trait_);
|
||||
change.visit_impl_item_fn_mut(fn_item);
|
||||
|
||||
let salsa_tracked_attr = fn_item.attrs.remove(tracked_attr_index);
|
||||
let args: FnArgs = match &salsa_tracked_attr.meta {
|
||||
let mut salsa_tracked_attr = fn_item.attrs.remove(tracked_attr_index);
|
||||
let mut args: FnArgs = match &salsa_tracked_attr.meta {
|
||||
syn::Meta::Path(..) => Default::default(),
|
||||
_ => 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 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 HEAP_SIZE: bool = false;
|
||||
|
||||
const SELF_TY: bool = false;
|
||||
}
|
||||
|
||||
impl SalsaStructAllowedOptions for TrackedStruct {
|
||||
|
|
|
@ -80,6 +80,6 @@ fn debug_name() {
|
|||
assert_eq!(output.field(&db), 88);
|
||||
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);
|
||||
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