Where bound for type equality with GAT without cycles
⚓ Rust 📅 2026-01-04 👤 surdeus 👁️ 2Consider this code:
use higher_kinded_types::ForLifetime;
pub trait LendingFn<T> {
type Output<'a>
where
Self: 'a;
fn call<'a>(&'a self, args: T) -> Self::Output<'a>;
}
trait Foo {
type Bar;
fn bar(&self) -> Self::Bar;
}
struct Baz<V>
where
V: ForLifetime,
for<'a> V::Of<'a>: Foo,
{
bar: <V::Of<'static> as Foo>::Bar,
}
impl<V> Baz<V>
where
V: ForLifetime,
for<'a> V::Of<'a>: Foo,
{
fn baz<F>(f: F) -> Self
where
F: for<'a> LendingFn<(), Output<'a> = V::Of<'a>>,
// <V<'a> as Foo>::Bar = <V<'static> as Foo>::Bar
{
let foo = f.call(());
let bar = foo.bar();
Self { bar }
}
}
Basically, I need to extract Bar from the output of a lending function, and that Bar in itself isn't the reason for GAT and will always be the same for any implementation. But I can't use <V<'a> as Foo>::Bar as <V::Of<'static> as Foo>::Bar because it must not be true. I would like to enforce in the where bound that those types end up equal so that code can rely on it.
Some of my attempts to write such a bound resulted in error[E0391]: cycle detected when computing the bounds for type parameter V.
My assumption is that Bar for types like that are considered different by the type system:
#[derive(Clone, Copy)]
struct FooI1<'a>(&'a u8);
impl<'a> Foo for FooI1<'a> {
type Bar = &'a u8;
fn bar(&self) -> Self::Bar {
self.0
}
}
#[derive(Clone, Copy)]
struct FooI2<'a>(&'static u8, std::marker::PhantomData<&'a ()>);
impl<'a> Foo for FooI2<'a> {
type Bar = &'static u8;
fn bar(&self) -> Self::Bar {
self.0
}
}
1 post - 1 participant
🏷️ Rust_feed