rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.36k stars 12.72k forks source link

When calling a function that is actually a method, mention it #102518

Open estebank opened 2 years ago

estebank commented 2 years ago

Given code like cos(3.3); where cos is a method of f64, we currently look for free functions elsewhere in the dependency tree:

error[E0425]: cannot find function `cos` in this scope
 --> src/main.rs:2:13
  |
2 |     let _ = cos(3.3);
  |             ^^^ not found in this scope
  |
help: consider importing this function
  |
1 | use libm::cos;
  |

But we should also check for existence of methods under that name for its sole argument.

error[E0425]: cannot find function `cos` in this scope
 --> src/main.rs:2:13
  |
2 |     let _ = cos(3.3);
  |             ^^^ not found in this scope
  |
help: you might have meant to call method `f64::cos`
  |
2 |     let _ = 3.3.cos();
  |             ~~~~~~~~~
chenyukang commented 2 years ago

This error is reported in the phase of name resolving, for func(obj), seems we need to know the type of obj and then check whether it has func, This seems need to be in type checking phase?

compiler-errors commented 2 years ago

Made some progress:

error[E0425]: cannot find function `len` in this scope
 --> /home/gh-compiler-errors/test2.rs:2:13
  |
2 |     let x = len([1i32]);
  |             ^^^ not found in this scope
  |
help: use the `.` operator to call method `len` on `&[i32]`
  |
2 -     let x = len([1i32]);
2 +     let x = [1i32].len();
  |

@rustbot claim

chenyukang commented 2 years ago

Made some progress:

error[E0425]: cannot find function `len` in this scope
 --> /home/gh-compiler-errors/test2.rs:2:13
  |
2 |     let x = len([1i32]);
  |             ^^^ not found in this scope
  |
help: use the `.` operator to call method `len` on `&[i32]`
  |
2 -     let x = len([1i32]);
2 +     let x = [1i32].len();
  |

@rustbot claim

The code in the issue seems still does not report new suggestion:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=1b4aad8d1252936ed279ddb2f71839fc

compiler-errors commented 2 years ago

This is because in the cos example, we don't suggest turning it into .cos if there was a "import this function" suggestion made -- in this case, there was already the suggestion to import libm::cos.

compiler-errors commented 2 years ago

Not sure if that's actually the behavior we want -- but if we did make that suggestion even if there was a previous import suggestion, I think it would be kinda noisy. Just my opinion though.

Though, it's kinda hard to give the import suggestion a lower priority than the fn->method suggestion, due to the fact that the former happens during name resolution, and the latter happens during type check...

estebank commented 2 years ago

@compiler-errors in that case, lets keep the ticket open for this case in particular. Your PR already improves things quite a bit, we can take some time to think about how to best go about this other case.

Dylan-DPC commented 2 months ago

Current output:

error[E0425]: cannot find function `cos` in this scope
 --> src/main.rs:3:13
  |
3 |     let _ = cos(3.3 as f32);
  |             ^^^ not found in this scope
  |
help: consider importing this function
  |
2 + use libm::cos;
  |

error[E0425]: cannot find function `len` in this scope
 --> src/main.rs:5:13
  |
5 |     let x = len([1i32]);
  |             ^^^ not found in this scope
  |
help: use the `.` operator to call the method `len` on `&[i32]`
  |
5 -     let x = len([1i32]);
5 +     let x = [1i32].len();
  |

For more information about this error, try `rustc --explain E0425`.