From c2d44b2286ecf84103e2c66237f578212cd9d8fe Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 30 Jun 2018 22:08:27 -0700 Subject: [PATCH] in which the private/restricted-in-public error messaging gets specific MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit April 2016's Issue #33174 called out the E0446 diagnostics as confusing. While adding the name of the restricted type to the message (548e681f) clarified matters somewhat, Esteban Küber pointed out that we could stand to place a secondary span on the restricted type. Here, we differentiate between crate-visible, truly private, and otherwise restricted types, and place a secondary span specifically on the visibility modifier of the restricted type's declaration (which we can do now that HIR visibilities have spans!). At long last, this resolves #33174. --- src/librustc_privacy/lib.rs | 19 +++++++--- src/test/ui/error-codes/E0446.stderr | 3 ++ ...174-restricted-type-in-public-interface.rs | 38 +++++++++++++++++++ ...restricted-type-in-public-interface.stderr | 30 +++++++++++++++ 4 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/pub/issue-33174-restricted-type-in-public-interface.rs create mode 100644 src/test/ui/pub/issue-33174-restricted-type-in-public-interface.stderr 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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { 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 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 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; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`. -- 2.44.0