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

compiler suggests use of private trait; fails to suggest the public one. #26454

Closed
pnkfelix opened this issue Jun 20, 2015 · 17 comments
Closed
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-resolve Area: Name/path resolution done by `rustc_resolve` specifically A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-bug Category: This is a bug. 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

@pnkfelix
Copy link
Member

When I do try!(file.metadata()).mtime() without MetadataExt in scope, the compiler suggests that I import std::sys::ext::fs::MetadataExt. It does not suggest any other candidates:

<anon>:17:15: 17:22 help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
<anon>:17:15: 17:22 help: candidate #1: use `std::sys::ext::fs::MetadataExt`
error: aborting due to previous error

But that trait is private, so a use of it will not work.

It turns out that I can do use std::os::unix::fs::MetadataExt; (which I assume is an alternative path to the same trait), and that path is publicly accessible.

playpen demo: https://play.rust-lang.org/?gist=557a8c49fbf072db1033&version=nightly

(This is related to #25358 but is not a dupe of it; that bug is about the suggestion of traits to implement, while this bug is about the suggestion of traits to pull into scope via use)

@pnkfelix pnkfelix added the A-diagnostics Area: Messages for errors, warnings, and lints label Jun 20, 2015
@kaelliu
Copy link

kaelliu commented Jul 9, 2015

i use rust 1.1.0 stable,use your #[cfg(unix)] still not work,have to use std::os::unix::fs::MetadataExt and then works

@pnkfelix
Copy link
Member Author

pnkfelix commented Jul 9, 2015

@kaelliu that is exactly what the linked gist is demonstrating. This bug is not yet fixed (and thus it is still open).

@pnkfelix
Copy link
Member Author

pnkfelix commented Jul 9, 2015

(near dupe of #13065 ; perhaps I will close this in favor of that, though this bug has the advantage that it provides a concrete test case)

Update: they are not exactly the same; this bug is regarding the use item that is suggested in the help for the method resolution error, while #13065 is about the error report for a use itself. Still, fixing #13065 would largely mitigate this issue.

@anowell
Copy link

anowell commented Sep 5, 2015

I was tripped up by this today. Tried using .mode(..) from OpenOptionsExt. Compiler recommended:

candidate #1: use `std::sys::ext::fs::OpenOptionsExt`

Adding that results in

error: trait `OpenOptionsExt` is private

It was non-obvious to discover that I actually needed:

use std::os::unix::fs::OpenOptionsExt;

@diwic
Copy link
Contributor

diwic commented Sep 25, 2015

This does not happen only with traits, as was pointed out on reddit today. It seems to be more of a generic problem that private idents are not translated to their public re-exports.

The reporter got this error:

<std macros>:6:1: 6:32 error: the trait `core::convert::From<regex::re::Error>` is not implemented for the type `PathParseError` [E0277]
<std macros>:6 $ crate:: convert:: From:: from ( err ) ) } } )

The compiler should have said regex::Error instead of regex::re::Error as the latter is private and the former is its public re-export.

@aidanhs
Copy link
Member

aidanhs commented Feb 20, 2017

Minor variation, the compiler will also suggest traits that don't have a possible path at all (i.e. this isn't just the compiler finding a public trait, then choosing the wrong path to it):

fn main() {
    let v: &[usize] = &[1];
    v.slice(0, 1);
}

https://is.gd/l48SNP
suggests I use use std::collections::vec_deque::RingSlices;, which is fully private.

@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 22, 2017
@oyvindln
Copy link
Contributor

https://is.gd/l48SNP
suggests I use use std::collections::vec_deque::RingSlices;, which is fully private.

This looks like it's fixed now.

@estebank
Copy link
Contributor

error[E0599]: no method named `mtime` found for type `std::fs::Metadata` in the current scope
  --> src/main.rs:17:15
   |
17 |     let m = m.mtime();
   |               ^^^^^
   |
   = 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:
   |
1  | use std::os::ext::fs::MetadataExt;
   |
error[E0599]: no method named `slice` found for type `&[usize]` in the current scope
 --> src/main.rs:3:7
  |
3 |     v.slice(0, 1);
  |       ^^^^^

@daboross
Copy link
Contributor

daboross commented Feb 10, 2018

This is still a problem! The trait just changed location.

