about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_privacy/lib.rs19
-rw-r--r--src/test/ui/error-codes/E0446.stderr3
-rw-r--r--src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs38
-rw-r--r--src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr30
4 files changed, 84 insertions, 6 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 05ee85e92f5..dafb89be5fd 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 bb5ae494d6c..6c7f3785464 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 00000000000..ec3f48f0347
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> {
+    pub(crate) creature: T,
+}
+
+pub type Helix_pomatia = Shell<Snail>;
+//~^ ERROR crate-visible type `Snail` in public interface
+//~| NOTE can't leak crate-visible type
+pub type Dermochelys_coriacea = Shell<sea::Turtle>;
+//~^ ERROR restricted type `sea::Turtle` in public interface
+//~| NOTE can't leak restricted type
+pub type Testudo_graeca = Shell<Tortoise>;
+//~^ 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 00000000000..b35a12f999c
--- /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<Snail>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<sea::Turtle>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<Tortoise>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0446`.