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

Targeted suggestions for specific "no method" errors on standard library types #59450

Closed
dtolnay opened this issue Mar 26, 2019 · 6 comments · Fixed by #120730
Closed

Targeted suggestions for specific "no method" errors on standard library types #59450

dtolnay opened this issue Mar 26, 2019 · 6 comments · Fixed by #120730
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-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@dtolnay
Copy link
Member

dtolnay commented Mar 26, 2019

Rustc currently shows a perfectly reasonable error message when calling a nonexistent method:

use std::collections::BTreeSet;

fn main() {
    let mut set = BTreeSet::new();
    set.push("");
}
error[E0599]: no method named `push` found for type `std::collections::BTreeSet<_>` in the current scope
 --> src/main.rs:5:9
  |
5 |     set.push("");
  |         ^^^^

But for specific frequently encountered cases, it would be great to show a more targeted error that gives the name of the method you almost definitely meant to call, despite not being similar enough to trigger the "did you mean" suggestion.

Candidates would be cases that arise often from refactoring (this applies to BTreeSet::push, which I see every now and then after replacing a Vec with a BTreeSet) or cases of a Rust API being named differently from an equivalent C++ API.

  • BTreeSet::push ⟶ suggest insert
  • Vec::push_back ⟶ suggest push
  • VecDeque::push ⟶ suggest push_back
  • Vec::length, Vec::size ⟶ suggest len
@dtolnay dtolnay added the A-diagnostics Area: Messages for errors, warnings, and lints label Mar 26, 2019
@estebank estebank added the A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. label Mar 26, 2019
@estebank
Copy link
Contributor

Do you think this would be a common enough pattern that it'd be worth creating something like rustc_on_unimplemented but for confusables?

Something like

trait BTreeSet {
    #[rustc_confusables("insert")]
    fn push() {}
}
error[E0599]: no method named `push` found for type `std::collections::BTreeSet<_>` in the current scope
 --> src/main.rs:5:9
  |
5 |     set.push("");
  |         ^^^^ help: you might have meant to use `insert`

@dtolnay
Copy link
Member Author

dtolnay commented Mar 27, 2019

Something similar to rustc_on_unimplemented sounds like it would work! I don't know enough about the diagnostics implementation to know what the other options are.

Bonus points if it is straightforward for a new rustc contributor to add a confusable and corresponding test case.

@estebank estebank added D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 8, 2020
@crlf0710 crlf0710 added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jun 11, 2020
@fmease
Copy link
Member

fmease commented Oct 19, 2022

We could also reuse (abuse?) #[doc(alias = "…")] for this. I think I've seen this mentioned a few times.

@kadiwa4
Copy link
Contributor

kadiwa4 commented Jan 23, 2023

Maybe relevant: #107108 adds doc(alias) support to that error

bors added a commit to rust-lang-ci/rust that referenced this issue Jul 16, 2023
…ons, r=cjgillot

Add `#[rustc_confusables]` attribute to allow targeted "no method" error suggestions on standard library types

After this PR, the standard library developer can annotate methods on e.g. `BTreeSet::push` with `#[rustc_confusables("insert")]`. When the user mistypes `btreeset.push()`, `BTreeSet::insert` will be suggested if there are no other candidates to suggest. This PR lays the foundations for contributors to add `rustc_confusables` annotations to standard library types for targeted suggestions, as specified in rust-lang#59450, or to address cases such as rust-lang#108437.

### Example

Assume `BTreeSet` is the standard library type:

```
// Standard library definition
#![feature(rustc_attrs)]

struct BTreeSet;

impl BTreeSet {
    #[rustc_confusables("push")]
    fn insert(&self) {}
}

// User code
fn main() {
    let x = BTreeSet {};
    x.push();
}
```

A new suggestion (which has lower precedence than suggestions for misspellings and only is shown when there are no misspellings suggestions) will be added to hint the user maybe they intended to write `x.insert()` instead:

```
error[E0599]: no method named `push` found for struct `BTreeSet` in the current scope
  --> test.rs:12:7
   |
3  | struct BTreeSet;
   | --------------- method `push` not found for this struct
...
12 |     x.push();
   |       ^^^^ method not found in `BTreeSet`
   |
help: you might have meant to use `insert`
   |
12 |     x.insert();
   |       ~~~~~~

error: aborting due to previous error
```
@jieyouxu
Copy link
Member

jieyouxu commented Feb 1, 2024

