Trait bound on associated type not recognized

Hi all,

I'm trying to implement an API based on Iterators that should look like the following:

pub trait Marker {}

pub trait MarkerIter: Iterator
where
    Self::Item: Marker,
{}

impl<I> MarkerIter for I
where
    I: Iterator,
    I::Item: Marker,
{}

impl Marker for i32 {}

pub fn requires_marker<M: Marker>(m: M) {
    println!("Got marker");
}

pub fn consume_marker_iter<MI>(mi: MI) 
where
    MI: MarkerIter,
{
    mi.for_each(requires_marker);
}

For me this should work just fine, the compiler should understand that MatkerIters have always Item: Marker. However, I get the following error:

error[E0277]: the trait bound `<MI as std::iter::Iterator>::Item: Marker` is not satisfied
  --> src/lib.rs:20:1
   |
3  | / pub trait MarkerIter: Iterator
4  | | where
5  | |     Self::Item: Marker,
6  | | {}
   | |__- required by `MarkerIter`
...
20 | / pub fn consume_marker_iter<MI>(mi: MI) 
21 | | where
22 | |     MI: MarkerIter,
23 | | {
24 | |     mi.for_each(requires_marker);
25 | | }
   | |_^ the trait `Marker` is not implemented for `<MI as std::iter::Iterator>::Item`
   |
   = help: consider adding a `where <MI as std::iter::Iterator>::Item: Marker` bound

Indeed, adding the where clause solves the problem but then I could also abandon MarkerIter completly :unamused:

Has anyone an idea how to get this work?

Here is a playgound link if you want to play around on your own.

TBH I don't see why wouldn't it work. It is like the bound where Self::Item: Marker is not taken into consideration while type elision. Normally it is last thing I am thinking about, but here I would seriously consider raise an issue in rust-lang github.

1 Like

where is a requirement, not a specification. It's like a type-system-level if. MarkerIter is valid if the Item is specified to be Marker.

2 Likes

That is obviously true. However as far as I know current type system is based on prolog-like machine (chalk), so bounds are just added to some knowledge, and basing on this some reasoning is performed. This looks like something which could be easly handled by prologish machine.

Implied bounds already work in chalk, but chalk hasn't been enabled in rustc. Some integration has been made (you can pass the nightly -Zchalk flag to rustc) but it won't be enabled for a while. I don't think there have been any plans to backport the chalk behavior to the current resolver.

1 Like

Ok, I was sure that chalk is enable in rustc for some reason. It explains everything.