No warning on duplicate function outside trait implementation

struct Person {
    name: String,
    age: u8,
}

trait HasVoiceBox {
    fn speak(&self);
    fn can_speak(&self) -> bool;
}

impl HasVoiceBox for Person {
    fn speak(&self) {
        println!("Hello, my name is {}.", self.name);
    }
    // This does not run
    fn can_speak(&self) -> bool {
        !matches!(self.age, 0..=2)
    }
}

impl Person {
    // This runs
    fn can_speak(&self) -> bool {
        matches!(self.age, 0..=2)
    }
}

fn main() {
    let person = Person {
        name: String::from("Bob"),
        age: 3,
    };
    /* Returns false, there should be an error or warning of some sort
    on the functions that won't run and unused traits*/
    println!("Can {} speak? {}", person.name, person.can_speak());
}

I think this is a bit of an intentional design decision to give you the ability to override trait methods.

Can you specify the exact rules that would be followed to avoid a false positive? For example, I could imagine it should not fire if the trait is public, or from an external crate. It would also maybe need to check if every implementation overrides it. I don't know how feasible that is, but it sounds hard, and still risky to return false positives.

Atleast there should be an option for pedantic source code check while compiling binaries or libs without pub functions. Maybe this can be implemented in clippy.

1 Like

I could see a clippy lint for when a type both has a trait implementation (provided) method and an inherent implementation with the same signature that isn't just calling the trait method (or the trait impl forwards to the inherent).

A differing signature isn't going to be mixed up by accident, and a forwarding impl isn't too uncommon. If it's an equivalent impl, it probably should be delegated to be implemented in one of the two places, and if it's the same name and signature with differing implementations, that's almost certainly problematic.

1 Like

Not only to override trait methods, but importantly inherent methods are usable without importing the trait, so sometimes people will do this on purpose to make it easier to call things.

(There have been requests to allow "inherent traits" to make this automatic, for example.)

1 Like

The lack of unused trait warning is surprising though. It's a private trait which is implemented but never called.

1 Like