in which the private/restricted-in-public error messaging gets specific
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.
This commit is contained in:
parent
8d1cbb018e
commit
c2d44b2286
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 | | }
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
Loading…
Reference in New Issue