I'm trying to make a generic trait where one of the methods uses a default implementation that wraps the rest to reduce boilerplate.
Here's a minimal reproduction:
trait ReadFormat<'a, 'b: 'a, Arg: 'b, T: 'static>: Sized {
fn new(c: &'a mut Cursor<'a>, arg: Arg) -> Self;
fn into_format(self) -> SResult<T>;
fn read(bytes: &'b [u8], arg: Arg) -> SResult<T> {
let c = &mut Cursor::new(bytes);
let r = Self::new(c, arg);
let f = r.into_format();
f
}
}
I'm getting the following error
61 | trait ReadFormat<'a, 'b: 'a, Arg: 'b, T: 'static>: Sized {
| -- lifetime `'a` defined here
...
65 | let c = &mut Cursor::new(bytes);
| ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
66 | let r = Self::new(c, arg);
| ----------------- argument requires that borrow lasts for `'a`
...
69 | }
| - temporary value is freed at the end of this statement
I've tried various combinations of lifetimes, but none of them work. In general, I don't understand why it expects Self to live after read returns when it's consumed by into_format and T owns all of it's data.
If I copy-paste the exact same code into a concrete implementation and replace Self::new with Reader::new it compiles.
impl<'a, 'b: 'a> ReadFormat<'a, 'b, (), ()> for Reader<'a> {
..
fn read(bytes: &'b [u8], arg: ()) -> SResult<()> {
let c = &mut Cursor::new(bytes);
let r = Reader::new(c, arg);
let f = r.into_format();
f
}
}