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

Incorrect error message, “can't call method on ambiguous numeric type {integer} #72498

Open
steffahn opened this issue May 23, 2020 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-enhancement Category: An issue proposing an enhancement or a PR with one. D-papercut Diagnostics: An error or lint that needs small tweaks. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@steffahn
Copy link
Member

steffahn commented May 23, 2020

// use std::ops::AddAssign;

fn foo() {
    1.add_assign(1);
}

Uncomment the use and it compiles, QED.

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0689]: can't call method `add_assign` on ambiguous numeric type `{integer}`
 --> src/lib.rs:4:7
  |
4 |     1.add_assign(1);
  |       ^^^^^^^^^^
  |
help: you must specify a concrete type for this numeric value, like `i32`
  |
4 |     1_i32.add_assign(1);
  |     ^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0689`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.


After following the compiler’s hint, we get:

// use std::ops::AddAssign;

fn foo() {
    1_i32.add_assign(1);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `add_assign` found for type `i32` in the current scope
 --> src/lib.rs:4:11
  |
4 |     1_i32.add_assign(1);
  |           ^^^^^^^^^^ method not found in `i32`
  |
  = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
  |
3 | use std::ops::AddAssign;
  |

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

So, I suppose, at least 2 steps do currently lead to a compiling program.

@rustbot modify labels: T-compiler, A-diagnostics, D-incorrect, C-bug.

@rustbot rustbot added A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-incorrect Diagnostics: A diagnostic that is giving misleading or incorrect information. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 23, 2020
@estebank estebank added A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` D-papercut Diagnostics: An error or lint that needs small tweaks. and removed C-bug Category: This is a bug. D-incorrect Diagnostics: A diagnostic that is giving misleading or incorrect information. labels May 23, 2020
@estebank
Copy link
Contributor

I wouldn't call invalid as, as you point out, the compiler guides you in the right direction. This is acceptable in my opinion, as my rubric for D-incorrect is "the error is pushing you away from a solution". We could extend E0689 to suggest the import.

@steffahn
Copy link
Member Author

Well, while it is not misleading, I thought it is still incorrect. The error reads as if you couldn’t call methods on ambiguous integer types in Rust. Which is very apparently simply not true. The (so-called) “help”, further, very clearly specifies that one must specify the concrete type, and demonstrates how the 1 could be turned into something “like” 1_i32. I just tested it, calling trait methods on other {integer} types works just as well and when there actually is some ambiguity, the compiler resolves it towards i32 and gives an error about the trait being “not implemented for i32”. Perhaps it’s just a lack of creativity on my end, but right now I can’t really think of any situation at all where turning 1 into 1_i32 would suddenly make the compiler happy. Oh wait, now I came up with one but that thing has an entirely different error message.


And a few minutes later, an example where the added _i32 changes the behavior (would that be a bug?)

@steffahn
Copy link
Member Author

And a few minutes later, an example where the added _i32 changes the behavior (would that be a bug?)

Oh, so perhaps that’s what the error message refers to: Not being able to call an ordinary method on the ambiguous integer type, while (which the message doesn’t mention) trait methods still work. (Which is a bizarre situation though, IMO.)

@crlf0710 crlf0710 added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jun 11, 2020
@steffahn
Copy link
Member Author

Coming back to this issue with a lot more Rust experience under the belt, this last behavior seems arguably quite problematic/confusing, as it results in things like:

trait Trait {
    fn abs(self) -> Self;
}

impl Trait for i64 {
    fn abs(self) -> Self {
        2 * self
    }
}

fn main() {
    let x = 42;
    println!("{}", x.abs());
    println!("{}", x.abs());
}

Ouput:

84
42

I’ve opened a separate issue on that (#99405)

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 A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-enhancement Category: An issue proposing an enhancement or a PR with one. D-papercut Diagnostics: An error or lint that needs small tweaks. 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

4 participants