diff --git a/stabby-macros/src/traits.rs b/stabby-macros/src/traits.rs index 027fba6..788ca0b 100644 --- a/stabby-macros/src/traits.rs +++ b/stabby-macros/src/traits.rs @@ -679,10 +679,10 @@ impl DynTraitDescription<'_> { .map(|fn_ptr | { let DynTraitFn { ident, - generics: _, + generics, abi, unsafety, - receiver: syn::Receiver {mutability, reference: Some((_, lt)), self_token, ..}, + receiver: syn::Receiver {mutability, reference: Some((_, receiver_lt)), self_token, ..}, inputs, output, } = fn_ptr else {panic!("Only references and mutable references are supported")}; @@ -697,15 +697,22 @@ impl DynTraitDescription<'_> { .zip(arg_tys.iter()) .map(|(name, ty)| quote!(#name: #ty)) .collect::>(); + let mut arg_lts = generics.lifetimes().cloned().collect::>(); let output = output.as_ref().map(|ty| { let ty = self.self_dependent_types.unselfed(ty); quote!(-> #ty) }); - let lt = lt.clone().unwrap_or_else(|| Lifetime::new("'stabby_receiver_lt", self_token.span())); + let receiver_lt = if let Some(lt) = receiver_lt { + lt.clone() + } else { + let default_lt = Lifetime::new("'stabby_receiver_lt", self_token.span()); + arg_lts.push(syn::LifetimeDef::new(default_lt.clone())); + default_lt + }; let receiver = if mutability.is_some() { - quote!(#st::AnonymRefMut<#lt>) + quote!(#st::AnonymRefMut<#receiver_lt>) } else { - quote!(#st::AnonymRef<#lt>) + quote!(#st::AnonymRef<#receiver_lt>) }; let as_ref = if mutability.is_some() { quote!(as_mut()) @@ -715,13 +722,13 @@ impl DynTraitDescription<'_> { let mut ctor = quote!(#st::StableLike::new({ #unsafety #abi fn #ext_ident < 'stabby_local_lt, - #lt, #(#trait_lts,)* + #(#arg_lts,)* StabbyArbitraryType: 'stabby_local_lt, #(#dyntrait_types,)* #(#trait_types,)* #(#trait_consts,)* - >(this: #receiver, _lt_proof: ::core::marker::PhantomData<&#lt &'stabby_local_lt ()>, #(#args,)*) #output + >(this: #receiver, _lt_proof: ::core::marker::PhantomData<&#receiver_lt &'stabby_local_lt ()>, #(#args,)*) #output where StabbyArbitraryType: #trait_id <#(#unbound_trait_lts,)* #(#unbound_trait_types,)* #(#unbound_trait_consts,)* #(#trait_to_vt_bindings,)* >, #(#vt_bounds)* @@ -735,9 +742,9 @@ impl DynTraitDescription<'_> { } } #ext_ident :: < StabbyArbitraryType, #(#dyntrait_types,)* #(#unbound_trait_types,)* #(#unbound_trait_consts,)* > as for < - #lt, #(#trait_lts,)* - > #unsafety #abi fn (#receiver, ::core::marker::PhantomData<&#lt &'stabby_vt_lt ()>, #(#arg_tys,)*) #output + #(#arg_lts,)* + > #unsafety #abi fn (#receiver, ::core::marker::PhantomData<&#receiver_lt &'stabby_vt_lt ()>, #(#arg_tys,)*) #output })); if self.check_bounds { ctor = quote!(#st::StableIf::new(#ctor)) diff --git a/stabby/src/tests/traits.rs b/stabby/src/tests/traits.rs index 62e962a..2fd7c96 100644 --- a/stabby/src/tests/traits.rs +++ b/stabby/src/tests/traits.rs @@ -24,6 +24,7 @@ pub trait MyTrait { type Output; extern "C" fn do_stuff<'a>(&'a self, with: &'a Self::Output) -> &'a u8; extern "C" fn gen_stuff(&mut self) -> Self::Output; + extern "C" fn filter_stuff<'a>(&self, source: &'a u8) -> &'a u8; } // IMPL @@ -36,6 +37,9 @@ impl MyTrait for u8 { extern "C" fn gen_stuff(&mut self) -> Self::Output { *self } + extern "C" fn filter_stuff<'a>(&self, source: &'a u8) -> &'a u8 { + source + } } impl MyTrait for u16 { type Output = u8; @@ -45,6 +49,9 @@ impl MyTrait for u16 { extern "C" fn gen_stuff(&mut self) -> Self::Output { *self as u8 } + extern "C" fn filter_stuff<'a>(&self, source: &'a u8) -> &'a u8 { + source + } } // MYTRAIT2 @@ -141,6 +148,8 @@ fn dyn_traits() { )>::from(boxed); assert_eq!(dyned.do_stuff(&0), &6); assert_eq!(dyned.gen_stuff(), 6); + let value = 33u8; + assert_eq!(&value as *const _, dyned.filter_stuff(&value) as *const _); assert_eq!(dyned.gen_stuff3(Box::new(())), 6); // assert_eq!(unsafe { dyned.downcast_ref::() }, Some(&6)); // assert!(unsafe { dyned.downcast_ref::() }.is_none());