It appears that rust (both compiler and rust-analyzer) picks the trait here because it consumes self.
trait Trait {
fn run(self);
}
struct Test;
impl Test {
fn run(&self, _: f32) {}
}
impl Trait for Test {
fn run(self) {}
}
fn main() {
Test.run(3.0);
// ^^^^^^^^ error here
// Diagnostics:
// 1. expected 0 arguments, found 1 [E0107]
// 2. this method takes 0 arguments but 1 argument was supplied [E0061]
// 3. unexpected argument of type `{float}` [E0061]
// 4. remove the extra argument [E0061]
}
If you swap which one consumes vs takes a reference, it picks the self impl, and you cannot call the trait method instead (Trait::run(&self)). So it does actually seem to be prioritizing, I'm guessing because it doesn't check the next "level" (1 = self, 2 = &self) for another implementation if it finds one.
Is this intended behavior? I personally expected it to complain that the call was ambiguous.
If this is intended, clippy has a bug given this workaround:
(&Test).run(3.0);
// ^^^^^^^
// Diagnostics:
// 1. this expression borrows a value the compiler would automatically borrow
// for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
// `#[warn(clippy::needless_borrow)]` on by default [needless_borrow]
// 2. change this to: `Test` [needless_borrow]
I'll happily create an issue in the rust or clippy repo, but I thought I'd ask here first to figure out exactly what the intended behavior is (so I know where to post) and if this has already been discussed.
I'm on nightly 2025-12-05 and have not tested on stable.