diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e75db6f3f0026..4b36196d4669c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -949,7 +949,15 @@ impl<'a> Resolver<'a> { let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); - show_candidates(err, None, &import_suggestions, false, true); + show_candidates( + &self.definitions, + self.session, + err, + None, + &import_suggestions, + false, + true, + ); if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident); @@ -1689,6 +1697,8 @@ fn find_span_immediately_after_crate_name( /// entities with that name in all crates. This method allows outputting the /// results of this search in a programmer-friendly way crate fn show_candidates( + definitions: &rustc_hir::definitions::Definitions, + session: &Session, err: &mut DiagnosticBuilder<'_>, // This is `None` if all placement locations are inside expansions use_placement_span: Option, @@ -1700,22 +1710,22 @@ crate fn show_candidates( return; } - let mut accessible_path_strings: Vec<(String, &str)> = Vec::new(); - let mut inaccessible_path_strings: Vec<(String, &str)> = Vec::new(); + let mut accessible_path_strings: Vec<(String, &str, Option)> = Vec::new(); + let mut inaccessible_path_strings: Vec<(String, &str, Option)> = Vec::new(); candidates.iter().for_each(|c| { (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings }) - .push((path_names_to_string(&c.path), c.descr)) + .push((path_names_to_string(&c.path), c.descr, c.did)) }); // we want consistent results across executions, but candidates are produced // by iterating through a hash map, so make sure they are ordered: for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] { - path_strings.sort(); + path_strings.sort_by(|a, b| a.0.cmp(&b.0)); let core_path_strings = - path_strings.drain_filter(|p| p.starts_with("core::")).collect::>(); + path_strings.drain_filter(|p| p.0.starts_with("core::")).collect::>(); path_strings.extend(core_path_strings); - path_strings.dedup(); + path_strings.dedup_by(|a, b| a.0 == b.0); } if !accessible_path_strings.is_empty() { @@ -1755,19 +1765,56 @@ crate fn show_candidates( } else { assert!(!inaccessible_path_strings.is_empty()); - let (determiner, kind, verb1, verb2) = if inaccessible_path_strings.len() == 1 { - ("this", inaccessible_path_strings[0].1, "exists", "is") + if inaccessible_path_strings.len() == 1 { + let (name, descr, def_id) = &inaccessible_path_strings[0]; + let msg = format!("{} `{}` exists but is inaccessible", descr, name); + + if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { + let span = definitions.def_span(local_def_id); + let span = session.source_map().guess_head_span(span); + let mut multi_span = MultiSpan::from_span(span); + multi_span.push_span_label(span, "not accessible".to_string()); + err.span_note(multi_span, &msg); + } else { + err.note(&msg); + } } else { - ("these", "items", "exist", "are") - }; + let (_, descr_first, _) = &inaccessible_path_strings[0]; + let descr = if inaccessible_path_strings + .iter() + .skip(1) + .all(|(_, descr, _)| descr == descr_first) + { + format!("{}", descr_first) + } else { + "item".to_string() + }; - let mut msg = format!("{} {} {} but {} inaccessible:", determiner, kind, verb1, verb2); + let mut msg = format!("these {}s exist but are inaccessible", descr); + let mut has_colon = false; - for candidate in inaccessible_path_strings { - msg.push('\n'); - msg.push_str(&candidate.0); - } + let mut spans = Vec::new(); + for (name, _, def_id) in &inaccessible_path_strings { + if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { + let span = definitions.def_span(local_def_id); + let span = session.source_map().guess_head_span(span); + spans.push((name, span)); + } else { + if !has_colon { + msg.push(':'); + has_colon = true; + } + msg.push('\n'); + msg.push_str(name); + } + } + + let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect()); + for (name, span) in spans { + multi_span.push_span_label(span, format!("`{}`: not accessible", name)); + } - err.note(&msg); + err.span_note(multi_span, &msg); + } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1cbe8f41d92b0..5ca2392a60ab2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2966,7 +2966,15 @@ impl<'a> Resolver<'a> { (None, false) }; if !candidates.is_empty() { - diagnostics::show_candidates(&mut err, span, &candidates, instead, found_use); + diagnostics::show_candidates( + &self.definitions, + self.session, + &mut err, + span, + &candidates, + instead, + found_use, + ); } else if let Some((span, msg, sugg, appl)) = suggestion { err.span_suggestion(span, msg, sugg, appl); } diff --git a/src/test/ui/imports/glob-resolve1.stderr b/src/test/ui/imports/glob-resolve1.stderr index 3e23c278d669d..3b66a5e315050 100644 --- a/src/test/ui/imports/glob-resolve1.stderr +++ b/src/test/ui/imports/glob-resolve1.stderr @@ -4,8 +4,11 @@ error[E0425]: cannot find function `fpriv` in this scope LL | fpriv(); | ^^^^^ not found in this scope | - = note: this function exists but is inaccessible: - bar::fpriv +note: function `bar::fpriv` exists but is inaccessible + --> $DIR/glob-resolve1.rs:7:5 + | +LL | fn fpriv() {} + | ^^^^^^^^^^ not accessible error[E0425]: cannot find function `epriv` in this scope --> $DIR/glob-resolve1.rs:27:5 @@ -13,8 +16,11 @@ error[E0425]: cannot find function `epriv` in this scope LL | epriv(); | ^^^^^ not found in this scope | - = note: this function exists but is inaccessible: - bar::epriv +note: function `bar::epriv` exists but is inaccessible + --> $DIR/glob-resolve1.rs:9:9 + | +LL | fn epriv(); + | ^^^^^^^^^^^ not accessible error[E0423]: expected value, found enum `B` --> $DIR/glob-resolve1.rs:28:5 @@ -40,8 +46,11 @@ error[E0425]: cannot find value `C` in this scope LL | C; | ^ not found in this scope | - = note: this unit struct exists but is inaccessible: - bar::C +note: unit struct `bar::C` exists but is inaccessible + --> $DIR/glob-resolve1.rs:18:5 + | +LL | struct C; + | ^^^^^^^^^ not accessible error[E0425]: cannot find function `import` in this scope --> $DIR/glob-resolve1.rs:30:5 @@ -63,8 +72,11 @@ LL | pub enum B { LL | foo::(); | ^ help: an enum with a similar name exists: `B` | - = note: this enum exists but is inaccessible: - bar::A +note: enum `bar::A` exists but is inaccessible + --> $DIR/glob-resolve1.rs:11:5 + | +LL | enum A { + | ^^^^^^ not accessible error[E0412]: cannot find type `C` in this scope --> $DIR/glob-resolve1.rs:33:11 @@ -75,8 +87,11 @@ LL | pub enum B { LL | foo::(); | ^ help: an enum with a similar name exists: `B` | - = note: this struct exists but is inaccessible: - bar::C +note: struct `bar::C` exists but is inaccessible + --> $DIR/glob-resolve1.rs:18:5 + | +LL | struct C; + | ^^^^^^^^^ not accessible error[E0412]: cannot find type `D` in this scope --> $DIR/glob-resolve1.rs:34:11 @@ -87,8 +102,11 @@ LL | pub enum B { LL | foo::(); | ^ help: an enum with a similar name exists: `B` | - = note: this type alias exists but is inaccessible: - bar::D +note: type alias `bar::D` exists but is inaccessible + --> $DIR/glob-resolve1.rs:20:5 + | +LL | type D = isize; + | ^^^^^^^^^^^^^^^ not accessible error: aborting due to 8 previous errors diff --git a/src/test/ui/imports/issue-4366-2.stderr b/src/test/ui/imports/issue-4366-2.stderr index 225104d0dde24..4c94634ee60f7 100644 --- a/src/test/ui/imports/issue-4366-2.stderr +++ b/src/test/ui/imports/issue-4366-2.stderr @@ -4,8 +4,11 @@ error[E0412]: cannot find type `Bar` in this scope LL | fn sub() -> Bar { 1 } | ^^^ not found in this scope | - = note: this type alias exists but is inaccessible: - a::b::Bar +note: type alias `a::b::Bar` exists but is inaccessible + --> $DIR/issue-4366-2.rs:11:9 + | +LL | type Bar = isize; + | ^^^^^^^^^^^^^^^^^ not accessible error[E0423]: expected function, found module `foo` --> $DIR/issue-4366-2.rs:25:5 diff --git a/src/test/ui/resolve/issue-42944.stderr b/src/test/ui/resolve/issue-42944.stderr index 1ca7a6d34f782..cad3ccc4a0ef8 100644 --- a/src/test/ui/resolve/issue-42944.stderr +++ b/src/test/ui/resolve/issue-42944.stderr @@ -16,8 +16,11 @@ error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this s LL | Bx(()); | ^^ not found in this scope | - = note: this tuple struct exists but is inaccessible: - foo::Bx +note: tuple struct `foo::Bx` exists but is inaccessible + --> $DIR/issue-42944.rs:2:5 + | +LL | pub struct Bx(()); + | ^^^^^^^^^^^^^^^^^^ not accessible error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-88472.rs b/src/test/ui/resolve/issue-88472.rs index 53cfec5746664..6bf7caeddbfcd 100644 --- a/src/test/ui/resolve/issue-88472.rs +++ b/src/test/ui/resolve/issue-88472.rs @@ -6,6 +6,8 @@ mod a { struct Foo; + //~^ NOTE: struct `a::Foo` exists but is inaccessible + //~| NOTE: not accessible } mod b { @@ -14,14 +16,16 @@ mod b { type Bar = Foo; //~^ ERROR: cannot find type `Foo` in this scope [E0412] //~| NOTE: not found in this scope - //~| NOTE: this struct exists but is inaccessible } mod c { enum Eee {} + //~^ NOTE: these enums exist but are inaccessible + //~| NOTE: `c::Eee`: not accessible mod d { enum Eee {} + //~^ NOTE: `c::d::Eee`: not accessible } } @@ -29,7 +33,6 @@ mod e { type Baz = Eee; //~^ ERROR: cannot find type `Eee` in this scope [E0412] //~| NOTE: not found in this scope - //~| NOTE: these items exist but are inaccessible } fn main() {} diff --git a/src/test/ui/resolve/issue-88472.stderr b/src/test/ui/resolve/issue-88472.stderr index 6846210b302be..8431fc97766f7 100644 --- a/src/test/ui/resolve/issue-88472.stderr +++ b/src/test/ui/resolve/issue-88472.stderr @@ -1,24 +1,32 @@ error[E0412]: cannot find type `Foo` in this scope - --> $DIR/issue-88472.rs:14:16 + --> $DIR/issue-88472.rs:16:16 | LL | type Bar = Foo; | ^^^ not found in this scope | - = note: this struct exists but is inaccessible: - a::Foo +note: struct `a::Foo` exists but is inaccessible + --> $DIR/issue-88472.rs:8:5 + | +LL | struct Foo; + | ^^^^^^^^^^^ not accessible error[E0412]: cannot find type `Eee` in this scope - --> $DIR/issue-88472.rs:29:16 + --> $DIR/issue-88472.rs:33:16 | LL | type Baz = Eee; | ^^^ not found in this scope | - = note: these items exist but are inaccessible: - c::Eee - c::d::Eee +note: these enums exist but are inaccessible + --> $DIR/issue-88472.rs:22:5 + | +LL | enum Eee {} + | ^^^^^^^^ `c::Eee`: not accessible +... +LL | enum Eee {} + | ^^^^^^^^ `c::d::Eee`: not accessible warning: unused import: `crate::a::*` - --> $DIR/issue-88472.rs:12:9 + --> $DIR/issue-88472.rs:14:9 | LL | use crate::a::*; | ^^^^^^^^^^^ diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index e79f953970a43..ff72b0b563ab1 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -171,8 +171,11 @@ LL | pub enum E { LL | let _: Z = m::n::Z; | ^ help: an enum with a similar name exists: `E` | - = note: this enum exists but is inaccessible: - m::Z +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0423]: expected value, found enum `m::n::Z` --> $DIR/privacy-enum-ctor.rs:57:16 @@ -211,8 +214,11 @@ LL | pub enum E { LL | let _: Z = m::n::Z::Fn; | ^ help: an enum with a similar name exists: `E` | - = note: this enum exists but is inaccessible: - m::Z +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:64:12 @@ -223,8 +229,11 @@ LL | pub enum E { LL | let _: Z = m::n::Z::Struct; | ^ help: an enum with a similar name exists: `E` | - = note: this enum exists but is inaccessible: - m::Z +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0423]: expected value, found struct variant `m::n::Z::Struct` --> $DIR/privacy-enum-ctor.rs:64:16 @@ -246,8 +255,11 @@ LL | pub enum E { LL | let _: Z = m::n::Z::Unit {}; | ^ help: an enum with a similar name exists: `E` | - = note: this enum exists but is inaccessible: - m::Z +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:57:22 diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index bf1d6753cc1d0..ada053014ef5e 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -33,8 +33,11 @@ error[E0423]: expected value, found struct `xcrate::S` LL | xcrate::S; | ^^^^^^^^^ constructor is not visible here due to private fields | - = note: this tuple struct exists but is inaccessible: - m::S +note: tuple struct `m::S` exists but is inaccessible + --> $DIR/privacy-struct-ctor.rs:6:5 + | +LL | pub struct S(u8); + | ^^^^^^^^^^^^^^^^^ not accessible error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:18:12 diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index 57b46058777ae..aca08d81163fd 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -66,8 +66,11 @@ error[E0531]: cannot find unit struct, unit variant or constant `Self` in this s LL | mut Self => (), | ^^^^ not found in this scope | - = note: this unit struct exists but is inaccessible: - foo::Self +note: unit struct `foo::Self` exists but is inaccessible + --> $DIR/self_type_keyword.rs:2:3 + | +LL | struct Self; + | ^^^^^^^^^^^^ not accessible error[E0392]: parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12