Newbie fighting HRTBs


#1

Let me begin with saying thank you for your help.
Now to the problem I am fighting. Please consider the following code:

pub trait T1 {
    fn id(&mut self) -> ();
}

pub struct S1<'a, T>
where for<'t: 'a> T: 't + T1
{
    rt: &'a mut T
}

pub struct ST1;
impl T1 for ST1 {
    pub fn id(&mut self) {
        println!("ST1");
    }
}

fn main() {
    let mut st1 = &mut ST1;
    let mut s1 = S1 {rt: st1};
}

This code gives me the following error:

src/test.rs:8:5: 8:18 error: the parameter type `T` may not live long enough [E0309]
src/test.rs:8     rt: &'a mut T
                  ^~~~~~~~~~~~~
src/test.rs:8:5: 8:18 help: run `rustc --explain E0309` to see a detailed explanation
src/test.rs:8:5: 8:18 help: consider adding an explicit lifetime bound `T: 'a`...
src/test.rs:8:5: 8:18 note: ...so that the reference type `&'a mut T` does not outlive the data it points at
src/test.rs:8     rt: &'a mut T
                  ^~~~~~~~~~~~~
error: aborting due to previous error
error: Could not compile `test`.

My question is why such an error? I thought I am telling compiler that T should live as long as 't for all 't that outlive 'a (for<'t: 'a>) What am I missing?


#2

I don’t have an answer for why that error is happening (your interpretation of the where clause is correct and logically seems like it should work) but would it be possible to use where T: 'a + T1 like the message tells you? That works, as does where for<'t: 'a> T: 't + 'a + T1 (depending on what your real code looks like).


#3

If i do where T: 'a + T1 it will tie together lifetime of T to a lifetime of the reference, which I was trying to avoid. Doing the T: 't + 'a + T might actually work as we saying that T should live as long as 'a and as long as 't, which, considering that 't is longer than 'a, is the same as to say T should live as long as 't, which is what I want. Let me try that. Thank you for the answer.


#4

Is for<'t: 'a> T: 't materially different from T: 'static?


#5

In my real case it’s not as my "T" really leaves for the whole life of the program. However from abstraction stand point I didn’t want to impose that restriction, as it’s unnecessary restrictive, all I wanted to say is that T should leave longer than the reference to it that I am using in my struct. I am newbie and trying to learn and understand how to talk Rust. :slight_smile:


#6

This to me sounds like exactly T: 'a i.e. any borrows held by T must outlive 'a or else there’d be a dangling pointer situation. Note that it’s not about the scope of an actual instance of T but about the type itself and types don’t ‘live’.


#7

Ditto @gkoz. You want T: 'a + T1. For lifetimes the colon is pronounced “outlives” so T: 'a is pronounced "T outlives the lifetime 'a", so any lifetime for T that outlives 'a should work.


#8

Hm… I guess both of you are right. I’ll try that and will see what are the consequences in the real code. Thanks again.