Type alias adds Sized restriction?

I have a type alias:

type DynIter<'a, T> = Box<dyn Iterator<Item=T> + 'a>;

I want to do this:

let mut iter = DynIter::new(vec.iter());

But I get an error:

error[E0599]: no function or associated item named `new` found for struct `std::boxed::Box<dyn std::iter::Iterator<Item = _>>` in the current scope
    --> src/main.rs:4:29
     |
4    |       let mut iter = DynIter::new(vec.iter());
     |                               ^^^ function or associated item not found in `std::boxed::Box<dyn std::iter::Iterator<Item = _>>`
     |
     = note: the method `new` exists but the following trait bounds were not satisfied:
             `dyn std::iter::Iterator<Item = _>: std::marker::Sized`

But this works:

let mut iter: DynIter<'_, _> = Box::new(vec.iter());

So, why can't I use the type alias for Box::new in this case?

Box::<T>::new requires T: Sized because it's taking the value T as a direct argument. Once constructed, it can be coerced to the unsized Box type.

Box<dyn Trait> doesn't have a new method at all, since dyn Trait can't be passed as a value.

3 Likes

Thanks, @camsteffen for asking the question.
Thanks, @cuviper for answering.
Now I'm wondering why the type Box is generic over T: ?Sized but the new() method is only generic over T (so by default, T: Sized if I understand all of this correctly)... Why not define the new() method with T: ?Sized bound?

Probably because we can't pass unsized argument to function, and Box::new takes argument of type T.

1 Like

As someone who has used Java and Javascript a lot, it is hard for me to convince myself that a dyn Trait is not a reference (and thus dynamically sized).

Well the thing that's a reference is a &dyn Trait.

1 Like

In Rust, there are no implicit references. You always have to take references/pointers explicity by working with &T, &mut T, *const T, *mut T, or smart pointers like Box<T> or Rc<T>.

The very point of dyn Trait being ?Sized is exactly that it's not a pointer unto itself. It's a dynamically-sized value, which therefore cannot exist on its own. You always have to use it through a pointer, e.g. Box<dyn Trait>.

If dyn Trait were in itself a reference, you'd have to specify separately whether it's owning or not (similarly to the distinction between references vs Box), and it would always require a double indirection to use it with smart pointers. That would be far inferior in terms of usability, complexity, language uniformity, and runtime performance than the status quo – i.e. just specifying what kind of regular reference or smart pointer you want to use it with.

(Relatedly, note that references and raw/smart pointers are always Sized, even if their pointed value is ?Sized.)

1 Like

I understand. I'm just saying it's a paradigm shift. Thanks for the explanations.