How to declare trait function with associated type in result


#1
trait Backend {
    type Canvas;
    
    fn canvas<'a>(&'a mut self) -> Self::Canvas<'a>;
}

When someone calls backend.canvas() it should return some Canvas and block backend until Canvas exists.
How could I do that?


#2

I believe this does what you want:

trait Backend<'a> {
    type Canvas: 'a;
    
    fn canvas(&'a mut self) -> Self::Canvas;
}

Lifetime question
#3

Could you please explain what constaint &'a implies in &'a mut self?


#4

The trait you wrote is not possible because it requires a new feature. You can’t apply a lifetime to an associated type like that. You can read more about this in this RFC. (You’ll notice that StreamingIterator from the RFC is very similar to your trait.)

The workaround that @jethrogb supplied will work; it essentially just moves the lifetime to the outside of the trait. However, in order to use this trait effectively, you have to use what are called higher-ranked trait bounds, a feature that is inconvenient has some bugs. When you want to use a T: Backend, instead you’ll probably have to write it T: for<'a> Backend<'a>.

Could you please explain what constaint &'a implies in &'a mut self?

It means that this method borrows self for as long as 'a. You’ve also said that Canvas lives at least as long as 'a. This doesn’t require that the backend be borrowed as long as Canvas exists, but it does allow you to write an impl where that is true.