Extracting static associated type from type with lifetime

I know this might sound weird, but we are in a situation in which we have a trait T with an associated type A with a lifetime, and A in turn is bound by a trait U that has an associated type B that is Copy, 'static, whatever, basically a number.

Our problem is that we need to extract B from T without having a lifetime around. So

trait T {
    type A<'a>: U
        where Self: 'a;
}

trait U {
    type B: 'static + Clone + Copy + Send + Sync;
}

The real-life situation is that T is a factory of I/O things of type A, satisfying the trait U that have a lifetime as they depends on some memory held by T, like a Cursor, and B is its error type, which however has no connection with the lifetime—it's just an enum.

With for you can constrain B in a where clause, but we need the opposite—we need to retrieve B from T, in a situation in which there's no lifetime around.

It seems something reasonable to do—B is a static type that has nothing to do with 'a.

But can you do it?

Our current solution is to "copy" B into an associate type C of T. But when we have to write continuously where clauses with for specifying that B and C are the same.

Why do you have to do that? This works for what I tried:

trait T {
    type A<'a>: U<B = Self::C>
        where Self: 'a;
    type C: 'static + Clone + Copy + Send + Sync;
}
2 Likes

This is exactly what we do—that's what I meant by "copying". I should have written an example. The problem is that when we try to implement T

It works without the for bound.

Yes. We need that bound because in the real (more complicated) example A has other type parameters and does not always implement U.

That's a key component of the problem that makes a for<..> bound required somewhere.

You can try a subtrait for the case where A<'_>: U, along with a blanket implementation.

trait T {
    type A<'a>;
}

trait SubT: for<'a> T<A<'a>: U<B = Self::C>> {
    type C: 'static + Clone + Copy + Send + Sync;
}

impl<Ty, C> SubT for Ty
where
    Ty: ?Sized + for<'a> T<A<'a>: U<B = C>>,
    C: 'static + Clone + Copy + Send + Sync,
{
    type C = C;
}

Then you can use the bound Ty: SubT instead of Ty: for<..> T<..> when needed elsewhere.

N.b. no matter what you may run into the poor interaction between for<..> bounds and GATs since for<..> is required. Though if all implementors of T are 'static, it may not be relevant.

Thanks, that was a really good suggestion. You should have a tagline like “I’m Winston Wolfe. I solve problems”.