Prioritization of self over &self trait fns

⚓ Rust    📅 2025-12-07    👤 surdeus    👁️ 2      

surdeus

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.

4 posts - 2 participants

Read full topic

🏷️ Rust_feed