# Why is Iterator object-safe?

**URL:** <https://users.rust-lang.org/t/why-is-iterator-object-safe/73344>\
**Category:** uncategorized\
**Created:** [March 23, 2022, 4:26pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344 "2022-03-23T16:26:51Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![curoli](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/curoli/32/52712_2.png) [@curoli](https://users.rust-lang.org/u/curoli)\
**Post date:** [March 23, 2022, 4:26pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/1 "2022-03-23T16:26:51Z")

</div>

Hello,

I have a kind of `Iterator` in my code, and I want to have a `map` function just like there is one for the standard `Iterator`:

```rust
pub(crate) type TokenResult<I> = Result<Token<I>, ParseError>;

pub trait TokenIter<I>: Iterator<Item=TokenResult<I>> {
    fn map<J, F: FnMut(I) -> J>(self, f: F) -> Map<I, J, F>;
}

impl<T, I> TokenIter<I> for T where T: Iterator<Item=TokenResult<I>> {
    fn map<J, F: FnMut(I) -> J>(self, f: F) -> Map<I, J, F> {
        todo!()
    }
}

```

Also, I want to use my `TokenIter` for trait objects like this:

```rust
    fn parse(&self, token_iter: Box<dyn TokenIter<I>>) -> Result<A, ParseError>;

```

Rust tells me this does not work, because `map` has a type parameter and thus makes `TokenIter` not object-safe:

```rust
error[E0038]: the trait `TokenIter` cannot be made into an object
  --> src/parser.rs:5:37
   |
5 | fn parse(&self, token_iter: Box<dyn TokenIter<I>>) -> Result<A, ParseError>;
   | ^^^^^^^^^^^^^^^^ `TokenIter` cannot be made into an object
   |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
  --> src/token/token_iter.rs:10:8
   |
9 | pub trait TokenIter<I>: Iterator<Item=TokenResult<I>> {
   | --------- this trait cannot be made into an object...
10 | fn map<J, F: FnMut(I) -> J>(self, f: F) -> Map<I, J, F>;
   | ^^^ ...because method `map` has generic type parameters
   = help: consider moving `map` to another trait

```

I was hoping to take inspiration from the standard `Iterator` and its `map` method, but I can't figure out why `Iterator` is object-safe even though `map` has type parameters?

Thanks!

Best, Oliver

---

<div class="post-metadata">

**Author:** ![Michael-F-Bryan](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/michael-f-bryan/32/28749_2.png) [@Michael-F-Bryan](https://users.rust-lang.org/u/Michael-F-Bryan)\
**Post date:** [March 23, 2022, 4:42pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/2 "2022-03-23T16:42:29Z")

</div>

> [@curoli](#):
>
> why `Iterator` is object-safe even though `map` has type parameters?

Let's look at the full signature for `Iterator::map()`

> <https://github.com/rust-lang/rust/blob/c99b42cf14014987a147918fac2ad3d3290b257e/library/core/src/iter/traits/iterator.rs#L724-L727>

That `where Self: Sized` clause means the `map()` method will only be available when `Self` has a known size, allowing the rest of the interface to be object-safe.

---

<div class="post-metadata">

**Author:** ![curoli](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/curoli/32/52712_2.png) [@curoli](https://users.rust-lang.org/u/curoli)\
**Post date:** [March 23, 2022, 5:08pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/3 "2022-03-23T17:08:32Z")

</div>

Thanks for pointing out `Sized`, but what's the connection between object safety and known size?

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/skifire13/32/17959_2.png) [@SkiFire13](https://users.rust-lang.org/u/SkiFire13)\
**Post date:** [March 23, 2022, 5:15pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/4 "2022-03-23T17:15:23Z")

</div>

Trait objects don't implement `Sized`, so if you require `Self: Sized` in a method it won't be included in the trait object. This also means it won't be considered when checking if the trait is object-safe, but note that this also means you won't be able to call it on a trait object. 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.

---

<div class="post-metadata">

**Author:** ![curoli](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/curoli/32/52712_2.png) [@curoli](https://users.rust-lang.org/u/curoli)\
**Post date:** [March 23, 2022, 5:45pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/5 "2022-03-23T17:45:20Z")

</div>

Ah, thanks, that makes sense!  
I guess in my case, I will implement `map` not on `TokenIter<I>`, but instead on `Box<dyn TokenIter<I>>`.

---

<div class="post-metadata">

**Author:** ![curoli](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/curoli/32/52712_2.png) [@curoli](https://users.rust-lang.org/u/curoli)\
**Post date:** [March 23, 2022, 7:03pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/6 "2022-03-23T19:03:09Z")

</div>

Actually, I can't implement `Box<dyn TokenIter<I>>`, because it's not my type. Maybe I'll work around by making `TokenIter<I>` a struct that owns a `Box<dyn Iterator<Item=TokenResult<I>>>`. Not what I hoped for, but what can I do.

---

<div class="post-metadata">

**Author:** ![alice](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/alice/32/9777_2.png) [@alice](https://users.rust-lang.org/u/alice)\
**Post date:** [March 23, 2022, 7:55pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/7 "2022-03-23T19:55:11Z")

</div>

> [@curoli](#):
>
> Actually, I can't implement `Box<dyn TokenIter<I>>` , because it's not my type.

You can't have a bare impl block, but you should be able to implement traits for it as long as you own the `TokenIter` trait.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/skifire13/32/17959_2.png) [@SkiFire13](https://users.rust-lang.org/u/SkiFire13)\
**Post date:** [March 23, 2022, 7:59pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/8 "2022-03-23T19:59:27Z")

</div>

You could just copy the stdlib, adding `where Self: Sized` to `map` and then implementing `TokenIter<I> for Box<dyn TokenIter<I>>`. This will work because you're implementing your own trait for another type.

---

<div class="post-metadata">

**Author:** ![curoli](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/curoli/32/52712_2.png) [@curoli](https://users.rust-lang.org/u/curoli)\
**Post date:** [March 23, 2022, 8:01pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/9 "2022-03-23T20:01:55Z")

</div>

Oh, cool, thanks, I didn't think of `impl TokenIter<I> for Box<dyn TokenIter<I>>`.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://users.rust-lang.org/u/chrefr)\
**Post date:** [March 23, 2022, 8:14pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/10 "2022-03-23T20:14:29Z")

</div>

> [@curoli](#):
>
> Actually, I can't implement `Box<dyn TokenIter<I>>` , because it's not my type. Maybe I'll work around by making `TokenIter<I>` a struct that owns a `Box<dyn Iterator<Item=TokenResult<I>>>` . Not what I hoped for, but what can I do.

Assuming `TokenIter` is defined in your crate, you can do that, because `Box` is a [fundamental type](https://doc.rust-lang.org/reference/glossary.html#fundamental-type-constructors).

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [June 21, 2022, 8:14pm UTC](https://users.rust-lang.org/t/why-is-iterator-object-safe/73344/11 "2022-06-21T20:14:44Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
