Blanket IntoIter implementation

It's a bit of a newb question and i I think i already know the answer but asking to confirm anyway: can a blanket implementation of trait like IntoIter below be made to work, or will coherence not allow it ? ( error: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local )

impl<'a, T> IntoIterator for &'a T
where
    T: FooRef<Struct = T>,
{
    type Item = <VeryGenericIterator<'a, FooStruct> as Iterator>::Item;
    type IntoIter = VeryGenericIterator<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        VeryGenericIterator {
            data: self,
            done: false,
        }
    }
}

Playground link

Very similar code when implemented for a concrete type works just fine of course:

impl<'a > IntoIterator for &'a FooStruct
where
    FooStruct: FooRef<Struct = FooStruct>,
{
    type Item = <VeryGenericIterator<'a, FooStruct> as Iterator>::Item;
    type IntoIter = VeryGenericIterator<'a, FooStruct>;
    fn into_iter(self) -> Self::IntoIter {
        VeryGenericIterator {
            data: self,
            done: false,
        }
    }
}

This also of course works with a macro for every specific struct, but i was hoping to avoid that. Other alternatives are to do Wrapper<T> or just not use IntoIter and have my own equivalent trait with .iter() or such.

I'm hoping there's some existing trick with extra bound or constraint to get around the potential conflict, or there's an obvious bug in how I'm trying to do this ?

As far as I'm aware, orphan rules will currently indeed never allow such a blanket impl, but I regularly find this fact a bit unfortunate (or rather something where it seems like it should be possible to improve the compiler) in the case where FooRef is a trait local to the current crate.

3 Likes

FooRef being local to the crate isn't enough though. The more operating thing is that the types to which this blanket impl applies must be local to the crate - i.e. the compiler would have to additionally prevent the crate to implement FooRef<Struct=T> for &[T] - which is a more complicated requirement. Can theoretically be enforced (transitively), but might result in more complicated error messages.

1 Like

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.