Equality constraints break type resolution

Imagine a trait for serialization (AsRaw). I'm trying to make a trait for wrappers that serialize into the same encoding as their inner type. A simplified version:

trait AsRaw {
    type Raw;
}

trait WrapperTrait: AsRaw {
    type Inner: AsRaw<Raw = Self::Raw>;
}

#[repr(u32)]
enum Foo {
    Bar = 1,
    Baz = 2,
}

impl AsRaw for Foo {
    type Raw = u32;
}

fn noop1<P: WrapperTrait>(x: <P::Inner as AsRaw>::Raw) -> <P as AsRaw>::Raw {
    x
}

fn noop2<P: WrapperTrait<Inner = Foo>>(x: <P::Inner as AsRaw>::Raw) -> <P as AsRaw>::Raw {
    // ERROR: mismatched types
    x
}

fn noop3<P: WrapperTrait<Inner = Foo>>(x: <P::Inner as AsRaw>::Raw) -> <P as AsRaw>::Raw {
    noop1::<P>(x)
}

It seems that adding an equality constraint (Inner = Foo) breaks type resolution in noop2() for some reason, but noop1() works just fine. Furthermore, noop3() works (and has the same signature as noop2()), but it seems to require calling a helper function without an equality constraint in order for Rust to realize that the types match.

It seems the compiler is unable to "see" certain bounds on an associated type when it has an equality constraint. Is this a bug or limitation?

1 Like

Funny, something similarly came up just recently in another post. The new trait solver doesn't handle this one though, so I'm not sure how related they actually are. But the compiler seems to be inconsistent or incomplete around normalization/type equality when a concrete type is mixed in with generic projections.

I'd say it's a bug/limitation. You could file an issue about it.

1 Like

Thanks for taking a look. I've opened Equality constraints break type resolution · Issue #134483 · rust-lang/rust · GitHub

1 Like