Constraint on trait with GAT leaks outside?

Hello!

I'm trying to utilize Iterable trait:

use std::ops::Deref;

trait Iterable {
    type Item<'a> where Self: 'a;
    type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
    
    fn iter<'a>(&'a self) -> Self::Iter<'a>;
}

trait Set<T>: Iterable
where
    for<'a> <Self as Iterable>::Item<'a>: Deref<Target = T>
{ }

trait Types {
    type Set: Set<i32>;
}

fn main() {
    
}

Unfortunately, I receive compilation error:

error[E0277]: the trait bound `for<'a> <<Self as Types>::Set as Iterable>::Item<'a>: Deref` is not satisfied
  --> src/main.rs:16:15
   |
16 |     type Set: Set<i32>;
   |               ^^^^^^^^ the trait `for<'a> Deref` is not implemented for `<<Self as Types>::Set as Iterable>::Item<'a>`
   |
note: required by a bound in `Set`
  --> src/main.rs:12:43
   |
10 | trait Set<T>: Iterable
   |       --- required by a bound in this
11 | where
12 |     for<'a> <Self as Iterable>::Item<'a>: Deref<Target = T>
   |                                           ^^^^^^^^^^^^^^^^^ required by this bound in `Set`

If I modify Types according to recommendations:

use std::ops::Deref;

trait Iterable {
    type Item<'a> where Self: 'a;
    type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
    
    fn iter<'a>(&'a self) -> Self::Iter<'a>;
}

trait Set<T>: Iterable
where
    for<'a> <Self as Iterable>::Item<'a>: Deref<Target = T>
{ }

trait Types {
    type Set: Set<i32>
    where
        for<'a> <<Self as Types>::Set as Iterable>::Item<'a>: Deref<Target = i32>;
}

fn main() {
    
}

it works, but extremely ugly, I can't even move Deref requirement to generics block, where it would be much more readable

Meanwhile, following variant:

use std::ops::Deref;

trait Iterable<T> {
    type Item<'a>: Deref<Target = T> where Self: 'a;
    type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
    
    fn iter<'a>(&'a self) -> Self::Iter<'a>;
}

trait Set<T>: Iterable<T>
{ }

trait Types {
    type Set: Set<i32>;
}

fn main() {
    
}

works just fine, but isn't suitable since Deref bound is moved to Iterable declaration.

Any ideas what to do with first variant to make it not require lengthy bound at the usage spot?

Thanks

EDIT:
I thought it's caused by generic bound moved to associated type and tried this:

use std::ops::Deref;

trait Iterable {
    type Item<'a> where Self: 'a;
    type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
    
    fn iter<'a>(&'a self) -> Self::Iter<'a>;
}

trait Set: Iterable
where
    for<'a> <Self as Iterable>::Item<'a>: Deref<Target = <Self as Set>::Elem>
{
    type Elem;
}

trait Types {
    type Set: Set<Elem = i32>;
}

fn main() {
    
}

Sadly, still no luck. The only way I found is to merge Iterable into Set and declare Item, Iter and fn iter in Set trait.

Don't see anything related to GAT's here, looks like good old issue 20671.

Not any different from the following example:

trait Foo<T: ?Sized> {}

trait Bar where i32: Foo<Self> {}

trait Baz: Bar {}

impl<T: Bar> Baz for T {}

Same story as usual: no, no, I don't believe you that any type that satisfies Bar constraints can be used as Bar… tell me that it would actually work, then I'll believe you:

trait Foo<T: ?Sized> {}

trait Bar where i32: Foo<Self> {}

trait Baz: Bar where i32: Foo<Self> {}

impl<T: Bar> Baz for T where i32: Foo<Self> {}
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.