taubem
taubem

Reputation: 51

How can I bound the `IntoIter` type for `<&Self as IntoIterator>`?

I have a trait for which I want to require that implementing types are iterable by borrow. I have managed to do this using a for<'x> higher-ranked trait bound (HRTB) on &'x Self.

However, I also want to require that the IntoIter associated type implements ExactSizeIterator, but every way I try to describe this in the type system causes compilation issues which seem to stem from the use of the HRTB (which I am not fully confident I'm using correctly).

Here is the (simplified) code:


struct Thing<'thing>(&'thing ());

trait Trait<'thing>
    where
        for<'x> &'x Self: IntoIterator<Item = &'x Thing<'thing>>,
        // Compiles fine until uncommenting this line:
        //for<'x> <&'x Self as IntoIterator>::IntoIter: ExactSizeIterator
{ }

struct Bucket<'things> {
    things: Vec<Thing<'things>>,
}

struct BucketRef<'a, 'things: 'a> {
    bucket: &'a Bucket<'things>,
}

impl<'x, 'a, 'things: 'a> IntoIterator for &'x BucketRef<'a, 'things> {
    type Item = &'x Thing<'things>;
    type IntoIter = std::slice::Iter<'x, Thing<'things>>;
    fn into_iter(self) -> Self::IntoIter {
        self.bucket.things.iter()
    }
}

impl<'a, 'things: 'a> Trait<'things> for BucketRef<'a, 'things> { }

fn foo<'a, 'things>(anchor: &BucketRef<'a, 'things>) {
    println!("{}", ExactSizeIterator::len(&anchor.into_iter()));
}

As written this compiles fine, but when I try to further restrict the bounds on Trait via the commented line, I get the following compiler error:

error[E0277]: the trait bound `for<'x> <&'x anchor::BucketRef<'a, 'things> as std::iter::IntoIterator>::IntoIter: std::iter::ExactSizeIterator` is not satisfied

It seems to my not-a-compiler-writer mind that given rustc appears able to determine inside the function foo that all instances of &BucketRef are ExactSizeIterators, that it should be able to do similarly for the trait bound, but this is not borne out in reality.

Can anyone explain to me why this doesn't work and if there is a better way to express either the bound itself or the intent behind the bound?

active toolchain
----------------
stable-x86_64-unknown-linux-gnu (default)
rustc 1.43.0 (4fb7144ed 2020-04-20)

Upvotes: 5

Views: 659

Answers (1)

Related Questions