'Rust: additional trait bounds in conjunction with higher-ranked lifetime bounds

I want trait implementations in Rust to be able to return arbitrary iterators (of specific item type) that may reference the original object with a lifetime 'a without having to explicitly mention 'a in the trait generics and everywhere where the trait is used or otherwise introducing significant trait bound bloat to user code. The only simple way I've figured to do this is that the trait has to be implemented for &'a MyStruct instead of MyStruct (this approach is used in some places in the standard library), but the significant drawback is that in generic code wrappers cannot “own” implementations of the trait (MyStruct) without exposing the lifetime in trait bounds all over the code. So nothing gained when ownership is needed.

Another way I figured out that should work (just done the simple test below so far) is to use higher-ranked lifetime bounds on a “base trait” that would implement the iterator-generation functions. In the code below Foo is the main trait, FooInterfaceGen is the iterator-generator trait that has its lifetime “hidden” through for <'a> when assumed as a super-trait of Foo. The FooInterface generated by FooInterfaceGen would be the trait for an appropriate type of iterator when modified to that application of the idea. However, it seems impossible to make additional trait bounds on the specific implementation FooInterfaceGen::Interface. The code below works, but when you uncomment the Asdf trait bound in the function footest, the compiler complains that

the trait `for<'a> Asdf` is not implemented for `<_ as FooInterfaceGen<'a>>::Interface

But I have implemented Asdf! It's as if the compiler is ignoring the 'a in the expression <T as FooInterfaceGen<'a>> and just applying for<'a> to the right-hand-side. Any ideas if this is a compiler bug, a known restriction, or of any ways around it?


trait FooInterface<'a> {
    fn foo(&self) -> u32;
}

trait FooInterfaceGen<'a> {
    type Interface : FooInterface<'a>;
    fn gen(&'a self) -> Self::Interface;
}

trait Foo : for<'a> FooInterfaceGen<'a> { }

struct S2;
struct S1(S2);

impl<'a> FooInterfaceGen<'a> for S1 {
    type Interface = &'a S2;    
    fn gen(&'a self) -> Self::Interface { &self.0 }
}

impl Foo for S1 { }

impl<'a> FooInterface<'a> for &'a S2 {
    fn foo(&self) -> u32 { 42 }
}

trait Asdf {}
impl<'a> Asdf for &'a S2 {}

fn footest<T : Foo>(a : &T) -> u32
/* where for<'a> <T as FooInterfaceGen<'a>>::Interface : Asdf */ {
    a.gen().foo()
}

fn main() {
    let q = S1(S2);
    println!("{}", footest(&q));
}

(Regarding some alternative implementations, maybe there's a technical reason for it, but otherwise I really don't understand the reason behind the significant trait bound bloat that Rust code easily introduces. Assuming a trait should in any reasonable situation automatically assume all the trait bound as well, also in generic code, not just specific code, without having to copy-paste an increasing number of where-clauses all over the code.)



Solution 1:[1]

The error seems to be a known compiler bug: https://github.com/rust-lang/rust/issues/89196

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Brian Bowman