Narrow impl shadows wider impl?

⚓ Rust    📅 2025-10-04    👤 surdeus    👁️ 6      

surdeus

I am struggling to get this code to compile:

struct Marker;
struct Input;
struct Output;

trait Coerce<T, U> {
    fn coerce(val: T) -> U;
}

impl<T> Coerce<T, Output> for Marker {
    fn coerce(_val: T) -> Output {
        Output
    }
}

fn test_coerce1<T>(x: T) -> Output
where
    Marker: Coerce<T, Output>,
{
    Marker::coerce(x)
}

fn test_coerce2<U>(x: U) -> Output
// where
//     Marker: Coerce<U, Output>,
{
    test_coerce1(Input)
}

fn test_coerce3<V>(x: V) -> Output
where
    Marker: Coerce<V, Output>,
{
    test_coerce1(Input) // error[E0308]: mismatched types
}

test_coerce2() compiles successfully, so I imagine test_coerce3() should compile as well!

It seems that adding the bound Marker: Coerce<V, Output> bound somehow prevents the compiler from noticing that there already exists a more general implementation: impl<T> Coerce<T, Output> for Marker.

It is trying to substitute V for T, but it SHOULD be substituting Input for T.

Is this a known bug? Is there any way to work around this, other than manually specifying a fully-qualified path? I really would like to avoid using a fully-qualified path since the full type might be extremely complicated (e.g. potentially involving async), or possibly even opaque.

6 posts - 4 participants

Read full topic

🏷️ Rust_feed