struct S;
trait PasswordHasher<T> {}
impl<H, P> Iterator for S
where
H: PasswordHasher<P>,
{
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
Which does not compile.
I worked around this, by storing P as PhantomData in S as a workaround, but I'd rather not do this, since imho PhantomData is just noise when reading the code.
I also imagined that maybe this would work
struct S;
trait PasswordHasher<T> {}
impl<H> Iterator for S
where
for<P> H: PasswordHasher<P>,
{
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
But HRTBs sadly only work with lifetimes at the moment.
Is there any way to implement this without resorting to PhantomData?
It would help to describe what you're actually trying to do.
Notably, the reason that doesn't work is that it doesn't make sense -- which P? Why that one? What are you doing with it? What if something implements PasswordHasher for multiple different Ps? Without having a call or a method, we have no idea what you're even trying to accomplish.
Maybe you want the <T> on a method in a non-generic PasswordHasher trait. Maybe you want a PhantomData. Maybe you want an associated type on PasswordHasher instead of a generic. But you have to say what you're trying to so.
I want to get rid of the PhantomData in the struct.
I can move the generic P into the functions in verify() and hash() without problems, but then, I get issues when specifying P on the iterator implementation.
Edit:
On second thought, I guess that my problem then boils down to having multiple implementations of Iterator for the same type, which is not possible due to its API using a single associated type.
I guess I just leave it as it is.