Now that PR #112239 is merged, it should be easy to add #[rustc_confusables(...)] to some of these methods along with some tests.

estebank added a commit to estebank/rust that referenced this issue Feb 7, 2024
Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

rust-lang#59450
estebank added a commit to estebank/rust that referenced this issue Feb 10, 2024
Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

rust-lang#59450
estebank added a commit to estebank/rust that referenced this issue Feb 12, 2024
Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

rust-lang#59450
estebank added a commit to estebank/rust that referenced this issue Feb 13, 2024
Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

rust-lang#59450
@estebank
Copy link
Contributor

I'll have #120730 close this ticket. We can open new ones for specific methods that require more aliases.

oli-obk added a commit to oli-obk/rust that referenced this issue Feb 15, 2024
Provide suggestions through `rustc_confusables` annotations

Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

Fix rust-lang#59450 (we can open subsequent tickets for specific cases).

Fix rust-lang#108437:

```
error[E0599]: `Option<{integer}>` is not an iterator
   --> f101.rs:3:9
    |
3   |     opt.flat_map(|val| Some(val));
    |         ^^^^^^^^ `Option<{integer}>` is not an iterator
    |
   ::: /home/gh-estebank/rust/library/core/src/option.rs:571:1
    |
571 | pub enum Option<T> {
    | ------------------ doesn't satisfy `Option<{integer}>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `Option<{integer}>: Iterator`
            which is required by `&mut Option<{integer}>: Iterator`
help: you might have meant to use `and_then`
    |
3   |     opt.and_then(|val| Some(val));
    |         ~~~~~~~~
```

On type error of method call arguments, look at confusables for suggestion. Fix rust-lang#87212:

```
error[E0308]: mismatched types
    --> f101.rs:8:18
     |
8    |     stuff.append(Thing);
     |           ------ ^^^^^ expected `&mut Vec<Thing>`, found `Thing`
     |           |
     |           arguments to this method are incorrect
     |
     = note: expected mutable reference `&mut Vec<Thing>`
                           found struct `Thing`
note: method defined here
    --> /home/gh-estebank/rust/library/alloc/src/vec/mod.rs:2025:12
     |
2025 |     pub fn append(&mut self, other: &mut Self) {
     |            ^^^^^^
help: you might have meant to use `push`
     |
8    |     stuff.push(Thing);
     |           ~~~~
```
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 17, 2024
Provide suggestions through `rustc_confusables` annotations

Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

Fix rust-lang#59450 (we can open subsequent tickets for specific cases).

Fix rust-lang#108437:

```
error[E0599]: `Option<{integer}>` is not an iterator
   --> f101.rs:3:9
    |
3   |     opt.flat_map(|val| Some(val));
    |         ^^^^^^^^ `Option<{integer}>` is not an iterator
    |
   ::: /home/gh-estebank/rust/library/core/src/option.rs:571:1
    |
571 | pub enum Option<T> {
    | ------------------ doesn't satisfy `Option<{integer}>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `Option<{integer}>: Iterator`
            which is required by `&mut Option<{integer}>: Iterator`
help: you might have meant to use `and_then`
    |
3   |     opt.and_then(|val| Some(val));
    |         ~~~~~~~~
```

On type error of method call arguments, look at confusables for suggestion. Fix rust-lang#87212:

```
error[E0308]: mismatched types
    --> f101.rs:8:18
     |
8    |     stuff.append(Thing);
     |           ------ ^^^^^ expected `&mut Vec<Thing>`, found `Thing`
     |           |
     |           arguments to this method are incorrect
     |
     = note: expected mutable reference `&mut Vec<Thing>`
                           found struct `Thing`
note: method defined here
    --> /home/gh-estebank/rust/library/alloc/src/vec/mod.rs:2025:12
     |
2025 |     pub fn append(&mut self, other: &mut Self) {
     |            ^^^^^^
help: you might have meant to use `push`
     |
8    |     stuff.push(Thing);
     |           ~~~~
```
estebank added a commit to estebank/rust that referenced this issue Feb 22, 2024
Help with common API confusion, like asking for `push` when the data structure really has `append`.

```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/rustc_confusables_std_cases.rs:17:7
   |
LL |     x.size();
   |       ^^^^
   |
help: you might have meant to use `len`
   |
LL |     x.len();
   |       ~~~
help: there is a method with a similar name
   |
LL |     x.resize();
   |       ~~~~~~
```

rust-lang#59450
@bors bors closed this as completed in a28d221 Feb 23, 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 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-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants