Narrow impl shadows wider impl?
⚓ Rust 📅 2025-10-04 👤 surdeus 👁️ 6I 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
🏷️ Rust_feed