std::os::ext::fs::MetadataExt is not the real export any more than std::sys::ext::fs::MetadataExt. The real export is std::os::unix::fs::MetadataExt.

See this:

use std::fs;

use std::os::ext::fs::MetadataExt;

fn main() {
    fs::metadata("/usr").unwrap().mtime()
}

results in this:

error[E0433]: failed to resolve. Could not find `ext` in `os`
 --> src/main.rs:3:14
  |
3 | use std::os::ext::fs::MetadataExt;
  |              ^^^ Could not find `ext` in `os`

warning: unused import: `std::os::ext::fs::MetadataExt`
 --> src/main.rs:3:5
  |
3 | use std::os::ext::fs::MetadataExt;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

error[E0599]: no method named `mtime` found for type `std::fs::Metadata` in the current scope
 --> src/main.rs:6:35
  |
6 |     fs::metadata("/usr").unwrap().mtime()
  |                                   ^^^^^
  |
  = 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:
  |
1 | use std::os::ext::fs::MetadataExt;
  |

error: aborting due to 2 previous errors

https://play.rust-lang.org/?gist=0000f47910af132388af4ab3bb5db27a

@estebank estebank reopened this Feb 10, 2018
@nnmm
Copy link

nnmm commented Aug 4, 2019

This problem still exists, see https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2b970cac6b7a498a0d381bbfc01e2c83 for another example (it suggests use image::buffer::ConvertBuffer;) and #57780

@estebank estebank added A-resolve Area: Name/path resolution done by `rustc_resolve` specifically A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` labels Aug 15, 2019
@estebank
Copy link
Contributor

estebank commented Aug 15, 2019

Self-contained repro case:

mod foo {
    mod bar {
        struct X;
    }
}

fn main() { X } // suggests `use foo::bar::X;`
mod foo {
    mod bar {
        struct X;
    }
}

use foo::bar::X; // Complains about `bar` being private

fn main() { X }

@estebank estebank added the D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. label Oct 10, 2019
@gilescope
Copy link
Contributor

gilescope commented Oct 30, 2019

This reminds me a bit about the nicer diagnostics thread: https://internals.rust-lang.org/t/pre-rfc-nicer-types-in-diagnostics/11139/25 - I think there they talk about a type that has been re-exported at a higher level module and that ideally that higher level re-export is the type we should ideally be refering to in error messages (as that's the one the user will be working with in general).

@ianloic
Copy link

ianloic commented Jan 27, 2020

I had this today when I tried to .map a future in some async code it was suggested that I:

help: the following trait is implemented but not in scope; perhaps add a `use` for it:
   |
5  | use futures_util::future::future::FutureExt;
   |

but when I try I get:

error[E0603]: module `future` is private
  --> ../../src/tests/fidl_benchmarks/runner/src/main.rs:16:27
   |
16 |     futures_util::future::future::FutureExt,
   |                           ^^^^^^

@kornelski
Copy link
Contributor

kornelski commented Feb 6, 2020

It also picks up serde's re-export of Option instead of std's Option.

extern crate serde;

fn main() {
    let x: Option<i32> = 1i32;
}

help: try using a variant of the expected enum: serde::__private::Some(1i32)

@comods
Copy link

comods commented Apr 29, 2020

tldr:
list_candidates() from error E0405's source.
detect_private() from error E0603's source.
update errors E0599 and E0603's help to list_candidates().iter().filter(detect_private() == false)

Long:
After following the help for error E0599, I am still receiving the error E0599 and the line that was suppose to fix it has the error E0603.

error[E0599]: no method named `address` found for mutable reference `&mut actix_web_actors::ws::WebsocketContext<ECall>` in the current scope
  --> src/main.rs:64:20
   |
64 |     let addr = ctx.address();
   |                    ^^^^^^^ method not found in `&mut actix_web_actors::ws::WebsocketContext<ECall>`
   |
   = 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:
   |
2  | use actix::actor::AsyncContext;

error[E0603]: module `actor` is private
  --> src/main.rs:11:12
   |
11 | use actix::actor::AsyncContext;
   |            ^^^^^ this module is private
   |

Line 2 | use actix::actor::AsyncContext; should be 2 | use actix::AsyncContext;.
The compiler already has a way to find the public traits, just look at what error [E0405] does:

error[E0405]: cannot find trait `Handler` in this scope
...
help: possible candidates are found in other modules, you can import them into scope
    |
2   | use actix::Handler;
    |
2   | use actix::dev::Handler;
    |
2   | use actix::prelude::Handler;

So error[E0599] and error[E0603] should error[E0405]'s source code to get all candidates but then do not display any private ones.

Meta

rustc --version --verbose:

rustc 1.43.0
binary: rustc
commit-date: 2020-04-20
host: x86_64-pc-windows-gnu
release: 1.43.0
LLVM version: 9.0

Manishearth added a commit to Manishearth/rust that referenced this issue Jun 21, 2020
…rochenkov

Prefer accessible paths in 'use' suggestions

This PR addresses issue rust-lang#26454, where `use` suggestions are made for paths that don't work. For example:

```rust
mod foo {
    mod bar {
        struct X;
    }
}

