Generic struct with non `'static` type should be `'static` if it never holds such element

I am trying to declare a trait to capture a set of implementations that convert one type to another type.

trait Convertor<In, Out>: 'static + Clone {
    fn convert<'a>(self, input: In) -> Out
    where
        In: 'a,
        Out: 'a;
}

I want the convertor itself to not hold any non static references, hence declared on 'static and also be clonable.
The method convert however need not require input be 'static, (i.e. I would like to allow taking in references as well). The only guarantee to be give is that output must be valid for at least the lifetime of input.

As the convert method consumes itself, I create a trait to jump over virtual methods over a Box like

trait ErasedConvertor<In, Out>: 'static {
    fn boxed_convert<'a>(self: Box<Self>, input: In) -> Out
    where
        In: 'a,
        Out: 'a;

    fn boxed_clone(&self) -> Box<dyn ErasedConvertor<In, Out>>;
}
impl<C, In, Out> ErasedConvertor<In, Out> for C
where
    C: 'static + Convertor<In, Out> + Clone,
{
    fn boxed_convert<'a>(self: Box<Self>, input: In) -> Out
    where
        In: 'a,
        Out: 'a,
    {
        self.convert(input)
    }

    fn boxed_clone(&self) -> Box<dyn ErasedConvertor<In, Out>> {
        Box::new(self.clone())
    }
}

Then went about declaring a boxed convertor as

struct BoxedConvertor<In, Out> {
    convertor: Box<dyn ErasedConvertor<In, Out>>,
}

Now purely through the signature of BoxedConvertor<In,Out> it looks like(and is the case that) the lifetime of it should be minimum of lifetime of In and Out.
But the struct can be technically 'static as all the fields in it are 'static too.
(I want to claim dyn ErasedConvertor<In,Out> be 'static even when In and Out need not be 'static, In a sense to declare it can never hold In and Out if they are not 'static)

The below code leads to compilation error, as compiler asks for In and Out to be 'static which defeats the goal.

impl<In, Out> Convertor<In, Out> for BoxedConvertor<In, Out> {
    fn convert<'a>(self, input: In) -> Out
    where
        In: 'a,
        Out: 'a,
    {
        self.convertor.boxed_convert(input)
    }
}

impl<In, Out> Clone for BoxedConvertor<In, Out> {
    fn clone(&self) -> Self {
        Self {
            convertor: self.convertor.boxed_clone(),
        }
    }
}

Any implementation of ErasedConvertor<In,Out> can't hold non static references as the trait is super trait on 'static.

Any ways to implement something like this?

that is not really how types work. 'static types cannot contain any lifetime in them.

if a type has a type parameter that is not 'static, then it itself is not 'static.

this is crucial for things like Any for example.
if you want to be able to act upon non-'static types you should try to be generic instead.

for example dyn for<'a> ErasedConvertor<&'a str, &'a [u8]> is 'static.

but that is pretty limiting unlessyou know you just want one lifetime parameter

this crate helps for this kind of stuff :

1 Like

Implementors could use unsafe to store values of lifetime-laden types while themselves being 'static, and rely upon the invariance of trait parameters for soundness.

And as alluded to by @Morgane55440, if dyn Trait<Param> + 'static met a 'static bound itself, you could transmute lifetimes of Param in safe code by round-tripping through dyn Any. There could be an implementation (without unsafe) that stores &'static Whatevers as the In parameter, and if what you asked was possible, I could make it dyn and then convert it to something I can pass non'static &Whatevers to, which would be unsound.

This comment is more or less a repeat of my reply in issue 104684. That reply includes code examples.

Something like

this, or a collection of marker types for common type constructors to abstract this pattern a little, are the closest things I can think of.

1 Like