Trait method invocation is ambiguous but compiler doesn't error

In the below code, it looks like y.foo() is resolved with y as a [u32], which ends up with Foo<SliceMarker>::foo getting called. But when using the Full Qualified Syntax, I'm also able to force it to resolve y as &[u32] which calls Foo<SizedMarker>::foo. Why is rustc not causing a compiler error here when it looks like there is possible ambiguity in what function should get called, or why is it that it resolves it to the slice version?


pub trait Foo<Marker> {
    fn foo(&self);
}


pub struct SizedMarker();
impl<T: Sized> Foo<SizedMarker> for T {
    fn foo(&self) {
        println!("Foo for Sized T: T = {:#?}", std::any::type_name::<T>()) 
    }
}

pub struct SliceMarker();
impl<'a, T> Foo<SliceMarker> for [T] {
    fn foo(&self) {
        println!("Foo for [T]: [T] = {:#?}", std::any::type_name::<[T]>()) 
    }
}


fn main() {
    let x: i8 = 5;
    x.foo();
    
    let y:&[u32] = &[1, 2, 3];
    y.foo();
    <&[u32] as Foo<SizedMarker>>::foo(&y);
    <[u32] as Foo<SliceMarker>>::foo(&y);
}

Playground: Rust Playground (rust-lang.org)

Method resolution provides a precedence between possible implementations based on the receiver type.

For y: &[u32] the potential receivers in order of consideration are are:

  • &[u32]
    • &&[u32]
    • &mut &[u32]
  • [u32]
    • &[u32] (again)
    • &mut [u32]

The implementation for [T] matches for the first candidate.

I see that, and also that the second candidate matches the implementation for T. But from the linked reference:

If this results in multiple possible candidates, then it is an error, and the receiver must be converted to an appropriate receiver type to make the method call.

Does this part of the reference not mean that since &[u32] and & &[u32] are possible candidates, it should error? Or is it saying that it would error if multiple possible methods were found for the first given type that matches?

This one.

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.