I've seen this potential future feature mentioned since several years ago. Has there been any work toward this, or has interest faded away? I'm writing a very flexible imaging library that would benefit hugely.
Here is how a trait could look in a perfect world:
pub trait Image {
type Index;
type Pixel<'a>;
fn pixel<'a> (&'a self, index: Self::Index) -> Self::Pixel<'a>;
}
// Fill returns the same value at any index.
// T is copyable, so we can just return it any time pixel() is called.
impl<T: Copy, I> Image for Fill<T, I> {
type Index = I;
type Pixel<'a> = T;
fn pixel<'a> (&'a self, _: I) -> T { self.pixel }
}
// VecImage2 is a 2-dimensional image of T's backed by a Vec.
// T is possibly not copyable or even clonable, so we want to return a reference to the pixel instead of a value.
impl<T> Image for VecImage2<T> {
type Index = Point2;
type Pixel<'a> = &'a T;
fn pixel<'a> (&'a self, pt: Point2) -> &'a T { ... }
}
Without the ability to parameterize the Pixel
associated type with a lifetime, I can think of two ugly workarounds, both of which I've tried and found cumbersome.
Workaround 1:
// Parameterize the trait instead of the Pixel type.
// This gives generic functions working with images ugly and complicated signatures that sometimes don't work too well.
trait Image<'a> {
type Index;
type Pixel : 'a;
fn pixel (&'a self, index: Self::Index) -> Self::Pixel;
}
impl<'a, T: 'a, I> Image<'a> for Fill<T, I> {
type Index = I;
type Pixel = T;
fn pixel (&'a self, _: I) -> T { self.pixel }
}
// We can still return a reference, but at a cost of ergonomics.
impl<'a, T: 'a> Image<'a> for VecImage2<T> {
type Index = Point2;
type Pixel = &'a T;
fn pixel (&'a self, pt: Point2) -> &'a T { ... }
}
Workaround 2:
// Forget about lifetimes in the trait at all.
pub trait Image {
type Index;
type Pixel;
fn pixel (&self, index: Self::Index) -> Self::Pixel;
}
// Implement Image for a reference to VecImage2 instead of the struct itself.
// Now we can't make a blanket impl of Image for references to other Image types and &self is a reference to a reference.
impl<'a, T> Image for &'a VecImage2<T> {
type Index = Point2;
type Pixel = &'a T;
fn pixel (&self, pt: Point2) -> &'a T { ... }
}