diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 05ee85e92f57..dafb89be5fda 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1456,29 +1456,36 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' if let Some(def_id) = ty_def_id { // Non-local means public (private items can't leave their crate, modulo bugs) if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { - let vis = match self.tcx.hir.find(node_id) { + let hir_vis = match self.tcx.hir.find(node_id) { Some(hir::map::NodeItem(item)) => &item.vis, Some(hir::map::NodeForeignItem(item)) => &item.vis, _ => bug!("expected item of foreign item"), }; - let vis = ty::Visibility::from_hir(vis, node_id, self.tcx); + let vis = ty::Visibility::from_hir(hir_vis, node_id, self.tcx); if !vis.is_at_least(self.min_visibility, self.tcx) { self.min_visibility = vis; } if !vis.is_at_least(self.required_visibility, self.tcx) { + let vis_adj = match hir_vis.node { + hir::VisibilityCrate(_) => "crate-visible", + hir::VisibilityRestricted { .. } => "restricted", + _ => "private" + }; + if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { let mut err = struct_span_err!(self.tcx.sess, self.span, E0446, - "private type `{}` in public interface", ty); - err.span_label(self.span, "can't leak private type"); + "{} type `{}` in public interface", vis_adj, ty); + err.span_label(self.span, format!("can't leak {} type", vis_adj)); + err.span_label(hir_vis.span, format!("`{}` declared as {}", ty, vis_adj)); err.emit(); } else { self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, node_id, self.span, - &format!("private type `{}` in public \ - interface (error E0446)", ty)); + &format!("{} type `{}` in public \ + interface (error E0446)", vis_adj, ty)); } } } diff --git a/src/test/ui/error-codes/E0446.stderr b/src/test/ui/error-codes/E0446.stderr index bb5ae494d6c8..6c7f3785464f 100644 --- a/src/test/ui/error-codes/E0446.stderr +++ b/src/test/ui/error-codes/E0446.stderr @@ -1,6 +1,9 @@ error[E0446]: private type `Foo::Bar` in public interface --> $DIR/E0446.rs:14:5 | +LL | struct Bar(u32); + | - `Foo::Bar` declared as private +LL | LL | / pub fn bar() -> Bar { //~ ERROR E0446 LL | | Bar(0) LL | | } diff --git a/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs new file mode 100644 index 000000000000..ec3f48f0347d --- /dev/null +++ b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_camel_case_types)] // genus is always capitalized + +pub(crate) struct Snail; +//~^ NOTE `Snail` declared as crate-visible + +mod sea { + pub(super) struct Turtle; + //~^ NOTE `sea::Turtle` declared as restricted +} + +struct Tortoise; +//~^ NOTE `Tortoise` declared as private + +pub struct Shell { + pub(crate) creature: T, +} + +pub type Helix_pomatia = Shell; +//~^ ERROR crate-visible type `Snail` in public interface +//~| NOTE can't leak crate-visible type +pub type Dermochelys_coriacea = Shell; +//~^ ERROR restricted type `sea::Turtle` in public interface +//~| NOTE can't leak restricted type +pub type Testudo_graeca = Shell; +//~^ ERROR private type `Tortoise` in public interface +//~| NOTE can't leak private type + +fn main() {} diff --git a/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr new file mode 100644 index 000000000000..b35a12f999c8 --- /dev/null +++ b/src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr @@ -0,0 +1,30 @@ +error[E0446]: crate-visible type `Snail` in public interface + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:28:1 + | +LL | pub(crate) struct Snail; + | ---------- `Snail` declared as crate-visible +... +LL | pub type Helix_pomatia = Shell; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-visible type + +error[E0446]: restricted type `sea::Turtle` in public interface + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:31:1 + | +LL | pub(super) struct Turtle; + | ---------- `sea::Turtle` declared as restricted +... +LL | pub type Dermochelys_coriacea = Shell; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak restricted type + +error[E0446]: private type `Tortoise` in public interface + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:34:1 + | +LL | struct Tortoise; + | - `Tortoise` declared as private +... +LL | pub type Testudo_graeca = Shell; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0446`.