Misterious behavior of method resolution

I have this playground that I cannot make sense of: Rust Playground

Essentially: I add to all AsRef with V satisfying a marker trait a method len(). There is nothing satisfying the marker trait. Then I take a boxed slice, and I cannot call len() anymore. But there's nothing satisfying the trait, so the additional len() method shouldn't be considered.

What am I missing?

1 Like

I’m not sure how exactly the method resolution rules operate, nor whether it’s even fully documented in the first place, but it’s definitely true that sometimes, especially with generic trait implementations, a method can be considered present as far as the method resolution algorithm is concerned, so that additional auto-(de-)ref (and unsizing) steps may be left out, but then with full trait resolution/checks it turns out, the method wasn’t actually there for the type in question, after all.

It’s just how it is – method resolution is always a bit of a weird corner of Rust, anyways, as it interacts badly e.g. with type inference, too – it’s best to think of it as a bit of a heuristical / best-effort / convenience-feature thing, anyways, and when the compiler complains, you might need to make some method calls more explicit. In this case for example, you could do the previously implicit unsizing coercion into a slice manually and call

fn main() {
    let a = Box::new([1, 2, 3]);
    println!("{}", a[..].len());
}

or

fn main() {
    let a = Box::new([1, 2, 3]);
    println!("{}", a.as_slice().len());
}

to make the code compile again. To be maximally explicit[1], you could skip using method syntax entirely, as in

fn main() {
    let a = Box::new([1, 2, 3]);
    println!("{}", <[_]>::len(&*a));
}

  1. with no more chance of any other in-scope methods or new trait implementations being able to break the code ↩︎

The fact that trait bounds are considered after finding out suitable function, not during that process?

It must be more nuanced than this. Clearly, from the V:Bits, T: AsRef<[V]> part, the T: AsRef<[V]> is considered, but the V: Bits part isn’t. You can see this e.g. by changing the code to something different like

impl<V:Bits, T: AsRef<Box<[V]>>>

Rust Playground

where the len method from BitFieldSliceCore no longer interferes, as Box<[i32; 3]> doesn’t implement AsRef<Box<[_]>> for any type _.

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.