Skip to content

Commit

Permalink
Merge pull request #48 from spastorino/properly-handle-trait-lifetimes
Browse files Browse the repository at this point in the history
Lifetimes mentioned in return type also matter
  • Loading branch information
tmandry authored Feb 7, 2025
2 parents 53b2f14 + 4ba5da0 commit c14a47e
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 22 deletions.
21 changes: 21 additions & 0 deletions dynosaur/tests/pass/multiple-lifetimes-and-where-clauses.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#[dynosaur::dynosaur(DynSomeTrait)]
trait SomeTrait<'a, 'b> {
async fn lotsa_lifetimes<'d, 'e, 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) -> &'a u32
where
'b: 'a;
}

struct MyData<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32)
where
'b: 'a;

impl<'a, 'b, 'c> SomeTrait<'a, 'b> for MyData<'a, 'b, 'c> {
async fn lotsa_lifetimes<'d, 'e, 'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) -> &'a u32
where
'b: 'a,
{
self.0
}
}

fn main() {}
98 changes: 98 additions & 0 deletions dynosaur/tests/pass/multiple-lifetimes-and-where-clauses.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
trait SomeTrait<'a, 'b> {
async fn lotsa_lifetimes<'d, 'e,
'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32)
-> &'a u32
where
'b: 'a;
}
mod _dynosaur_macro_dynsometrait {
use super::*;
trait ErasedSomeTrait<'a, 'b> {
fn lotsa_lifetimes<'d, 'e, 'f, 'life0,
'dynosaur>(&'life0 self, a: &'d u32, b: &'e u32, c: &'f u32)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
&'a u32> + 'dynosaur>>
where
'b: 'a,
'd: 'dynosaur,
'e: 'dynosaur,
'f: 'dynosaur,
'a: 'dynosaur,
'b: 'dynosaur,
'life0: 'dynosaur,
Self: 'dynosaur;
}
impl<'a, 'b, DYNOSAUR: SomeTrait<'a, 'b>> ErasedSomeTrait<'a, 'b> for
DYNOSAUR {
fn lotsa_lifetimes<'d, 'e, 'f, 'life0,
'dynosaur>(&'life0 self, a: &'d u32, b: &'e u32, c: &'f u32)
->
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
&'a u32> + 'dynosaur>> where 'b: 'a, 'd: 'dynosaur,
'e: 'dynosaur, 'f: 'dynosaur, 'a: 'dynosaur, 'b: 'dynosaur,
'life0: 'dynosaur, Self: 'dynosaur {
Box::pin(<Self as
SomeTrait<'a, 'b>>::lotsa_lifetimes(self, a, b, c))
}
}
#[repr(transparent)]
pub struct DynSomeTrait<'dynosaur_struct, 'a, 'b> {
ptr: dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct,
}
impl<'dynosaur_struct, 'a, 'b> SomeTrait<'a, 'b> for
DynSomeTrait<'dynosaur_struct, 'a, 'b> {
fn lotsa_lifetimes<'d, 'e,
'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32)
-> impl ::core::future::Future<Output = &'a u32> where 'b: 'a {
let fut:
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
&'a u32> + '_>> = self.ptr.lotsa_lifetimes(a, b, c);
let fut:
::core::pin::Pin<Box<dyn ::core::future::Future<Output =
&'a u32> + 'static>> =
unsafe { ::core::mem::transmute(fut) };
fut
}
}
impl<'dynosaur_struct, 'a, 'b> DynSomeTrait<'dynosaur_struct, 'a, 'b> {
pub fn boxed(value: impl SomeTrait<'a, 'b> + 'dynosaur_struct)
-> Box<DynSomeTrait<'dynosaur_struct, 'a, 'b>> {
let value = Box::new(value);
let value: Box<dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct> =
value;
unsafe { ::core::mem::transmute(value) }
}
pub fn from_ref(value: &(impl SomeTrait<'a, 'b> + 'dynosaur_struct))
-> &DynSomeTrait<'dynosaur_struct, 'a, 'b> {
let value: &(dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct) =
&*value;
unsafe { ::core::mem::transmute(value) }
}
pub fn from_mut(value:
&mut (impl SomeTrait<'a, 'b> + 'dynosaur_struct))
-> &mut DynSomeTrait<'dynosaur_struct, 'a, 'b> {
let value: &mut (dyn ErasedSomeTrait<'a, 'b> + 'dynosaur_struct) =
&mut *value;
unsafe { ::core::mem::transmute(value) }
}
}
}
use _dynosaur_macro_dynsometrait::DynSomeTrait;

struct MyData<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32) where 'b: 'a;

impl<'a, 'b, 'c> SomeTrait<'a, 'b> for MyData<'a, 'b, 'c> {
async fn lotsa_lifetimes<'d, 'e,
'f>(&self, a: &'d u32, b: &'e u32, c: &'f u32) -> &'a u32 where
'b: 'a {
self.0
}
}

fn main() {}
16 changes: 11 additions & 5 deletions dynosaur_derive/src/expand.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::lifetime::{used_lifetimes, AddLifetimeToImplTrait, CollectLifetimes};
use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes};
use crate::receiver::has_self_in_sig;
use crate::sig::{is_async, is_rpit};
use crate::where_clauses::{has_where_self_sized, where_clause_or_default};
Expand Down Expand Up @@ -92,12 +92,18 @@ fn expand_fn_input(item_trait_generics: &Generics, sig: &mut Signature) {
}
}

for param in used_lifetimes(&item_trait_generics, &lifetimes.explicit) {
let param = &param.lifetime;
let span = param.span();
for lifetime in item_trait_generics
.params
.iter()
.filter_map(move |param| match param {
GenericParam::Lifetime(param) => Some(&param.lifetime),
_ => None,
})
{
let span = lifetime.span();
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(span=> #param: 'dynosaur));
.push(parse_quote_spanned!(span=> #lifetime: 'dynosaur));
}

if sig.generics.lt_token.is_none() {
Expand Down
19 changes: 2 additions & 17 deletions dynosaur_derive/src/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use proc_macro2::{Span, TokenStream};
use std::mem;
use syn::visit_mut::{self, VisitMut};
use syn::{
parse_quote_spanned, token, Expr, GenericArgument, GenericParam, Generics, Lifetime,
LifetimeParam, Receiver, ReturnType, Token, Type, TypeBareFn, TypeImplTrait, TypeParen,
TypePtr, TypeReference,
parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Token, Type,
TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference,
};

pub struct CollectLifetimes {
Expand Down Expand Up @@ -111,17 +110,3 @@ fn parenthesize_impl_trait(elem: &mut Type, paren_span: Span) {
});
}
}

pub(crate) fn used_lifetimes<'a>(
generics: &'a Generics,
used: &'a [Lifetime],
) -> impl Iterator<Item = &'a LifetimeParam> {
generics.params.iter().filter_map(move |param| {
if let GenericParam::Lifetime(param) = param {
if used.contains(&param.lifetime) {
return Some(param);
}
}
None
})
}

0 comments on commit c14a47e

Please sign in to comment.