|
1 | 1 | #![recursion_limit = "1024"] |
2 | 2 |
|
3 | 3 | extern crate proc_macro; |
| 4 | +use proc_macro2::Span; |
4 | 5 | use quote::{ToTokens, quote}; |
5 | 6 |
|
6 | 7 | use proc_macro::TokenStream; |
7 | 8 |
|
| 9 | +fn extract_lifetime( |
| 10 | + gp: &syn::punctuated::Punctuated<syn::GenericParam, syn::token::Comma>, |
| 11 | +) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { |
| 12 | + let mut lifetimes = gp |
| 13 | + .iter() |
| 14 | + .filter_map(|param: &syn::GenericParam| match param { |
| 15 | + syn::GenericParam::Lifetime(lifetime) => Some(lifetime.lifetime.clone()), |
| 16 | + _ => None, |
| 17 | + }) |
| 18 | + .collect::<Vec<_>>(); |
| 19 | + if lifetimes.len() > 1 { |
| 20 | + panic!("Pread cannot be derived for multiple lifetimes") |
| 21 | + } |
| 22 | + let lifetime = lifetimes |
| 23 | + .pop() |
| 24 | + .unwrap_or(syn::Lifetime::new("'a", Span::call_site())); |
| 25 | + // alpha rename/make the thing fresh |
| 26 | + let alpha = format!("'{}_fresh", lifetime.ident.to_string()); |
| 27 | + ( |
| 28 | + lifetime.to_token_stream(), |
| 29 | + syn::Lifetime::new(&alpha.to_string(), lifetime.span()).to_token_stream(), |
| 30 | + ) |
| 31 | +} |
| 32 | + |
8 | 33 | fn impl_field( |
9 | 34 | ident: &proc_macro2::TokenStream, |
10 | 35 | ty: &syn::Type, |
@@ -122,17 +147,7 @@ fn impl_struct( |
122 | 147 | p => quote! { #p }, |
123 | 148 | }); |
124 | 149 |
|
125 | | - let mut lifetimes = gp |
126 | | - .iter() |
127 | | - .filter_map(|param: &syn::GenericParam| match param { |
128 | | - syn::GenericParam::Lifetime(lifetime) => Some(quote! { #lifetime }), |
129 | | - _ => None, |
130 | | - }) |
131 | | - .collect::<Vec<_>>(); |
132 | | - if lifetimes.len() > 1 { |
133 | | - panic!("Pread cannot be derived for multiple lifetimes") |
134 | | - } |
135 | | - let lifetime = lifetimes.pop().unwrap_or(quote! { 'a }); |
| 150 | + let (lifetime, _fresh_lifetime) = extract_lifetime(gp); |
136 | 151 | let gn = quote! { #gl #( #gn ),* #gg }; |
137 | 152 | // drop the lifetime from our generic params, since we already grabbed it |
138 | 153 | let initial_generic_params = gp |
@@ -296,14 +311,16 @@ fn impl_try_into_ctx( |
296 | 311 | p => quote! { #p }, |
297 | 312 | }); |
298 | 313 | let gn = quote! { #gl #( #gn ),* #gg }; |
| 314 | + // it's always important to keep it _fresh_ when we pwrite |
| 315 | + let (_lifetime, fresh_lifetime) = extract_lifetime(gp); |
299 | 316 | let gwref = if !gp.is_empty() { |
300 | 317 | let gi: Vec<_> = gp.iter().filter_map(|param: &syn::GenericParam| match param { |
301 | 318 | syn::GenericParam::Type(t) => { |
302 | 319 | let ident = &t.ident; |
303 | 320 | Some(quote! { |
304 | | - &'a #ident : ::scroll::ctx::TryIntoCtx<::scroll::Endian>, |
305 | | - ::scroll::Error: ::std::convert::From<<&'a #ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error>, |
306 | | - <&'a #ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error: ::std::convert::From<scroll::Error> |
| 321 | + &#fresh_lifetime #ident : ::scroll::ctx::TryIntoCtx<::scroll::Endian>, |
| 322 | + ::scroll::Error: ::std::convert::From<<&#fresh_lifetime #ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error>, |
| 323 | + <&#fresh_lifetime #ident as ::scroll::ctx::TryIntoCtx<::scroll::Endian>>::Error: ::std::convert::From<scroll::Error> |
307 | 324 | }) |
308 | 325 | }, |
309 | 326 | syn::GenericParam::Lifetime(_) => None, |
@@ -336,7 +353,7 @@ fn impl_try_into_ctx( |
336 | 353 | }; |
337 | 354 |
|
338 | 355 | quote! { |
339 | | - impl<'a, #gp > ::scroll::ctx::TryIntoCtx<::scroll::Endian> for &'a #name #gn #gwref { |
| 356 | + impl<#fresh_lifetime, #gp > ::scroll::ctx::TryIntoCtx<::scroll::Endian> for &#fresh_lifetime #name #gn #gwref { |
340 | 357 | type Error = ::scroll::Error; |
341 | 358 | #[inline] |
342 | 359 | fn try_into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) -> ::scroll::export::result::Result<usize, Self::Error> { |
|
0 commit comments