HRTBs for unspecified lifetimes?

Would it ever be possible to write an HRTB for a type whose lifetime variables' names' you don't know? That is, something like for<any lifetimes included in T> fn(T) -> u32?


I'm the author of Mockall, a popular mocking library. In order to mock generic methods, Mockall needs to store a completion function as a Box<Any>, and later downcast it to a concrete form. Mockall does not need to downcast the method's generic types; just a Fn object that accepts or returns those types. There is no reason why the completion function can't be 'static; Mockall already handles functions with reference arguments by adding an appropriate HRTB. The problem is that for non-static types more complicated than a reference, Mockall doesn't know what the lifetime arguments are.

One solution would be to allow TypeId for non-'static types. But that dead horse has been beaten enough. My request is simpler. Would it be possible to define an HRTB for every lifetime contained in a given type?

1 Like

A way of accomplishing something similar is just T: 'a, which requires T to be valid for (at least) 'a. This, in turn, means any lifetime parameters in T must outlive 'a.

If this isn't what you want, it'd be good to clarify further.

Yes, something like that would be good. But the compiler won't accept that, as far as I can tell. Here is the best that I can do: In the function bar, I tried to bound T by a lifetime and put that lifetime in the HRTB. But Rust still thinks that the function isn't 'static. Am I doing something wrong?

While definitely not convenient, you can accomplish what I think you want via a GAT indirection to pass a type constructor directly:

trait Bind1 {
    type Bind1<'a>;

struct Proxy;
impl Bind1 for Proxy {
    type Bind1<'a> = YourRealType<'a, 'a, 'a>;

fn type_id1<Ty: Bind1>() -> TypeId {
    TypeId::of::<for<'a> fn(Ty::Bind1<'a>) -> u32>()

No, that's no better. Even there the lifetimes of YourRealType are known. If I knew that, I could just write a longer HRTB: for<'a, 'b, 'c>.

Yea, it would be great to be able to add constraints involving higher ranked parameters, but currently that's not possible in Rust. I don't remember if this is something that would be tractable with chalk or if it presents other problems.

Rustc somewhat supports it internally for &'a &'b T, but doesn't store it in the binder. I believe there is a soundness issue because of that.