Skip to content

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

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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.

# for free to join this conversation on GitHub. Already have an account? # 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