Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 38 additions & 32 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2307,7 +2307,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

self.mention_default_field_values(source, ident, &mut err);

let mut not_publicly_reexported = false;
if let Some((this_res, outer_ident)) = outermost_res {
let mut import_suggestions = self.lookup_import_candidates(
outer_ident,
Expand All @@ -2332,7 +2331,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
);
// If we suggest importing a public re-export, don't point at the definition.
if point_to_def && ident.span != outer_ident.span {
not_publicly_reexported = true;
let label = errors::OuterIdentIsNotPubliclyReexported {
span: outer_ident.span,
outer_ident_descr: this_res.descr(),
Expand Down Expand Up @@ -2408,7 +2406,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let first_binding = decl;
let mut next_binding = Some(decl);
let mut next_ident = ident;
let mut path = vec![];
while let Some(binding) = next_binding {
let name = next_ident;
next_binding = match binding.kind {
Expand All @@ -2428,18 +2425,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};

match binding.kind {
DeclKind::Import { import, .. } => {
for segment in import.module_path.iter().skip(1) {
// Don't include `{{root}}` in suggestions - it's an internal symbol
// that should never be shown to users.
if segment.ident.name != kw::PathRoot {
path.push(segment.ident);
}
}
sugg_paths.push((
path.iter().cloned().chain(std::iter::once(ident)).collect::<Vec<_>>(),
true, // re-export
));
DeclKind::Import { source_decl, import, .. } => {
// Don't include `{{root}}` in suggestions - it's an internal symbol
// that should never be shown to users.
let path = import
.module_path
.iter()
.filter(|seg| seg.ident.name != kw::PathRoot)
.map(|seg| seg.ident.clone())
.chain(std::iter::once(ident))
.collect::<Vec<_>>();
let through_reexport = !matches!(source_decl.kind, DeclKind::Def(_));
sugg_paths.push((path, through_reexport));
}
DeclKind::Def(_) => {}
}
Expand Down Expand Up @@ -2472,25 +2469,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
err.subdiagnostic(note);
}
// We prioritize shorter paths, non-core imports and direct imports over the alternatives.
sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
for (sugg, reexport) in sugg_paths {
if not_publicly_reexported {
// The suggestion replaces `dedup_span` with a path reaching the failing ident.
// That's valid only when
// 1) the failing ident is the imported leaf, otherwise `as` renames and trailing segments
// get dropped, and
// 2) the use isn't nested, otherwise `dedup_span` is one ident in `{...}`.
//
// See issue #156060.
let can_replace_use =
!single_nested && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
Comment thread
mu001999 marked this conversation as resolved.
if can_replace_use {
// We prioritize shorter paths, non-core imports and direct imports over the
// alternatives.
sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
for (sugg, reexport) in sugg_paths {
if sugg.len() <= 1 {
// A single path segment suggestion is wrong. This happens on circular
// imports. `tests/ui/imports/issue-55884-2.rs`
continue;
}
let path = join_path_idents(sugg);
let sugg = if reexport {
errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
} else {
errors::ImportIdent::Directly { span: dedup_span, ident, path }
};
err.subdiagnostic(sugg);
break;
}
if sugg.len() <= 1 {
// A single path segment suggestion is wrong. This happens on circular imports.
// `tests/ui/imports/issue-55884-2.rs`
continue;
}
let path = join_path_idents(sugg);
let sugg = if reexport {
errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
} else {
errors::ImportIdent::Directly { span: dedup_span, ident, path }
};
err.subdiagnostic(sugg);
break;
}

err.emit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ note: ...and refers to the struct `S` which is defined here
|
LL | pub struct S {}
| ^^^^^^^^^^^^ you could import this directly
help: import `S` through the re-export
help: import `S` directly
|
LL - use crate::both::private::S;
LL + use m::S;
LL + use crate::m::S;
|

error[E0603]: struct import `S` is private
Expand All @@ -36,10 +36,10 @@ note: ...and refers to the struct `S` which is defined here
|
LL | pub struct S {}
| ^^^^^^^^^^^^ you could import this directly
help: import `S` through the re-export
help: import `S` directly
|
LL - use crate::both::private::S;
LL + use m::S;
LL + use crate::m::S;
|

error: aborting due to 2 previous errors
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/imports/issue-55884-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ note: ...and refers to the struct `ParseOptions` which is defined here
|
LL | pub struct ParseOptions {}
| ^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly
help: import `ParseOptions` directly
|
LL - pub use parser::ParseOptions;
LL + pub use options::ParseOptions;
|

error: aborting due to 1 previous error

Expand Down
17 changes: 17 additions & 0 deletions tests/ui/imports/private-import-nested-suggestion-156060.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Regression test for #156060.
Comment thread
el-ev marked this conversation as resolved.

mod one {
pub struct One();
}

mod two {
use crate::one::One;
pub struct Two();
}

mod test {
use crate::two::{One, Two};
//~^ ERROR struct import `One` is private [E0603]
}

fn main() {}
20 changes: 20 additions & 0 deletions tests/ui/imports/private-import-nested-suggestion-156060.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0603]: struct import `One` is private
--> $DIR/private-import-nested-suggestion-156060.rs:13:22
|
LL | use crate::two::{One, Two};
| ^^^ private struct import
|
note: the struct import `One` is defined here...
--> $DIR/private-import-nested-suggestion-156060.rs:8:9
|
LL | use crate::one::One;
| ^^^^^^^^^^^^^^^
note: ...and refers to the struct `One` which is defined here
--> $DIR/private-import-nested-suggestion-156060.rs:4:5
|
LL | pub struct One();
| ^^^^^^^^^^^^^^^^^ you could import this directly

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0603`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
error[E0603]: struct import `One` is private
--> $DIR/private-import-suggestion-path-156244.rs:17:12
|
LL | use b::One;
| ^^^ private struct import
|
note: the struct import `One` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:12:20
|
LL | use crate::a::{One, Two};
| ^^^
note: ...and refers to the struct `One` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:7:5
|
LL | pub struct One;
| ^^^^^^^^^^^^^^^ you could import this directly
help: import `One` directly
|
LL - use b::One;
LL + use crate::a::One;
|

error[E0603]: struct import `One` is private
--> $DIR/private-import-suggestion-path-156244.rs:35:20
|
LL | use crate::b::{One, Two};
| ^^^ private struct import
|
note: the struct import `One` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:12:20
|
LL | use crate::a::{One, Two};
| ^^^
note: ...and refers to the struct `One` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:7:5
|
LL | pub struct One;
| ^^^^^^^^^^^^^^^ you could import this directly

error[E0603]: struct import `Two` is private
--> $DIR/private-import-suggestion-path-156244.rs:35:25
|
LL | use crate::b::{One, Two};
| ^^^ private struct import
|
note: the struct import `Two` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:12:25
|
LL | use crate::a::{One, Two};
| ^^^
note: ...and refers to the struct `Two` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:8:5
|
LL | pub struct Two;
| ^^^^^^^^^^^^^^^ you could import this directly

error[E0603]: module import `inner` is private
--> $DIR/private-import-suggestion-path-156244.rs:38:24
|
LL | use crate::rename::inner::Item as Item1;
| ^^^^^ private module import
|
note: the module import `inner` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:31:9
|
LL | use crate::outer::actual as inner;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...and refers to the module `actual` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:25:5
|
LL | pub mod actual {
| ^^^^^^^^^^^^^^ you could import this directly
help: consider importing this struct instead
|
LL - use crate::rename::inner::Item as Item1;
LL + use outer::actual::Item as Item1;
|

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0603`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
error[E0603]: struct import `One` is private
--> $DIR/private-import-suggestion-path-156244.rs:20:19
|
LL | use crate::b::One;
| ^^^ private struct import
|
note: the struct import `One` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:12:20
|
LL | use crate::a::{One, Two};
| ^^^
note: ...and refers to the struct `One` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:7:5
|
LL | pub struct One;
| ^^^^^^^^^^^^^^^ you could import this directly
help: import `One` directly
|
LL - use crate::b::One;
LL + use crate::a::One;
|

error[E0603]: struct import `One` is private
--> $DIR/private-import-suggestion-path-156244.rs:35:20
|
LL | use crate::b::{One, Two};
| ^^^ private struct import
|
note: the struct import `One` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:12:20
|
LL | use crate::a::{One, Two};
| ^^^
note: ...and refers to the struct `One` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:7:5
|
LL | pub struct One;
| ^^^^^^^^^^^^^^^ you could import this directly

error[E0603]: struct import `Two` is private
--> $DIR/private-import-suggestion-path-156244.rs:35:25
|
LL | use crate::b::{One, Two};
| ^^^ private struct import
|
note: the struct import `Two` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:12:25
|
LL | use crate::a::{One, Two};
| ^^^
note: ...and refers to the struct `Two` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:8:5
|
LL | pub struct Two;
| ^^^^^^^^^^^^^^^ you could import this directly

error[E0603]: module import `inner` is private
--> $DIR/private-import-suggestion-path-156244.rs:38:24
|
LL | use crate::rename::inner::Item as Item1;
| ^^^^^ private module import
|
note: the module import `inner` is defined here...
--> $DIR/private-import-suggestion-path-156244.rs:31:9
|
LL | use crate::outer::actual as inner;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...and refers to the module `actual` which is defined here
--> $DIR/private-import-suggestion-path-156244.rs:25:5
|
LL | pub mod actual {
| ^^^^^^^^^^^^^^ you could import this directly
help: consider importing this struct instead
|
LL - use crate::rename::inner::Item as Item1;
LL + use crate::outer::actual::Item as Item1;
|

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0603`.
42 changes: 42 additions & 0 deletions tests/ui/imports/private-import-suggestion-path-156244.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// PR #156244 comment
//@ revisions: edition_2015 edition_2018
//@[edition_2015] edition: 2015
//@[edition_2018] edition: 2018

mod a {
pub struct One;
pub struct Two;
}

mod b {
use crate::a::{One, Two};
}

mod test {
#[cfg(edition_2015)]
use b::One;
//[edition_2015]~^ ERROR struct import `One` is private [E0603]
#[cfg(edition_2018)]
use crate::b::One;
//[edition_2018]~^ ERROR struct import `One` is private [E0603]
}

mod outer {
pub mod actual {
pub struct Item;
}
}

mod rename {
use crate::outer::actual as inner;
}

mod bad {
use crate::b::{One, Two};
//~^ ERROR struct import `One` is private [E0603]
//~| ERROR struct import `Two` is private [E0603]
use crate::rename::inner::Item as Item1;
//~^ ERROR module import `inner` is private [E0603]
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ note: ...and refers to the module `mem` which is defined here
--> $SRC_DIR/std/src/lib.rs:LL:COL
|
= note: you could import this directly
help: import `mem` through the re-export
help: import `mem` directly
|
LL - use foo::mem;
LL + use std::mem;
Expand Down
Loading