And I'm wondering if there's a better interface than this:
pub trait WriteExtension<T> {
type Adapter<'a>
where
Self: 'a;
fn write_adapter(&mut self) -> Self::Adapter<'_>;
}
impl<W: io::Write> WriteExtension<Struct1<W>> for W {
type Adapter<'a> = Struct1<&'a mut W> where W: 'a;
fn write_adapter(&mut self) -> Struct1<&mut W>
}
impl<H: Hasher> WriteExtension<Struct2<H>> for H {
type Adapter<'a> = Struct2<&'a mut H> where H: 'a;
fn write_adapter(&mut self) -> Struct2<&mut H>
}
Originally I tried to just make WriteExtension generic, but the output of write_adapter needs to access the lifetime of self, so I'm pretty sure that doesn't work. Next, I tried using only associated types, but the issue there is that my two WriteExtension impls conflict. So finally I added back a generic that I don't use in the trait just so I can get the trait resolver to play nice.
You could make them different traits, since the implementations do different things anyway (return an io::Writer, or return a fmt::Writer). In a sense you've already done that by turning your trait into a "trait constructor" by adding the parameter.
If you do this, you don't need the GAT and you can optionally give them different names if you find it's ambiguous a lot.
I see, thanks for the help! I decided to go the clear trait constructor output names route as I'd like users to be able to import a single trait and get all the adapters.