I want to extend the Iterator trait with some convenience function. For example
trait BetterIterator: Iterator {
fn skip_bad(&mut self);
}
This can be achieved like this:
struct Iter {}
impl Iterator for Iter {
type Item = ();
fn next(&mut self) -> Option<()> { None }
}
impl BetterIterator for Iter {
fn skip_bad(&mut self) {}
}
fn make_iter() -> Box<dyn BetterIterator<Item=()>> {
Box::new( Iter {} )
}
fn main()
{
let mut iter = make_iter();
iter.skip_bad();
for _item in iter {
// ...
}
}
What is unusual, here, is the dynamic dispatch in make_iter
.
Now, it would be much nicer if skip_bad
could be chained, e.g.
for _item in make_iter().skip_bad() {
// ...
}
That means BetterIterator
becomes
trait BetterIterator: Iterator {
fn skip_bad(&mut self) -> &mut Self;
}
impl BetterIterator for Iter {
fn skip_bad(&mut self) -> &mut Self { self }
}
But then the compiler complains "the trait BetterIterator
cannot be made into an object".
Is it correct that the violated rule in Object Safety is "Dispatchable functions require: ...Be a method that does not use Self except in the type of the receiver."?
There is no way out of this, is there?
If dynamic dispatch is your goal you can return a mutable reference to a dyn BetterIterator
instead.
trait BetterIterator: Iterator {
fn skip_bad(&mut self) -> &mut dyn BetterIterator<Item = Self::Item>;
}
impl BetterIterator for Iter {
fn skip_bad(&mut self) -> &mut dyn BetterIterator<Item = Self::Item> { self }
}