Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unintuitive behaviour and missing ambiguous function call error when a trait is implemented dependent on another trait and both traits define a function of the same name #127703

Closed
maia-s opened this issue Jul 13, 2024 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@maia-s
Copy link

maia-s commented Jul 13, 2024

Code

trait A {
    fn one();
}

trait B {
    fn one();
    fn two();
}

struct S;

impl A for S {
    fn one() { println!("A::one"); }
}

impl<T> B for T where T: A {
    fn one() { println!("B::one"); }
    fn two() {
        println!("B::two");
        Self::one();
    }
}

fn main() {
    S::two();
}

Current output

warning: associated function `one` is never used
 --> src/main.rs:6:8
  |
5 | trait B {
  |       - associated function in this trait
6 |     fn one();
  |        ^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: 1 warning emitted

Output when run:

B::two
A::one

Desired output

I expected the call to Self::one in B::two to either call B::one, or generate an ambiguous function call error.

Rationale and extra context

The code compiles, and it looks like B::one will be called from B::two, but A::one is called instead. The only warning is that B::one is unused, which it wouldn't be if it was used by other code. This is confusing and unintuitive.

Other cases

The same thing happens if the functions take a self parameter and are called via self.

Rust Version

% rustc --version --verbose
rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: aarch64-apple-darwin
release: 1.79.0
LLVM version: 18.1.7

% rustc +nightly --version --verbose
rustc 1.81.0-nightly (8337ba918 2024-06-12)
binary: rustc
commit-hash: 8337ba9189de188e2ed417018af2bf17a57d51ac
commit-date: 2024-06-12
host: aarch64-apple-darwin
release: 1.81.0-nightly
LLVM version: 18.1.7

Anything else?

Playground link

It happens on latest stable and nightly.

@maia-s maia-s added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 13, 2024
@eggyal
Copy link
Contributor

eggyal commented Jul 14, 2024

See RFC 2845, #89151 and rust-lang/rfcs#3624.

@maia-s
Copy link
Author

maia-s commented Jul 14, 2024

Thank you. This seems a little different, since there aren't any supertraits here.

@eggyal
Copy link
Contributor

eggyal commented Jul 14, 2024

Ah, quite right - I misread (too quickly!).

The issue here I think comes from the blanket implementation. Since T is a type parameter, functions provided by bounds on it are looked up first. At least for the "other cases" mentioned ("the same thing happens if the functions take a self parameter and are called via self"), this is documented in The Rust Reference chapter on Method-call expressions.

Perhaps in an impl block the trait being implemented should implicitly be added as a trait bound on the Self type. When explicitly added in this case, one gets the expected ambiguity error: playground.

@maia-s
Copy link
Author

maia-s commented Aug 2, 2024

I'm closing this issue in favor of #128509

@maia-s maia-s closed this as not planned Won't fix, can't repro, duplicate, stale Aug 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

2 participants