Skip to content

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

New issue

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

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

Already on GitHub? # to your account

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
# for free to join this conversation on GitHub. Already have an account? # 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