From 717c4817391f61953eed678607168cfea81e3111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 16 Jun 2023 18:09:54 +0000 Subject: [PATCH 1/2] Account for sealed traits in trait bound errors When implementing a public trait with a private super-trait, we now emit a note that the missing bound is not going to be able to be satisfied, and we explain the concept of a sealed trait. --- .../src/traits/error_reporting/suggestions.rs | 26 +++++++++++++++++++ .../sealed-traits/sealed-trait-local.rs | 19 ++++++++++++++ .../sealed-traits/sealed-trait-local.stderr | 16 ++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tests/ui/privacy/sealed-traits/sealed-trait-local.rs create mode 100644 tests/ui/privacy/sealed-traits/sealed-trait-local.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 966c4a7dcf38f..dba6ffc4c96c3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2724,6 +2724,32 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let msg = format!("required by this bound in `{short_item_name}`"); multispan.push_span_label(span, msg); err.span_note(multispan, descr); + if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() + && let ty::ClauseKind::Trait(trait_pred) = clause + { + let def_id = trait_pred.def_id(); + let visible_item = if let Some(local) = def_id.as_local() { + // Check for local traits being reachable. + let vis = &self.tcx.resolutions(()).effective_visibilities; + // Account for non-`pub` traits in the root of the local crate. + let is_locally_reachable = self.tcx.parent(def_id).is_crate_root(); + vis.is_reachable(local) || is_locally_reachable + } else { + // Check for foreign traits being reachable. + self.tcx.visible_parent_map(()).get(&def_id).is_some() + }; + if let DefKind::Trait = tcx.def_kind(item_def_id) && !visible_item { + // FIXME(estebank): extend this to search for all the types that do + // implement this trait and list them. + err.note(format!( + "`{short_item_name}` is a \"sealed trait\", because to implement \ + it you also need to implelement `{}`, which is not accessible; \ + this is usually done to force you to use one of the provided \ + types that already implement it", + with_no_trimmed_paths!(tcx.def_path_str(def_id)), + )); + } + } } else { err.span_note(tcx.def_span(item_def_id), descr); } diff --git a/tests/ui/privacy/sealed-traits/sealed-trait-local.rs b/tests/ui/privacy/sealed-traits/sealed-trait-local.rs new file mode 100644 index 0000000000000..778ddf0f81763 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/sealed-trait-local.rs @@ -0,0 +1,19 @@ +// provide custom privacy error for sealed traits +pub mod a { + pub trait Sealed: self::b::Hidden { + fn foo() {} + } + + struct X; + impl Sealed for X {} + impl self::b::Hidden for X {} + + mod b { + pub trait Hidden {} + } +} + +struct S; +impl a::Sealed for S {} //~ ERROR the trait bound `S: Hidden` is not satisfied + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr b/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr new file mode 100644 index 0000000000000..d1052ce35080c --- /dev/null +++ b/tests/ui/privacy/sealed-traits/sealed-trait-local.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `S: Hidden` is not satisfied + --> $DIR/sealed-trait-local.rs:17:20 + | +LL | impl a::Sealed for S {} + | ^ the trait `Hidden` is not implemented for `S` + | +note: required by a bound in `Sealed` + --> $DIR/sealed-trait-local.rs:3:23 + | +LL | pub trait Sealed: self::b::Hidden { + | ^^^^^^^^^^^^^^^ required by this bound in `Sealed` + = note: `Sealed` is a "sealed trait", because to implement it you also need to implelement `a::b::Hidden`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 7dffd24da5292cc01f18c4ab53f0b96f682fcbe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 16 Jun 2023 19:44:06 +0000 Subject: [PATCH 2/2] Tweak privacy errors to account for reachable items Suggest publicly accessible paths for items in private mod: When encountering a path in non-import situations that are not reachable due to privacy constraints, search for any public re-exports that the user could use instead. Track whether an import suggestion is offering a re-export. When encountering a path with private segments, mention if the item at the final path segment is not publicly accessible at all. Add item visibility metadata to privacy errors from imports: On unreachable imports, record the item that was being imported in order to suggest publicly available re-exports or to be explicit that the item is not available publicly from any path. In order to allow this, we add a mode to `resolve_path` that will not add new privacy errors, nor return early if it encounters one. This way we can get the `Res` corresponding to the final item in the import, which is used in the privacy error machinery. --- compiler/rustc_resolve/src/diagnostics.rs | 92 +++++++++++++------ compiler/rustc_resolve/src/ident.rs | 13 +++ compiler/rustc_resolve/src/imports.rs | 19 ++++ .../rustc_resolve/src/late/diagnostics.rs | 1 + compiler/rustc_resolve/src/lib.rs | 3 + .../ui/extern/extern-crate-visibility.stderr | 8 ++ tests/ui/issues/issue-11680.stderr | 8 +- tests/ui/macros/issue-88228.stderr | 4 +- tests/ui/privacy/export-tag-variant.stderr | 4 +- tests/ui/privacy/privacy-in-paths.stderr | 12 ++- tests/ui/privacy/privacy-ufcs.stderr | 4 +- tests/ui/privacy/privacy1.stderr | 28 +++++- .../sealed-traits/private-trait-non-local.rs | 4 + .../private-trait-non-local.stderr | 12 +++ .../ui/privacy/sealed-traits/private-trait.rs | 10 ++ .../sealed-traits/private-trait.stderr | 17 ++++ .../sealed-traits/re-exported-trait.fixed | 13 +++ .../sealed-traits/re-exported-trait.rs | 13 +++ .../sealed-traits/re-exported-trait.stderr | 19 ++++ .../proc-macro/derive-helper-shadowing.stderr | 4 +- tests/ui/reachable/unreachable-variant.stderr | 2 +- tests/ui/resolve/privacy-enum-ctor.stderr | 8 +- .../stability-in-private-module.stderr | 4 +- .../structs/struct-variant-privacy-xc.stderr | 4 +- .../ui/structs/struct-variant-privacy.stderr | 4 +- .../xcrate/xcrate-private-by-default.stderr | 20 +++- 26 files changed, 276 insertions(+), 54 deletions(-) create mode 100644 tests/ui/privacy/sealed-traits/private-trait-non-local.rs create mode 100644 tests/ui/privacy/sealed-traits/private-trait-non-local.stderr create mode 100644 tests/ui/privacy/sealed-traits/private-trait.rs create mode 100644 tests/ui/privacy/sealed-traits/private-trait.stderr create mode 100644 tests/ui/privacy/sealed-traits/re-exported-trait.fixed create mode 100644 tests/ui/privacy/sealed-traits/re-exported-trait.rs create mode 100644 tests/ui/privacy/sealed-traits/re-exported-trait.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 539b4a1d5e714..d77fb922e844d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -103,6 +103,7 @@ pub(crate) struct ImportSuggestion { pub descr: &'static str, pub path: Path, pub accessible: bool, + pub via_import: bool, /// An extra note that should be issued if this item is suggested pub note: Option, } @@ -140,9 +141,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut reported_spans = FxHashSet::default(); - for error in &self.privacy_errors { + for error in std::mem::take(&mut self.privacy_errors) { if reported_spans.insert(error.dedup_span) { - self.report_privacy_error(error); + self.report_privacy_error(&error); } } } @@ -1256,6 +1257,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path, accessible: child_accessible, note, + via_import, }); } } @@ -1609,8 +1611,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { - let PrivacyError { ident, binding, .. } = *privacy_error; + fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { + let PrivacyError { ident, binding, outermost_res, parent_scope, dedup_span } = + *privacy_error; let res = binding.res(); let ctor_fields_span = self.ctor_fields_span(binding); @@ -1627,6 +1630,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident); err.span_label(ident.span, format!("private {}", descr)); + if let Some((this_res, outer_ident)) = outermost_res { + let import_suggestions = self.lookup_import_candidates( + outer_ident, + this_res.ns().unwrap_or(Namespace::TypeNS), + &parent_scope, + &|res: Res| res == this_res, + ); + let point_to_def = !show_candidates( + self.tcx, + &mut err, + Some(dedup_span.until(outer_ident.span.shrink_to_hi())), + &import_suggestions, + Instead::Yes, + FoundUse::Yes, + DiagnosticMode::Import, + vec![], + "", + ); + // If we suggest importing a public re-export, don't point at the definition. + if point_to_def && ident.span != outer_ident.span { + err.span_label( + outer_ident.span, + format!("{} `{outer_ident}` is not publicly re-exported", this_res.descr()), + ); + } + } + let mut non_exhaustive = None; // If an ADT is foreign and marked as `non_exhaustive`, then that's // probably why we have the privacy error. @@ -2455,7 +2485,8 @@ pub(crate) fn import_candidates( /// When an entity with a given name is not available in scope, we search for /// entities with that name in all crates. This method allows outputting the -/// results of this search in a programmer-friendly way +/// results of this search in a programmer-friendly way. If any entities are +/// found and suggested, returns `true`, otherwise returns `false`. fn show_candidates( tcx: TyCtxt<'_>, err: &mut Diagnostic, @@ -2467,19 +2498,19 @@ fn show_candidates( mode: DiagnosticMode, path: Vec, append: &str, -) { +) -> bool { if candidates.is_empty() { - return; + return false; } - let mut accessible_path_strings: Vec<(String, &str, Option, &Option)> = + let mut accessible_path_strings: Vec<(String, &str, Option, &Option, bool)> = Vec::new(); - let mut inaccessible_path_strings: Vec<(String, &str, Option, &Option)> = + let mut inaccessible_path_strings: Vec<(String, &str, Option, &Option, bool)> = 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, c.did, &c.note)) + .push((path_names_to_string(&c.path), c.descr, c.did, &c.note, c.via_import)) }); // we want consistent results across executions, but candidates are produced @@ -2493,20 +2524,25 @@ fn show_candidates( } if !accessible_path_strings.is_empty() { - let (determiner, kind, name) = if accessible_path_strings.len() == 1 { - ("this", accessible_path_strings[0].1, format!(" `{}`", accessible_path_strings[0].0)) - } else { - ("one of these", "items", String::new()) - }; + let (determiner, kind, name, through) = + if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] { + ( + "this", + *descr, + format!(" `{name}`"), + if *via_import { " through its public re-export" } else { "" }, + ) + } else { + ("one of these", "items", String::new(), "") + }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; let mut msg = if let DiagnosticMode::Pattern = mode { format!( - "if you meant to match on {}{}{}, use the full path in the pattern", - kind, instead, name + "if you meant to match on {kind}{instead}{name}, use the full path in the pattern", ) } else { - format!("consider importing {} {}{}", determiner, kind, instead) + format!("consider importing {determiner} {kind}{through}{instead}") }; for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { @@ -2522,7 +2558,7 @@ fn show_candidates( accessible_path_strings.into_iter().map(|a| a.0), Applicability::MaybeIncorrect, ); - return; + return true; } DiagnosticMode::Import => ("", ""), DiagnosticMode::Normal => ("use ", ";\n"), @@ -2563,6 +2599,7 @@ fn show_candidates( err.help(msg); } + true } else if !matches!(mode, DiagnosticMode::Import) { assert!(!inaccessible_path_strings.is_empty()); @@ -2571,13 +2608,9 @@ fn show_candidates( } else { "" }; - if inaccessible_path_strings.len() == 1 { - let (name, descr, def_id, note) = &inaccessible_path_strings[0]; + if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] { let msg = format!( - "{}{} `{}`{} exists but is inaccessible", - prefix, - descr, - name, + "{prefix}{descr} `{name}`{} exists but is inaccessible", if let DiagnosticMode::Pattern = mode { ", which" } else { "" } ); @@ -2594,11 +2627,11 @@ fn show_candidates( err.note(note.to_string()); } } else { - let (_, descr_first, _, _) = &inaccessible_path_strings[0]; + let (_, descr_first, _, _, _) = &inaccessible_path_strings[0]; let descr = if inaccessible_path_strings .iter() .skip(1) - .all(|(_, descr, _, _)| descr == descr_first) + .all(|(_, descr, _, _, _)| descr == descr_first) { descr_first } else { @@ -2611,7 +2644,7 @@ fn show_candidates( let mut has_colon = false; let mut spans = Vec::new(); - for (name, _, def_id, _) in &inaccessible_path_strings { + for (name, _, def_id, _, _) in &inaccessible_path_strings { if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { let span = tcx.source_span(local_def_id); let span = tcx.sess.source_map().guess_head_span(span); @@ -2637,6 +2670,9 @@ fn show_candidates( err.span_note(multi_span, msg); } + true + } else { + false } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index e29a1626aedd2..e5fa062967ff2 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -893,6 +893,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident, binding, dedup_span: path_span, + outermost_res: None, + parent_scope: *parent_scope, }); } else { return Err((Determined, Weak::No)); @@ -1369,6 +1371,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut allow_super = true; let mut second_binding = None; + // We'll provide more context to the privacy errors later, up to `len`. + let privacy_errors_len = self.privacy_errors.len(); + for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() { debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id); let record_segment_res = |this: &mut Self, res| { @@ -1506,6 +1511,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { second_binding = Some(binding); } let res = binding.res(); + + // Mark every privacy error in this path with the res to the last element. This allows us + // to detect the item the user cares about and either find an alternative import, or tell + // the user it is not accessible. + for error in &mut self.privacy_errors[privacy_errors_len..] { + error.outermost_res = Some((res, ident)); + } + let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 47d8e5993fd82..4445330992004 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -792,6 +792,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; let prev_ambiguity_errors_len = self.ambiguity_errors.len(); let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span); + + // We'll provide more context to the privacy errors later, up to `len`. + let privacy_errors_len = self.privacy_errors.len(); + let path_res = self.resolve_path( &import.module_path, None, @@ -931,6 +935,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => unreachable!(), }; + if self.privacy_errors.len() != privacy_errors_len { + // Get the Res for the last element, so that we can point to alternative ways of + // importing it if available. + let mut path = import.module_path.clone(); + path.push(Segment::from_ident(ident)); + if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = + self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding) + { + let res = module.res().map(|r| (r, ident)); + for error in &mut self.privacy_errors[privacy_errors_len..] { + error.outermost_res = res; + } + } + } + let mut all_ns_err = true; self.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7284b33f09d8e..475772734ff82 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1831,6 +1831,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { path, accessible: true, note: None, + via_import: false, }, )); } else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 82b333fee28b8..8c1cd2f155715 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -689,10 +689,13 @@ impl<'a> NameBindingKind<'a> { } } +#[derive(Debug)] struct PrivacyError<'a> { ident: Ident, binding: &'a NameBinding<'a>, dedup_span: Span, + outermost_res: Option<(Res, Ident)>, + parent_scope: ParentScope<'a>, } #[derive(Debug)] diff --git a/tests/ui/extern/extern-crate-visibility.stderr b/tests/ui/extern/extern-crate-visibility.stderr index 9eeb83ae1a73f..b239727092ae1 100644 --- a/tests/ui/extern/extern-crate-visibility.stderr +++ b/tests/ui/extern/extern-crate-visibility.stderr @@ -9,6 +9,10 @@ note: the crate import `core` is defined here | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ +help: consider importing this module instead + | +LL | use std::cell; + | ~~~~~~~~~ error[E0603]: crate import `core` is private --> $DIR/extern-crate-visibility.rs:9:10 @@ -21,6 +25,10 @@ note: the crate import `core` is defined here | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ +help: consider importing this struct instead + | +LL | std::cell::Cell::new(0); + | ~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-11680.stderr b/tests/ui/issues/issue-11680.stderr index ea224af8ed7e2..5bcf93de811fe 100644 --- a/tests/ui/issues/issue-11680.stderr +++ b/tests/ui/issues/issue-11680.stderr @@ -2,7 +2,9 @@ error[E0603]: enum `Foo` is private --> $DIR/issue-11680.rs:6:21 | LL | let _b = other::Foo::Bar(1); - | ^^^ private enum + | ^^^ --- tuple variant `Bar` is not publicly re-exported + | | + | private enum | note: the enum `Foo` is defined here --> $DIR/auxiliary/issue-11680.rs:1:1 @@ -14,7 +16,9 @@ error[E0603]: enum `Foo` is private --> $DIR/issue-11680.rs:9:27 | LL | let _b = other::test::Foo::Bar(1); - | ^^^ private enum + | ^^^ --- tuple variant `Bar` is not publicly re-exported + | | + | private enum | note: the enum `Foo` is defined here --> $DIR/auxiliary/issue-11680.rs:6:5 diff --git a/tests/ui/macros/issue-88228.stderr b/tests/ui/macros/issue-88228.stderr index 1dbe2b77be2d9..f9d0ac95da756 100644 --- a/tests/ui/macros/issue-88228.stderr +++ b/tests/ui/macros/issue-88228.stderr @@ -4,7 +4,7 @@ error: cannot find macro `bla` in this scope LL | bla!(); | ^^^ | -help: consider importing this macro +help: consider importing this macro through its public re-export | LL + use crate::hey::bla; | @@ -23,7 +23,7 @@ error: cannot find derive macro `Bla` in this scope LL | #[derive(Bla)] | ^^^ | -help: consider importing this derive macro +help: consider importing this derive macro through its public re-export | LL + use crate::hey::Bla; | diff --git a/tests/ui/privacy/export-tag-variant.stderr b/tests/ui/privacy/export-tag-variant.stderr index f73bd454d3592..e8906985e059d 100644 --- a/tests/ui/privacy/export-tag-variant.stderr +++ b/tests/ui/privacy/export-tag-variant.stderr @@ -2,7 +2,9 @@ error[E0603]: enum `Y` is private --> $DIR/export-tag-variant.rs:7:26 | LL | fn main() { let z = foo::Y::Y1; } - | ^ private enum + | ^ -- unit variant `Y1` is not publicly re-exported + | | + | private enum | note: the enum `Y` is defined here --> $DIR/export-tag-variant.rs:4:5 diff --git a/tests/ui/privacy/privacy-in-paths.stderr b/tests/ui/privacy/privacy-in-paths.stderr index 2eb3ebb51c20a..9c3d5e97c62a3 100644 --- a/tests/ui/privacy/privacy-in-paths.stderr +++ b/tests/ui/privacy/privacy-in-paths.stderr @@ -2,7 +2,9 @@ error[E0603]: module `bar` is private --> $DIR/privacy-in-paths.rs:24:16 | LL | ::foo::bar::baz::f(); - | ^^^ private module + | ^^^ - function `f` is not publicly re-exported + | | + | private module | note: the module `bar` is defined here --> $DIR/privacy-in-paths.rs:3:5 @@ -21,12 +23,18 @@ note: the module `bar` is defined here | LL | mod bar { | ^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL | foo::S::f(); + | ~~~~~~ error[E0603]: trait `T` is private --> $DIR/privacy-in-paths.rs:26:23 | LL | <() as ::foo::T>::Assoc::f(); - | ^ private trait + | ^ ----- associated type `Assoc` is not publicly re-exported + | | + | private trait | note: the trait `T` is defined here --> $DIR/privacy-in-paths.rs:8:5 diff --git a/tests/ui/privacy/privacy-ufcs.stderr b/tests/ui/privacy/privacy-ufcs.stderr index e93a458ce6cb6..f45f3d8ec3720 100644 --- a/tests/ui/privacy/privacy-ufcs.stderr +++ b/tests/ui/privacy/privacy-ufcs.stderr @@ -2,7 +2,9 @@ error[E0603]: trait `Bar` is private --> $DIR/privacy-ufcs.rs:12:20 | LL | ::baz(); - | ^^^ private trait + | ^^^ --- associated function `baz` is not publicly re-exported + | | + | private trait | note: the trait `Bar` is defined here --> $DIR/privacy-ufcs.rs:4:5 diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index 6ebed8ee062ef..ca8f242e0bed2 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -50,7 +50,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:104:16 | LL | ::bar::baz::A::foo(); - | ^^^ private module + | ^^^ - struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -62,7 +64,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:105:16 | LL | ::bar::baz::A::bar(); - | ^^^ private module + | ^^^ - struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -74,7 +78,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:107:16 | LL | ::bar::baz::A.foo2(); - | ^^^ private module + | ^^^ - unit struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -86,7 +92,9 @@ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:108:16 | LL | ::bar::baz::A.bar2(); - | ^^^ private module + | ^^^ - unit struct `A` is not publicly re-exported + | | + | private module | note: the module `baz` is defined here --> $DIR/privacy1.rs:50:5 @@ -98,7 +106,9 @@ error[E0603]: trait `B` is private --> $DIR/privacy1.rs:112:16 | LL | ::bar::B::foo(); - | ^ private trait + | ^ --- associated function `foo` is not publicly re-exported + | | + | private trait | note: the trait `B` is defined here --> $DIR/privacy1.rs:40:5 @@ -129,6 +139,10 @@ note: the module `baz` is defined here | LL | mod baz { | ^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL | bar::foo(); + | ~~~~~~~~ error[E0603]: module `baz` is private --> $DIR/privacy1.rs:128:16 @@ -141,6 +155,10 @@ note: the module `baz` is defined here | LL | mod baz { | ^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL | bar::bar(); + | ~~~~~~~~ error[E0603]: trait `B` is private --> $DIR/privacy1.rs:157:17 diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.rs b/tests/ui/privacy/sealed-traits/private-trait-non-local.rs new file mode 100644 index 0000000000000..426f21cc7de2d --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.rs @@ -0,0 +1,4 @@ +extern crate core; +use core::slice::index::private_slice_index::Sealed; //~ ERROR module `index` is private +fn main() { +} diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr new file mode 100644 index 0000000000000..2949997986674 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr @@ -0,0 +1,12 @@ +error[E0603]: module `index` is private + --> $DIR/private-trait-non-local.rs:2:18 + | +LL | use core::slice::index::private_slice_index::Sealed; + | ^^^^^ private module ------ trait `Sealed` is not publicly re-exported + | +note: the module `index` is defined here + --> $SRC_DIR/core/src/slice/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/private-trait.rs b/tests/ui/privacy/sealed-traits/private-trait.rs new file mode 100644 index 0000000000000..bbcbaabfaf433 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait.rs @@ -0,0 +1,10 @@ +pub mod a { + mod b { + pub trait Hidden {} + } +} + +struct S; +impl a::b::Hidden for S {} //~ ERROR module `b` is private + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/private-trait.stderr b/tests/ui/privacy/sealed-traits/private-trait.stderr new file mode 100644 index 0000000000000..c7ec72ff1662c --- /dev/null +++ b/tests/ui/privacy/sealed-traits/private-trait.stderr @@ -0,0 +1,17 @@ +error[E0603]: module `b` is private + --> $DIR/private-trait.rs:8:9 + | +LL | impl a::b::Hidden for S {} + | ^ ------ trait `Hidden` is not publicly re-exported + | | + | private module + | +note: the module `b` is defined here + --> $DIR/private-trait.rs:2:5 + | +LL | mod b { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed new file mode 100644 index 0000000000000..79b6a6516ab26 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +pub mod a { + pub use self::b::Trait; + mod b { + pub trait Trait {} + } +} + +struct S; +impl a::Trait for S {} //~ ERROR module `b` is private + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.rs b/tests/ui/privacy/sealed-traits/re-exported-trait.rs new file mode 100644 index 0000000000000..5f96dfdcbd6c4 --- /dev/null +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.rs @@ -0,0 +1,13 @@ +// run-rustfix + +pub mod a { + pub use self::b::Trait; + mod b { + pub trait Trait {} + } +} + +struct S; +impl a::b::Trait for S {} //~ ERROR module `b` is private + +fn main() {} diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr new file mode 100644 index 0000000000000..b630565d0237f --- /dev/null +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr @@ -0,0 +1,19 @@ +error[E0603]: module `b` is private + --> $DIR/re-exported-trait.rs:11:9 + | +LL | impl a::b::Trait for S {} + | ^ private module + | +note: the module `b` is defined here + --> $DIR/re-exported-trait.rs:5:5 + | +LL | mod b { + | ^^^^^ +help: consider importing this trait through its public re-export instead + | +LL | impl a::Trait for S {} + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/proc-macro/derive-helper-shadowing.stderr b/tests/ui/proc-macro/derive-helper-shadowing.stderr index 7e7870b295127..566c41308468a 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.stderr +++ b/tests/ui/proc-macro/derive-helper-shadowing.stderr @@ -17,7 +17,7 @@ LL | #[derive(GenHelperUse)] | ^^^^^^^^^^^^ | = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this attribute macro +help: consider importing this attribute macro through its public re-export | LL + use empty_helper; | @@ -32,7 +32,7 @@ LL | gen_helper_use!(); | ----------------- in this macro invocation | = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider importing this attribute macro +help: consider importing this attribute macro through its public re-export | LL + use crate::empty_helper; | diff --git a/tests/ui/reachable/unreachable-variant.stderr b/tests/ui/reachable/unreachable-variant.stderr index 6c27a2756f7fb..ca1d2be65ce52 100644 --- a/tests/ui/reachable/unreachable-variant.stderr +++ b/tests/ui/reachable/unreachable-variant.stderr @@ -2,7 +2,7 @@ error[E0603]: module `super_sekrit` is private --> $DIR/unreachable-variant.rs:6:21 | LL | let _x = other::super_sekrit::sooper_sekrit::baz; - | ^^^^^^^^^^^^ private module + | ^^^^^^^^^^^^ private module --- unit variant `baz` is not publicly re-exported | note: the module `super_sekrit` is defined here --> $DIR/auxiliary/unreachable_variant.rs:1:1 diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr index 0bb09090569cb..b10eded015f8c 100644 --- a/tests/ui/resolve/privacy-enum-ctor.stderr +++ b/tests/ui/resolve/privacy-enum-ctor.stderr @@ -228,7 +228,9 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:61:22 | LL | let _: Z = m::n::Z::Fn; - | ^ private enum + | ^ -- tuple variant `Fn` is not publicly re-exported + | | + | private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 @@ -252,7 +254,9 @@ error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:68:22 | LL | let _: Z = m::n::Z::Unit {}; - | ^ private enum + | ^ ---- variant `Unit` is not publicly re-exported + | | + | private enum | note: the enum `Z` is defined here --> $DIR/privacy-enum-ctor.rs:11:9 diff --git a/tests/ui/stability-attribute/stability-in-private-module.stderr b/tests/ui/stability-attribute/stability-in-private-module.stderr index 2f02a24960e01..cc8758714fc92 100644 --- a/tests/ui/stability-attribute/stability-in-private-module.stderr +++ b/tests/ui/stability-attribute/stability-in-private-module.stderr @@ -2,7 +2,9 @@ error[E0603]: module `thread_info` is private --> $DIR/stability-in-private-module.rs:2:26 | LL | let _ = std::thread::thread_info::current_thread(); - | ^^^^^^^^^^^ private module + | ^^^^^^^^^^^ -------------- function `current_thread` is not publicly re-exported + | | + | private module | note: the module `thread_info` is defined here --> $SRC_DIR/std/src/thread/mod.rs:LL:COL diff --git a/tests/ui/structs/struct-variant-privacy-xc.stderr b/tests/ui/structs/struct-variant-privacy-xc.stderr index 1c1caaef8b79d..7a1c84badeff2 100644 --- a/tests/ui/structs/struct-variant-privacy-xc.stderr +++ b/tests/ui/structs/struct-variant-privacy-xc.stderr @@ -14,7 +14,9 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy-xc.rs:7:33 | LL | struct_variant_privacy::Bar::Baz { a: _a } => {} - | ^^^ private enum + | ^^^ --- variant `Baz` is not publicly re-exported + | | + | private enum | note: the enum `Bar` is defined here --> $DIR/auxiliary/struct_variant_privacy.rs:1:1 diff --git a/tests/ui/structs/struct-variant-privacy.stderr b/tests/ui/structs/struct-variant-privacy.stderr index eafd26c716f11..eabd66907f648 100644 --- a/tests/ui/structs/struct-variant-privacy.stderr +++ b/tests/ui/structs/struct-variant-privacy.stderr @@ -14,7 +14,9 @@ error[E0603]: enum `Bar` is private --> $DIR/struct-variant-privacy.rs:10:14 | LL | foo::Bar::Baz { a: _a } => {} - | ^^^ private enum + | ^^^ --- variant `Baz` is not publicly re-exported + | | + | private enum | note: the enum `Bar` is defined here --> $DIR/struct-variant-privacy.rs:2:5 diff --git a/tests/ui/xcrate/xcrate-private-by-default.stderr b/tests/ui/xcrate/xcrate-private-by-default.stderr index 0bdd4002f40ae..25bbbf5f62aa2 100644 --- a/tests/ui/xcrate/xcrate-private-by-default.stderr +++ b/tests/ui/xcrate/xcrate-private-by-default.stderr @@ -62,7 +62,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:35:29 | LL | static_priv_by_default::foo::a; - | ^^^ private module + | ^^^ - static `a` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -74,7 +76,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:37:29 | LL | static_priv_by_default::foo::b; - | ^^^ private module + | ^^^ - function `b` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -86,7 +90,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:39:29 | LL | static_priv_by_default::foo::c; - | ^^^ private module + | ^^^ - unit struct `c` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -98,7 +104,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:41:35 | LL | foo::(); - | ^^^ private module + | ^^^ - enum `d` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1 @@ -110,7 +118,9 @@ error[E0603]: module `foo` is private --> $DIR/xcrate-private-by-default.rs:43:35 | LL | foo::(); - | ^^^ private module + | ^^^ - type alias `e` is not publicly re-exported + | | + | private module | note: the module `foo` is defined here --> $DIR/auxiliary/static_priv_by_default.rs:12:1