Why can I invoke Iterator::take on Box<dyn Iterator> or &mut dyn Iterator?

According to object safety, if a method of a trait has bound Self: Sized, then this method would be non-dispatchable via a trait object, and such a method won't prevent creating a trait object of that trait.

It seems that Iterator::take matches the description above, whose signature is:

fn take(self, n: usize) -> Take<Self>
        Self: Sized

So in theory, we cannot call Iterator::take on a pointer to dyn Iterator like Box<dyn Iterator> or &mut dyn Iterator.

But actually we can, as the playground shown. So why can we invoke Iterator::take on its trait object, but can't invoke NonDispatchable::returns?

I have found a thread in this forum, as the answer said:

The stdlib solved this final problem by implementing Iterator for Box<dyn Iterator> and &mut dyn Iterator by reimplementing all the methods in terms of next , which is object safe and thus included in the trait object.

But I didn't find corresponding implementation in the implementors of Iterator. And directly search for sth like impl Iterator for &mut dyn matches nothing in the library/ directory of rust-lang repo. So what is the true answer of this problem? Specifically, if such implementation does exist, where can I find their source code? I'm really interested in how to implement take and other methods like this without any additional data structures and solely rely on Iterator::next.

It's these two blanket implementations - for &mut I, for Box<I>, both using the fact that dyn Trait always implements Trait.

These blanket implementations simply forward non-consuming methods, i.e. once which doesn't require Self: Sized (including next), to the underlying implementation; and all other methods, like take, are implemented on top of that (actually by just using the default implementation).

1 Like

Thanks for the reply! So the key here is that although dyn Iterator is !Sized, but &mut dyn Iterator and Box<dyn Iterator> is Sized, so we can return Take<Self> when Self = &mut dyn Iterator which is Sized?

Yes, exactly.

1 Like