Sized bound unexpectedly required with return type impl trait in trait

I'm getting a weird error message related to RPITIT. Rustc complains that the return type is unsized and thus a Self: Sized bound has to be added to the trait method. It also says that it's needed in order to make the impl<D: Distrib> Distrib for &D blanket impl work. Using a concrete return type instead makes the code compile successfully.

Error message
error[E0277]: the size for values of type `Self` cannot be known at compilation time
  --> src/lib.rs:6:26
   |
 6 |     fn samples(&self) -> impl Iterator<Item = Self::Sample>
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
note: required for `&Self` to implement `Distrib`
  --> src/lib.rs:21:18
   |
21 | impl<D: Distrib> Distrib for &D {
   |      -           ^^^^^^^     ^^
   |      |
   |      unsatisfied trait bound introduced here
help: consider further restricting `Self`
   |
 7 |     where Self: Sized
   |           +++++++++++

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (lib) due to 1 previous error

Playground

trait Distrib {
    type Sample;

    fn samples(&self) -> impl Iterator<Item = Self::Sample>
    // Why does rustc insist that this is needed?
    // What does it have to do with the size of the return type?
    where
        Self: Sized,
    {
        Samples(self) // self is a reference and thus sized
    }

    // Using a concrete return type works fine without a Sized bound
    fn samples2(&self) -> Samples<&Self> {
        Samples(self)
    }
}

impl<D: Distrib> Distrib for &D {
    type Sample = D::Sample;
}

struct Samples<D>(D);

impl<D: Distrib> Iterator for Samples<D> {
    type Item = D::Sample;
    fn next(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

You need this:

impl<D: Distrib + ?Sized> Distrib for &D {
    type Sample = D::Sample;
}

otherwise there is an implicit D: Sized bound here.

2 Likes

I could've sworn that was one of the first things I tried… Thanks!