fn main() { X; } // suggests `use foo::bar::X;`
```
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 21, 2020
…rochenkov

Prefer accessible paths in 'use' suggestions

This PR addresses issue rust-lang#26454, where `use` suggestions are made for paths that don't work. For example:

```rust
mod foo {
    mod bar {
        struct X;
    }
}

fn main() { X; } // suggests `use foo::bar::X;`
```
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 22, 2020
…rochenkov

Prefer accessible paths in 'use' suggestions

This PR addresses issue rust-lang#26454, where `use` suggestions are made for paths that don't work. For example:

```rust
mod foo {
    mod bar {
        struct X;
    }
}

fn main() { X; } // suggests `use foo::bar::X;`
```
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Jun 22, 2020
…rochenkov

Prefer accessible paths in 'use' suggestions

This PR addresses issue rust-lang#26454, where `use` suggestions are made for paths that don't work. For example:

```rust
mod foo {
    mod bar {
        struct X;
    }
}

fn main() { X; } // suggests `use foo::bar::X;`
```
@In-line
Copy link
Contributor

In-line commented Jul 22, 2021

It also picks up serde's re-export of Option instead of std's Option.

extern crate serde;

fn main() {
    let x: Option<i32> = 1i32;
}

help: try using a variant of the expected enum: serde::__private::Some(1i32)

#87349

@estebank
Copy link
Contributor

error[E0599]: no method named `mtime` found for struct `Metadata` in the current scope
  --> src/main.rs:17:15
   |
17 |     let m = m.mtime();
   |               ^^^^^ method not found in `Metadata`
  --> /rustc/0039d739d40a076334e111488946441378d11cd7/library/std/src/os/unix/fs.rs:625:8
   |
   = note: the method is available for `Metadata` here
   |
   = 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:
   |
1  + use std::os::unix::fs::MetadataExt;
   |
error[E0599]: no method named `slice` found for reference `&[usize]` in the current scope
 --> src/main.rs:3:7
  |
3 |     v.slice(0, 1);
  |       ^^^^^ method not found in `&[usize]`
error[E0433]: failed to resolve: could not find `ext` in `os`
 --> src/main.rs:3:14
  |
3 | use std::os::ext::fs::MetadataExt;
  |              ^^^ could not find `ext` in `os`

error[E0599]: no method named `mtime` found for struct `Metadata` in the current scope
 --> src/main.rs:6:35
  |
6 |     fs::metadata("/usr").unwrap().mtime()
  |                                   ^^^^^ method not found in `Metadata`
  |
  = 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:
  |
1 + use std::os::unix::fs::MetadataExt;
  |
error[E0425]: cannot find value `X` in this scope
  --> src/main.rs:12:5
   |
12 |     X;
   |     ^ not found in this scope
   |
help: consider importing one of these items
   |
1  + use crate::foo::X;
   |
1  + use regex_syntax::ast::HexLiteralKind::X;
error[E0308]: mismatched types
 --> src/main.rs:4:26
  |
4 |     let x: Option<i32> = 1i32;
  |            -----------   ^^^^ expected `Option<i32>`, found `i32`
  |            |
  |            expected due to this
  |
  = note: expected enum `std::option::Option<i32>`
             found type `i32`
help: try wrapping the expression in `Some`
  |
4 |     let x: Option<i32> = Some(1i32);
  |                          +++++    +

I believe all of the cases compiled on this thread with repros are properly handled now.

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-resolve Area: Name/path resolution done by `rustc_resolve` specifically A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-bug Category: This is a bug. 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

No branches or pull requests