diff --git a/components/salsa-2022-macros/Cargo.toml b/components/salsa-2022-macros/Cargo.toml index 2cc45983..a917bf6d 100644 --- a/components/salsa-2022-macros/Cargo.toml +++ b/components/salsa-2022-macros/Cargo.toml @@ -10,5 +10,5 @@ proc-macro = true heck = "0.4" proc-macro2 = "1.0" quote = "1.0" -syn = { version = "1.0", features = ["full", "extra-traits", "visit-mut"] } eyre = "0.6.5" +syn = { version = "2.0.64", features = ["visit-mut"] } diff --git a/components/salsa-2022-macros/src/configuration.rs b/components/salsa-2022-macros/src/configuration.rs index df16fe4f..65ad7f37 100644 --- a/components/salsa-2022-macros/src/configuration.rs +++ b/components/salsa-2022-macros/src/configuration.rs @@ -5,9 +5,9 @@ pub(crate) struct Configuration { pub(crate) input_ty: syn::Type, pub(crate) value_ty: syn::Type, pub(crate) cycle_strategy: CycleRecoveryStrategy, - pub(crate) backdate_fn: syn::ImplItemMethod, - pub(crate) execute_fn: syn::ImplItemMethod, - pub(crate) recover_fn: syn::ImplItemMethod, + pub(crate) backdate_fn: syn::ImplItemFn, + pub(crate) execute_fn: syn::ImplItemFn, + pub(crate) recover_fn: syn::ImplItemFn, } impl Configuration { @@ -58,7 +58,7 @@ impl quote::ToTokens for CycleRecoveryStrategy { /// Returns an appropriate definition for `should_backdate_value` depending on /// whether this value is memoized or not. -pub(crate) fn should_backdate_value_fn(should_backdate: bool) -> syn::ImplItemMethod { +pub(crate) fn should_backdate_value_fn(should_backdate: bool) -> syn::ImplItemFn { if should_backdate { parse_quote! { fn should_backdate_value(v1: &Self::Value<'_>, v2: &Self::Value<'_>) -> bool { @@ -76,7 +76,7 @@ pub(crate) fn should_backdate_value_fn(should_backdate: bool) -> syn::ImplItemMe /// Returns an appropriate definition for `recover_from_cycle` for cases where /// the cycle recovery is panic. -pub(crate) fn panic_cycle_recovery_fn() -> syn::ImplItemMethod { +pub(crate) fn panic_cycle_recovery_fn() -> syn::ImplItemFn { parse_quote! { fn recover_from_cycle<'db>( _db: &'db salsa::function::DynDb<'db, Self>, diff --git a/components/salsa-2022-macros/src/input.rs b/components/salsa-2022-macros/src/input.rs index 154eda99..9c043daf 100644 --- a/components/salsa-2022-macros/src/input.rs +++ b/components/salsa-2022-macros/src/input.rs @@ -83,7 +83,7 @@ impl InputStruct { let field_tys: Vec<_> = self.all_field_tys(); let field_clones: Vec<_> = self.all_fields().map(SalsaField::is_clone_field).collect(); let get_field_names: Vec<_> = self.all_get_field_names(); - let field_getters: Vec = field_indices.iter().zip(&get_field_names).zip(&field_vises).zip(&field_tys).zip(&field_clones).map(|((((field_index, get_field_name), field_vis), field_ty), is_clone_field)| + let field_getters: Vec = field_indices.iter().zip(&get_field_names).zip(&field_vises).zip(&field_tys).zip(&field_clones).map(|((((field_index, get_field_name), field_vis), field_ty), is_clone_field)| if !*is_clone_field { parse_quote_spanned! { get_field_name.span() => #field_vis fn #get_field_name<'db>(self, __db: &'db #db_dyn_ty) -> &'db #field_ty @@ -108,7 +108,7 @@ impl InputStruct { // setters let set_field_names = self.all_set_field_names(); - let field_setters: Vec = field_indices.iter() + let field_setters: Vec = field_indices.iter() .zip(&set_field_names) .zip(&field_vises) .zip(&field_tys) @@ -128,7 +128,7 @@ impl InputStruct { let constructor_name = self.constructor_name(); let singleton = self.0.is_isingleton(); - let constructor: syn::ImplItemMethod = if singleton { + let constructor: syn::ImplItemFn = if singleton { parse_quote_spanned! { constructor_name.span() => /// Creates a new singleton input /// @@ -168,7 +168,7 @@ impl InputStruct { ); if singleton { - let get: syn::ImplItemMethod = parse_quote! { + let get: syn::ImplItemFn = parse_quote! { #[track_caller] pub fn get(__db: &#db_dyn_ty) -> Self { let (__jar, __runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar(__db); @@ -177,7 +177,7 @@ impl InputStruct { } }; - let try_get: syn::ImplItemMethod = parse_quote! { + let try_get: syn::ImplItemFn = parse_quote! { #[track_caller] pub fn try_get(__db: &#db_dyn_ty) -> Option { let (__jar, __runtime) = <_ as salsa::storage::HasJar<#jar_ty>>::jar(__db); diff --git a/components/salsa-2022-macros/src/interned.rs b/components/salsa-2022-macros/src/interned.rs index 45ce0b85..027e1d92 100644 --- a/components/salsa-2022-macros/src/interned.rs +++ b/components/salsa-2022-macros/src/interned.rs @@ -187,7 +187,7 @@ impl InternedStruct { let db_dyn_ty = self.db_dyn_ty(); let jar_ty = self.jar_ty(); - let field_getters: Vec = self + let field_getters: Vec = self .all_fields() .map(|field| { let field_name = field.name(); @@ -214,7 +214,7 @@ impl InternedStruct { let field_tys = self.all_field_tys(); let data_ident = self.data_ident(); let constructor_name = self.constructor_name(); - let new_method: syn::ImplItemMethod = parse_quote_spanned! { constructor_name.span() => + let new_method: syn::ImplItemFn = parse_quote_spanned! { constructor_name.span() => #vis fn #constructor_name( db: &#db_dyn_ty, #(#field_names: #field_tys,)* @@ -261,7 +261,7 @@ impl InternedStruct { let db_dyn_ty = self.db_dyn_ty(); let jar_ty = self.jar_ty(); - let field_getters: Vec = self + let field_getters: Vec = self .all_fields() .map(|field| { let field_name = field.name(); @@ -292,7 +292,7 @@ impl InternedStruct { let field_tys = self.all_field_tys(); let data_ident = self.data_ident(); let constructor_name = self.constructor_name(); - let new_method: syn::ImplItemMethod = parse_quote_spanned! { constructor_name.span() => + let new_method: syn::ImplItemFn = parse_quote_spanned! { constructor_name.span() => #vis fn #constructor_name( db: &#db_dyn_ty, #(#field_names: #field_tys,)* diff --git a/components/salsa-2022-macros/src/jar.rs b/components/salsa-2022-macros/src/jar.rs index 14fd134d..cfba9229 100644 --- a/components/salsa-2022-macros/src/jar.rs +++ b/components/salsa-2022-macros/src/jar.rs @@ -1,4 +1,5 @@ -use proc_macro2::Literal; +use proc_macro2::extra::DelimSpan; +use proc_macro2::{Delimiter, Group, Literal, TokenStream}; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::visit_mut::VisitMut; @@ -166,7 +167,7 @@ fn generate_fields(input: &ItemStruct) -> FieldsUnnamed { }, syn::Fields::Unnamed(f) => f.paren_token, syn::Fields::Unit => syn::token::Paren { - span: input.ident.span(), + span: to_delim_span(input), }, }; @@ -175,3 +176,9 @@ fn generate_fields(input: &ItemStruct) -> FieldsUnnamed { unnamed: output_fields, } } + +fn to_delim_span(s: &impl Spanned) -> DelimSpan { + let mut group = Group::new(Delimiter::None, TokenStream::new()); + group.set_span(s.span()); + group.delim_span() +} diff --git a/components/salsa-2022-macros/src/salsa_struct.rs b/components/salsa-2022-macros/src/salsa_struct.rs index 5380b9c6..cb7a0c0a 100644 --- a/components/salsa-2022-macros/src/salsa_struct.rs +++ b/components/salsa-2022-macros/src/salsa_struct.rs @@ -53,7 +53,7 @@ const BANNED_FIELD_NAMES: &[&str] = &["from", "new"]; /// Classifies the kind of field stored in this salsa /// struct. -#[derive(Debug, PartialEq, Eq)] +#[derive(PartialEq, Eq)] pub enum TheStructKind { /// Stores an "id" Id, @@ -62,6 +62,15 @@ pub enum TheStructKind { Pointer(syn::Lifetime), } +impl std::fmt::Debug for TheStructKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TheStructKind::Id => write!(f, "Id"), + TheStructKind::Pointer(lt) => write!(f, "Pointer({lt})"), + } + } +} + impl SalsaStruct { pub(crate) fn new( args: proc_macro::TokenStream, @@ -164,7 +173,7 @@ impl SalsaStruct { .attrs .iter() .map(|attr| { - if attr.path.is_ident("customize") { + if attr.path().is_ident("customize") { // FIXME: this should be a comma separated list but I couldn't // be bothered to remember how syn does this. let args: syn::Ident = attr.parse_args()?; @@ -294,8 +303,8 @@ impl SalsaStruct { .struct_item .attrs .iter() - .filter(|attr| !attr.path.is_ident("derive")) - .filter(|attr| !attr.path.is_ident("customize")) + .filter(|attr| !attr.path().is_ident("derive")) + .filter(|attr| !attr.path().is_ident("customize")) .collect(); parse_quote_spanned! { ident.span() => @@ -330,8 +339,8 @@ impl SalsaStruct { .struct_item .attrs .iter() - .filter(|attr| !attr.path.is_ident("derive")) - .filter(|attr| !attr.path.is_ident("customize")) + .filter(|attr| !attr.path().is_ident("derive")) + .filter(|attr| !attr.path().is_ident("customize")) .collect(); let module = &self.module; @@ -600,7 +609,7 @@ impl SalsaField { // Scan the attributes and look for the salsa attributes: for attr in &field.attrs { for (fa, func) in FIELD_OPTION_ATTRIBUTES { - if attr.path.is_ident(fa) { + if attr.path().is_ident(fa) { func(attr, &mut result); } } diff --git a/components/salsa-2022-macros/src/tracked_fn.rs b/components/salsa-2022-macros/src/tracked_fn.rs index 0e67af52..8236cd59 100644 --- a/components/salsa-2022-macros/src/tracked_fn.rs +++ b/components/salsa-2022-macros/src/tracked_fn.rs @@ -1,4 +1,4 @@ -use proc_macro2::{Literal, TokenStream}; +use proc_macro2::{Literal, Span, TokenStream}; use syn::spanned::Spanned; use syn::visit_mut::VisitMut; use syn::{ReturnType, Token}; @@ -119,23 +119,23 @@ pub(crate) fn tracked_impl( .iter_mut() .filter_map(|item| { let item_method = match item { - syn::ImplItem::Method(item_method) => item_method, + syn::ImplItem::Fn(item_method) => item_method, _ => return None, }; let salsa_tracked_attr = item_method.attrs.iter().position(|attr| { - let path = &attr.path.segments; + let path = &attr.path().segments; path.len() == 2 - && path[0].arguments == syn::PathArguments::None + && path[0].arguments.is_none() && path[0].ident == "salsa" - && path[1].arguments == syn::PathArguments::None + && path[1].arguments.is_none() && path[1].ident == "tracked" })?; let salsa_tracked_attr = item_method.attrs.remove(salsa_tracked_attr); - let inner_args = if !salsa_tracked_attr.tokens.is_empty() { - salsa_tracked_attr.parse_args() - } else { - Ok(FnArgs::default()) + let inner_args = match salsa_tracked_attr.meta { + syn::Meta::Path(_) => Ok(FnArgs::default()), + syn::Meta::List(_) | syn::Meta::NameValue(_) => salsa_tracked_attr.parse_args(), }; + let inner_args = match inner_args { Ok(inner_args) => inner_args, Err(err) => return Some(Err(err)), @@ -194,7 +194,7 @@ impl crate::options::AllowedOptions for TrackedImpl { fn tracked_method( outer_args: &ImplArgs, mut args: FnArgs, - item_method: &mut syn::ImplItemMethod, + item_method: &mut syn::ImplItemFn, self_type: &syn::TypePath, name: &str, ) -> syn::Result { @@ -670,7 +670,7 @@ fn setter_fn( args: &FnArgs, item_fn: &syn::ItemFn, config_ty: &syn::Type, -) -> syn::Result { +) -> syn::Result { // The setter has *always* the same signature as the original: // but it takes a value arg and has no return type. let jar_ty = args.jar_ty(); @@ -691,7 +691,7 @@ fn setter_fn( let value_arg = syn::Ident::new("__value", item_fn.sig.output.span()); setter_sig.inputs.push(parse_quote!(#value_arg: #value_ty)); setter_sig.output = ReturnType::Default; - Ok(syn::ImplItemMethod { + Ok(syn::ImplItemFn { attrs: vec![], vis: item_fn.vis.clone(), defaultness: None, @@ -722,7 +722,7 @@ fn setter_fn( fn set_lru_capacity_fn( args: &FnArgs, config_ty: &syn::Type, -) -> syn::Result> { +) -> syn::Result> { if args.lru.is_none() { return Ok(None); } @@ -744,7 +744,7 @@ fn specify_fn( args: &FnArgs, item_fn: &syn::ItemFn, config_ty: &syn::Type, -) -> syn::Result> { +) -> syn::Result> { if args.specify.is_none() { return Ok(None); } @@ -759,7 +759,7 @@ fn specify_fn( let value_arg = syn::Ident::new("__value", item_fn.sig.output.span()); setter_sig.inputs.push(parse_quote!(#value_arg: #value_ty)); setter_sig.output = ReturnType::Default; - Ok(Some(syn::ImplItemMethod { + Ok(Some(syn::ImplItemFn { attrs: vec![], vis: item_fn.vis.clone(), defaultness: None, @@ -784,7 +784,10 @@ fn make_fn_return_ref(fn_sig: &mut syn::Signature) -> syn::Result<()> { let (db_lifetime, _) = db_lifetime_and_ty(fn_sig)?; let (right_arrow, elem) = match fn_sig.output.clone() { - ReturnType::Default => (syn::Token![->](fn_sig.paren_token.span), parse_quote!(())), + ReturnType::Default => ( + syn::Token![->]([Span::call_site(), Span::call_site()]), + parse_quote!(()), + ), ReturnType::Type(rarrow, ty) => (rarrow, ty), }; @@ -821,7 +824,7 @@ fn db_lifetime_and_ty(func: &mut syn::Signature) -> syn::Result<(syn::Lifetime, let ident = syn::Ident::new("__db", and_token_span); func.generics.params.insert( 0, - syn::LifetimeDef { + syn::LifetimeParam { attrs: vec![], lifetime: syn::Lifetime { apostrophe: and_token_span, diff --git a/components/salsa-2022-macros/src/tracked_struct.rs b/components/salsa-2022-macros/src/tracked_struct.rs index 1d26ee8e..e86ca6c4 100644 --- a/components/salsa-2022-macros/src/tracked_struct.rs +++ b/components/salsa-2022-macros/src/tracked_struct.rs @@ -173,7 +173,7 @@ impl TrackedStruct { let field_tys: Vec<_> = self.all_fields().map(SalsaField::ty).collect(); let field_get_names: Vec<_> = self.all_fields().map(SalsaField::get_name).collect(); let field_clones: Vec<_> = self.all_fields().map(SalsaField::is_clone_field).collect(); - let field_getters: Vec = field_indices.iter().zip(&field_get_names).zip(&field_tys).zip(&field_vises).zip(&field_clones).map(|((((field_index, field_get_name), field_ty), field_vis), is_clone_field)| + let field_getters: Vec = field_indices.iter().zip(&field_get_names).zip(&field_tys).zip(&field_vises).zip(&field_clones).map(|((((field_index, field_get_name), field_ty), field_vis), is_clone_field)| match the_kind { TheStructKind::Id => { if !*is_clone_field {