Question about lifetimes (E0311)

When I try to compile the following code:

use std::borrow::BorrowMut;

trait U8Mut {
    fn u8_mut(&mut self) -> &mut u8;
}

trait U8MutBorrowed<T> 
{
    fn u8_mut_borrowed(&mut self) -> &mut u8;
}

impl<T, U> U8MutBorrowed<T> for U
where 
    U: BorrowMut<T>,
    T: U8Mut 
    // + 'static // This solves the problem
{
    fn u8_mut_borrowed(&mut self) -> &mut u8 {
        self.borrow_mut().u8_mut()
    }
}

fn main() {}

I get the following error:

error[E0311]: the parameter type `T` may not live long enough                                                                                 
  --> src/main.rs:19:27                                                                                                                       
   |                                                                                                                                          
19 |         self.borrow_mut().u8_mut()                                                                                                       
   |                           ^^^^^^                                                                                                         
   |                                                                                                                                          
   = help: consider adding an explicit lifetime bound for `T`                                                                                 
note: the parameter type `T` must be valid for the anonymous lifetime #1 defined on the method body at 18:5...                                
  --> src/main.rs:18:5                                                                                                                        
   |                                                                                                                                          
18 | /     fn u8_mut_borrowed(&mut self) -> &mut u8 {                                                                                         
19 | |         self.borrow_mut().u8_mut()                                                                                                     
20 | |     }                                                                                                                                  
   | |_____^                                                                                                                                  
note: ...so that the reference type `&mut T` does not outlive the data it points at                                                           
  --> src/main.rs:19:27                                                                                                                       
   |                                                                                                                                          
19 |         self.borrow_mut().u8_mut()                                                                                                       
   |                           ^^^^^^                 

I know how I can “fix” it, but I don’t understand why I get the error. Can somebody explain this? Thanks!

I don’t know the answer for sure, but I think this might be one of those situations where the compiler can’t prove a universal: "for all T, if U is BorrowMut<T> and U: 'a, then T must also be 'a". Although it could prove such a statement for any particular T, I’ve found it sometimes can’t generalize things and this might be one of those times.

However, I do know that T doesn’t need to be 'static – it only needs to outlive the lifetime parameter of u8_mut_borrowed. So this will also work (and there’s at least one other way to do it):

trait U8MutBorrowed<'a, T> 
{
    fn u8_mut_borrowed(&'a mut self) -> &'a mut u8;
}

impl<'a, T, U> U8MutBorrowed<'a, T> for U
where 
    U: BorrowMut<T>,
    T: U8Mut + 'a,
{
    fn u8_mut_borrowed(&'a mut self) -> &'a mut u8 {
        self.borrow_mut().u8_mut()
    }
}
1 Like

Thank you very much!