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

Diagnostics: suggest alternatives when new constructor is not available #69512

Closed
yoshuawuyts opened this issue Feb 27, 2020 · 7 comments · Fixed by #117006
Closed

Diagnostics: suggest alternatives when new constructor is not available #69512

yoshuawuyts opened this issue Feb 27, 2020 · 7 comments · Fixed by #117006
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

@yoshuawuyts
Copy link
Member

Failing Code

Consider the following code:

use std::net::TcpStream;

fn main() {
   let stream = TcpStream::new();
}

playground

This fails with an error that simply states that new is not available:

Compiling playground v0.0.1 (/playground)
error[E0599]: no function or associated item named `new` found for type `std::net::TcpStream` in the current scope
 --> src/main.rs:4:28
  |
4 |    let stream = TcpStream::new();
  |                            ^^^ function or associated item not found in `std::net::TcpStream`

error: aborting due to previous error

Working Code

The intent is fairly clear: we want to construct a new TcpStream using a method that follows the Rust naming conventions for constructors, but that method is not available. Instead the solution is likely to be either TcpStream::connect or
TcpStream::connect_timeout:

use std::net::TcpStream;

fn main() {
   let stream = TcpStream::connect("localhost:8080");
}

Diagnostics Suggestions

When new is not available it'd be ideal if the compiler could suggest
alternatives. A first heuristic for which methods to suggest be methods on
the same struct that don't take any self params, have Self as their
return type, and aren't implemented through any trait.

For TcpStream this would include TcpStream::connect and
TcpStream::connect_timeout. But not TcpStream::try_clone,
TcpStream::from_raw_fd, TcpStream::from_raw_socket and
std::net::Incoming::next.

I'm not too sure how to structure the help message exactly, but I could
imagine something along these lines might work:

Compiling playground v0.0.1 (/playground)
error[E0599]: no function or associated item named `new` found for type `std::net::TcpStream` in the current scope
 --> src/main.rs:4:28
  |
4 |    let stream = TcpStream::new();
  |                            ^^^ function or associated item not found in `std::net::TcpStream`
  = help: Did you mean to use `std::net::TcpStream::connect` or `std::net::TcpStream::connect_timeout`?

error: aborting due to previous error

cc/ @estebank

@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 27, 2020
@Centril
Copy link
Contributor

Centril commented Feb 27, 2020

Seems like #[doc(alias(...))]es should be added to the standard library to fix this.

@varkor
Copy link
Member

varkor commented Feb 29, 2020

This seems to be the same as #51398.

@Centril
Copy link
Contributor

Centril commented Feb 29, 2020

Closing in favor of that.

@Centril Centril closed this as completed Feb 29, 2020
@yoshuawuyts
Copy link
Member Author

yoshuawuyts commented Mar 2, 2020

Seems like #[doc(alias(...))]es should be added to the standard library to fix this.

@Centril For the example I brought up, how would an #[doc(alias(...))] work? The new method does not exist on TcpStream. So it shouldn't qualify as an alias? Additionally this is intended as an automated mechanism to improve the quality of diagnostics, rather than a manual mechanism (like attributes) which would need to be opted into.

While both cases do touch on improving diagnostics for missing methods, I don't think these are equivalent.

@Centril
Copy link
Contributor

Centril commented Mar 2, 2020

No but TcpStream::connect does exist, so e.g., #[doc(alias(TcpStream::new))] on it could add the information necessary (see e.g. #[doc(alias = "memcpy")] on copy_nonoverlapping) for the compiler to provide the diagnostic.

But I suppose the heuristic you've suggested might work without attributes, although I suspect it would suggest too many false positives, but let's reopen I guess.

@Centril Centril reopened this Mar 2, 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. labels Mar 3, 2020
@estebank
Copy link
Contributor

estebank commented Oct 21, 2023

@yoshuawuyts what do you think of the following?

Screenshot 2023-10-20 at 6 13 57 PM
error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope
   --> tests/ui/resolve/fn-new-doesnt-exist.rs:4:28
    |
4   |    let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found
    |                            ^^^ function or associated item not found in `TcpStream`
    |
note: if you're trying to build a new `TcpStream` consider using one of the following associated functions:
      TcpStream::connect
      TcpStream::connect_timeout
   --> /home/gh-estebank/rust/library/std/src/net/tcp.rs:156:5
    |
156 |     pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
172 |     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

estebank added a commit to estebank/rust that referenced this issue Oct 21, 2023
When we have a resolution error when looking at a fully qualified path
on a type, look for all associated functions on inherent impls that
return `Self` and mention them to the user.

Fix rust-lang#69512.
@yoshuawuyts
Copy link
Member Author

@estebank oh I love it!

estebank added a commit to estebank/rust that referenced this issue Oct 21, 2023
When we have a resolution error when looking at a fully qualified path
on a type, look for all associated functions on inherent impls that
return `Self` and mention them to the user.

Fix rust-lang#69512.
estebank added a commit to estebank/rust that referenced this issue Oct 21, 2023
When we have a resolution error when looking at a fully qualified path
on a type, look for all associated functions on inherent impls that
return `Self` and mention them to the user.

Fix rust-lang#69512.
estebank added a commit to estebank/rust that referenced this issue Oct 23, 2023
When we have a resolution error when looking at a fully qualified path
on a type, look for all associated functions on inherent impls that
return `Self` and mention them to the user.

Fix rust-lang#69512.
estebank added a commit to estebank/rust that referenced this issue Oct 23, 2023
When we have a resolution error when looking at a fully qualified path
on a type, look for all associated functions on inherent impls that
return `Self` and mention them to the user.

Fix rust-lang#69512.
bors added a commit to rust-lang-ci/rust that referenced this issue Nov 7, 2023
When not finding assoc fn on type, look for builder fn

When we have a resolution error when looking at a fully qualified path on a type, look for all associated functions on inherent impls that return `Self` and mention them to the user.

```
error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope
   --> tests/ui/resolve/fn-new-doesnt-exist.rs:4:28
    |
4   |    let stream = TcpStream::new();
    |                            ^^^ function or associated item not found in `TcpStream`
    |
note: if you're trying to build a new `TcpStream` consider using one of the following associated functions:
      TcpStream::connect
      TcpStream::connect_timeout
   --> /home/gh-estebank/rust/library/std/src/net/tcp.rs:156:5
    |
156 |     pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
172 |     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Fix rust-lang#69512.
@bors bors closed this as completed in f926031 Nov 7, 2023
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

Successfully merging a pull request may close this issue.

5 participants