Auto merge of #51866 - zackmdavis:hir_making_each_day_of_the_year, r=petrochenkov

add modifier keyword spans to hir::Visibility; improve unreachable-pub, private-no-mangle lint suggestions

#50455 pointed out that the unreachable-pub suggestion for brace-grouped `use`s was bogus; #50476 partially ameliorated this by marking the suggestion as `Applicability::MaybeIncorrect`, but this is the actual fix.

Meanwhile, another application of having spans available in `hir::Visibility` is found in the private-no-mangle lints, where we can now issue a suggestion to use `pub` if the item has a more restricted visibility marker (this seems much less likely to come up in practice than not having any visibility keyword at all, but thoroughness is a virtue). While we're there, we can also add a helpful note if the item does have a `pub` (but triggered the lint presumably because enclosing modules were private).

![hir_vis](https://user-images.githubusercontent.com/1076988/42018064-ca830290-7a65-11e8-9c4c-48bc846f861f.png)

r? @nrc
cc @Manishearth
This commit is contained in:
bors 2018-07-02 03:18:49 +00:00
commit 45935640f0
25 changed files with 345 additions and 189 deletions

View File

@ -1104,7 +1104,7 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
}
pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
if let Visibility::Restricted { ref path, id } = *vis {
if let VisibilityKind::Restricted { ref path, id } = vis.node {
visitor.visit_id(id);
visitor.visit_path(path, id)
}

View File

@ -1296,7 +1296,7 @@ impl<'a> LoweringContext<'a> {
name: keywords::Invalid.name(),
attrs: Default::default(),
node: exist_ty_item_kind,
vis: hir::Visibility::Inherited,
vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
span: exist_ty_span,
};
@ -2797,18 +2797,19 @@ impl<'a> LoweringContext<'a> {
let new_id = this.lower_node_id(new_node_id);
let path = this.lower_path_extra(def, &path, None, ParamMode::Explicit);
let item = hir::ItemUse(P(path), hir::UseKind::Single);
let vis = match vis {
hir::Visibility::Public => hir::Visibility::Public,
hir::Visibility::Crate(sugar) => hir::Visibility::Crate(sugar),
hir::Visibility::Inherited => hir::Visibility::Inherited,
hir::Visibility::Restricted { ref path, id: _ } => {
hir::Visibility::Restricted {
let vis_kind = match vis.node {
hir::VisibilityKind::Public => hir::VisibilityKind::Public,
hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
hir::VisibilityKind::Restricted { ref path, id: _ } => {
hir::VisibilityKind::Restricted {
path: path.clone(),
// We are allocating a new NodeId here
id: this.next_id().node_id,
}
}
};
let vis = respan(vis.span, vis_kind);
this.items.insert(
new_id.node_id,
@ -2869,18 +2870,19 @@ impl<'a> LoweringContext<'a> {
self.lower_use_tree(use_tree, &prefix, new_id, &mut vis, &mut name, &attrs);
self.with_hir_id_owner(new_id, |this| {
let vis = match vis {
hir::Visibility::Public => hir::Visibility::Public,
hir::Visibility::Crate(sugar) => hir::Visibility::Crate(sugar),
hir::Visibility::Inherited => hir::Visibility::Inherited,
hir::Visibility::Restricted { ref path, id: _ } => {
hir::Visibility::Restricted {
let vis_kind = match vis.node {
hir::VisibilityKind::Public => hir::VisibilityKind::Public,
hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
hir::VisibilityKind::Restricted { ref path, id: _ } => {
hir::VisibilityKind::Restricted {
path: path.clone(),
// We are allocating a new NodeId here
id: this.next_id().node_id,
}
}
};
let vis = respan(vis.span, vis_kind);
this.items.insert(
new_id,
@ -2901,7 +2903,7 @@ impl<'a> LoweringContext<'a> {
// the stability of `use a::{};`, to avoid it showing up as
// a re-export by accident when `pub`, e.g. in documentation.
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
*vis = hir::Inherited;
*vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
hir::ItemUse(path, hir::UseKind::ListStem)
}
}
@ -4284,10 +4286,10 @@ impl<'a> LoweringContext<'a> {
v: &Visibility,
explicit_owner: Option<NodeId>,
) -> hir::Visibility {
match v.node {
VisibilityKind::Public => hir::Public,
VisibilityKind::Crate(sugar) => hir::Visibility::Crate(sugar),
VisibilityKind::Restricted { ref path, id, .. } => hir::Visibility::Restricted {
let node = match v.node {
VisibilityKind::Public => hir::VisibilityKind::Public,
VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
VisibilityKind::Restricted { ref path, id } => hir::VisibilityKind::Restricted {
path: P(self.lower_path(id, path, ParamMode::Explicit)),
id: if let Some(owner) = explicit_owner {
self.lower_node_id_with_owner(id, owner).node_id
@ -4295,8 +4297,9 @@ impl<'a> LoweringContext<'a> {
self.lower_node_id(id).node_id
},
},
VisibilityKind::Inherited => hir::Inherited,
}
VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
};
respan(v.span, node)
}
fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {

View File

@ -458,11 +458,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_vis(&mut self, visibility: &'hir Visibility) {
match *visibility {
Visibility::Public |
Visibility::Crate(_) |
Visibility::Inherited => {}
Visibility::Restricted { id, .. } => {
match visibility.node {
VisibilityKind::Public |
VisibilityKind::Crate(_) |
VisibilityKind::Inherited => {}
VisibilityKind::Restricted { id, .. } => {
self.insert(id, NodeVisibility(visibility));
self.with_parent(id, |this| {
intravisit::walk_vis(this, visibility);

View File

@ -1049,7 +1049,9 @@ impl<'hir> Map<'hir> {
Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
Some(EntryGenericParam(_, _, param)) => param.span,
Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
Some(EntryVisibility(_, _, &Spanned {
node: VisibilityKind::Restricted { ref path, .. }, ..
})) => path.span,
Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
Some(EntryLocal(_, _, local)) => local.span,
Some(EntryMacroDef(_, macro_def)) => macro_def.span,

View File

@ -24,7 +24,6 @@ pub use self::Stmt_::*;
pub use self::Ty_::*;
pub use self::UnOp::*;
pub use self::UnsafeSource::*;
pub use self::Visibility::{Public, Inherited};
use hir::def::Def;
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
@ -1929,22 +1928,30 @@ pub struct PolyTraitRef {
pub span: Span,
}
pub type Visibility = Spanned<VisibilityKind>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Visibility {
pub enum VisibilityKind {
Public,
Crate(CrateSugar),
Restricted { path: P<Path>, id: NodeId },
Inherited,
}
impl Visibility {
impl VisibilityKind {
pub fn is_pub(&self) -> bool {
match *self {
VisibilityKind::Public => true,
_ => false
}
}
pub fn is_pub_restricted(&self) -> bool {
use self::Visibility::*;
match self {
&Public |
&Inherited => false,
&Crate(_) |
&Restricted { .. } => true,
match *self {
VisibilityKind::Public |
VisibilityKind::Inherited => false,
VisibilityKind::Crate(..) |
VisibilityKind::Restricted { .. } => true,
}
}
}

View File

@ -12,7 +12,7 @@ pub use self::AnnNode::*;
use rustc_target::spec::abi::Abi;
use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::codemap::{CodeMap, Spanned};
use syntax::parse::ParseSess;
use syntax::parse::lexer::comments;
use syntax::print::pp::{self, Breaks};
@ -839,11 +839,11 @@ impl<'a> State<'a> {
}
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
match *vis {
hir::Public => self.word_nbsp("pub")?,
hir::Visibility::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
hir::Visibility::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
hir::Visibility::Restricted { ref path, .. } => {
match vis.node {
hir::VisibilityKind::Public => self.word_nbsp("pub")?,
hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
hir::VisibilityKind::Restricted { ref path, .. } => {
self.s.word("pub(")?;
if path.segments.len() == 1 &&
path.segments[0].ident.name == keywords::Super.name() {
@ -856,7 +856,7 @@ impl<'a> State<'a> {
}
self.word_nbsp(")")?;
}
hir::Inherited => ()
hir::VisibilityKind::Inherited => ()
}
Ok(())
@ -952,17 +952,21 @@ impl<'a> State<'a> {
self.print_outer_attributes(&ti.attrs)?;
match ti.node {
hir::TraitItemKind::Const(ref ty, default) => {
self.print_associated_const(ti.ident, &ty, default, &hir::Inherited)?;
let vis = Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited };
self.print_associated_const(ti.ident, &ty, default, &vis)?;
}
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
self.print_method_sig(ti.ident, sig, &ti.generics, &hir::Inherited, arg_names,
None)?;
let vis = Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited };
self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None)?;
self.s.word(";")?;
}
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
let vis = Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited };
self.head("")?;
self.print_method_sig(ti.ident, sig, &ti.generics, &hir::Inherited, &[],
Some(body))?;
self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body))?;
self.nbsp()?;
self.end()?; // need to close a box
self.end()?; // need to close a box
@ -2266,7 +2270,8 @@ impl<'a> State<'a> {
},
name,
&generics,
&hir::Inherited,
&Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Inherited },
arg_names,
None)?;
self.end()

View File

@ -710,20 +710,20 @@ impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
PubCrate,
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
hir::Visibility::Public |
hir::Visibility::Inherited => {
hir::VisibilityKind::Public |
hir::VisibilityKind::Inherited => {
// No fields to hash.
}
hir::Visibility::Crate(sugar) => {
hir::VisibilityKind::Crate(sugar) => {
sugar.hash_stable(hcx, hasher);
}
hir::Visibility::Restricted { ref path, id } => {
hir::VisibilityKind::Restricted { ref path, id } => {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
id.hash_stable(hcx, hasher);
});
@ -733,6 +733,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
}
}
impl_stable_hash_for_spanned!(hir::VisibilityKind);
impl<'a> HashStable<StableHashingContext<'a>> for hir::Defaultness {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,

View File

@ -161,7 +161,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
intravisit::walk_item(self, &item);
}
hir::ItemEnum(..) => {
self.inherited_pub_visibility = item.vis == hir::Public;
self.inherited_pub_visibility = item.vis.node.is_pub();
intravisit::walk_item(self, &item);
}
hir::ItemFn(..)
@ -216,7 +216,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
let has_repr_c = self.repr_has_repr_c;
let inherited_pub_visibility = self.inherited_pub_visibility;
let live_fields = def.fields().iter().filter(|f| {
has_repr_c || inherited_pub_visibility || f.vis == hir::Public
has_repr_c || inherited_pub_visibility || f.vis.node.is_pub()
});
self.live_symbols.extend(live_fields.map(|f| f.id));

View File

@ -268,16 +268,16 @@ impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> {
impl Visibility {
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
match *visibility {
hir::Public => Visibility::Public,
hir::Visibility::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
hir::Visibility::Restricted { ref path, .. } => match path.def {
match visibility.node {
hir::VisibilityKind::Public => Visibility::Public,
hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
hir::VisibilityKind::Restricted { ref path, .. } => match path.def {
// If there is no resolution, `resolve` will have already reported an error, so
// assume that the visibility is public to avoid reporting more privacy errors.
Def::Err => Visibility::Public,
def => Visibility::Restricted(def.def_id()),
},
hir::Inherited => {
hir::VisibilityKind::Inherited => {
Visibility::Restricted(tcx.hir.get_module_parent(id))
}
}

View File

@ -397,7 +397,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
hir::ItemUnion(..) => "a union",
hir::ItemTrait(.., ref trait_item_refs) => {
// Issue #11592, traits are always considered exported, even when private.
if it.vis == hir::Visibility::Inherited {
if it.vis.node == hir::VisibilityKind::Inherited {
self.private_traits.insert(it.id);
for trait_item_ref in trait_item_refs {
self.private_traits.insert(trait_item_ref.id.node_id);
@ -414,7 +414,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
if let Some(node_id) = cx.tcx.hir.as_local_node_id(real_trait) {
match cx.tcx.hir.find(node_id) {
Some(hir_map::NodeItem(item)) => {
if item.vis == hir::Visibility::Inherited {
if item.vis.node == hir::VisibilityKind::Inherited {
for impl_item_ref in impl_item_refs {
self.private_traits.insert(impl_item_ref.id.node_id);
}
@ -1182,6 +1182,26 @@ impl LintPass for InvalidNoMangleItems {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
let suggest_export = |vis: &hir::Visibility, err: &mut DiagnosticBuilder| {
let suggestion = match vis.node {
hir::VisibilityKind::Inherited => {
// inherited visibility is empty span at item start; need an extra space
Some("pub ".to_owned())
},
hir::VisibilityKind::Restricted { .. } |
hir::VisibilityKind::Crate(_) => {
Some("pub".to_owned())
},
hir::VisibilityKind::Public => {
err.help("try exporting the item with a `pub use` statement");
None
}
};
if let Some(replacement) = suggestion {
err.span_suggestion(vis.span, "try making it public", replacement);
}
};
match it.node {
hir::ItemFn(.., ref generics, _) => {
if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
@ -1191,12 +1211,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
if !cx.access_levels.is_reachable(it.id) {
let msg = "function is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
let insertion_span = it.span.shrink_to_lo();
if it.vis == hir::Visibility::Inherited {
err.span_suggestion(insertion_span,
"try making it public",
"pub ".to_owned());
}
suggest_export(&it.vis, &mut err);
err.emit();
}
for param in &generics.params {
@ -1219,17 +1234,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
}
hir::ItemStatic(..) => {
if attr::contains_name(&it.attrs, "no_mangle") &&
!cx.access_levels.is_reachable(it.id) {
let msg = "static is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
let insertion_span = it.span.shrink_to_lo();
if it.vis == hir::Visibility::Inherited {
err.span_suggestion(insertion_span,
"try making it public",
"pub ".to_owned());
}
err.emit();
}
!cx.access_levels.is_reachable(it.id) {
let msg = "static is marked #[no_mangle], but not exported";
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
suggest_export(&it.vis, &mut err);
err.emit();
}
}
hir::ItemConst(..) => {
if attr::contains_name(&it.attrs, "no_mangle") {
@ -1391,31 +1401,32 @@ impl LintPass for UnreachablePub {
impl UnreachablePub {
fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
vis: &hir::Visibility, span: Span, exportable: bool,
mut applicability: Applicability) {
if !cx.access_levels.is_reachable(id) && *vis == hir::Visibility::Public {
if span.ctxt().outer().expn_info().is_some() {
applicability = Applicability::MaybeIncorrect;
}
let def_span = cx.tcx.sess.codemap().def_span(span);
let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span,
&format!("unreachable `pub` {}", what));
// We are presuming that visibility is token at start of
// declaration (can be macro variable rather than literal `pub`)
let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' ');
let replacement = if cx.tcx.features().crate_visibility_modifier {
"crate"
} else {
"pub(crate)"
}.to_owned();
err.span_suggestion_with_applicability(pub_span,
"consider restricting its visibility",
replacement,
applicability);
if exportable {
err.help("or consider exporting it for use by other crates");
}
err.emit();
vis: &hir::Visibility, span: Span, exportable: bool) {
let mut applicability = Applicability::MachineApplicable;
match vis.node {
hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => {
if span.ctxt().outer().expn_info().is_some() {
applicability = Applicability::MaybeIncorrect;
}
let def_span = cx.tcx.sess.codemap().def_span(span);
let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span,
&format!("unreachable `pub` {}", what));
let replacement = if cx.tcx.features().crate_visibility_modifier {
"crate"
} else {
"pub(crate)"
}.to_owned();
err.span_suggestion_with_applicability(vis.span,
"consider restricting its visibility",
replacement,
applicability);
if exportable {
err.help("or consider exporting it for use by other crates");
}
err.emit();
},
_ => {}
}
}
}
@ -1423,28 +1434,20 @@ impl UnreachablePub {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
let applicability = match item.node {
// suggestion span-manipulation is inadequate for `pub use
// module::{item}` (Issue #50455)
hir::ItemUse(..) => Applicability::MaybeIncorrect,
_ => Applicability::MachineApplicable,
};
self.perform_lint(cx, "item", item.id, &item.vis, item.span, true, applicability);
self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
}
fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) {
self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis,
foreign_item.span, true, Applicability::MachineApplicable);
foreign_item.span, true);
}
fn check_struct_field(&mut self, cx: &LateContext, field: &hir::StructField) {
self.perform_lint(cx, "field", field.id, &field.vis, field.span, false,
Applicability::MachineApplicable);
self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
}
fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false,
Applicability::MachineApplicable);
self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
}
}

View File

@ -40,6 +40,7 @@ use rustc_data_structures::sync::Lrc;
use std::u32;
use syntax::ast::{self, CRATE_NODE_ID};
use syntax::attr;
use syntax::codemap::Spanned;
use syntax::symbol::keywords;
use syntax_pos::{self, hygiene, FileName, FileMap, Span};
@ -319,9 +320,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_info_for_items(&mut self) -> Index {
let krate = self.tcx.hir.krate();
let mut index = IndexBuilder::new(self);
let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
index.record(DefId::local(CRATE_DEF_INDEX),
IsolatedEncoder::encode_info_for_mod,
FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &vis)));
let mut visitor = EncodeVisitor { index: index };
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
for macro_def in &krate.exported_macros {

View File

@ -61,7 +61,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> {
NestedVisitorMap::All(&self.tcx.hir)
}
fn visit_vis(&mut self, vis: &'tcx hir::Visibility) {
self.has_pub_restricted = self.has_pub_restricted || vis.is_pub_restricted();
self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted();
}
}
@ -162,7 +162,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
hir::ItemExistential(..) |
hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
if item.vis == hir::Public { self.prev_level } else { None }
if item.vis.node.is_pub() { self.prev_level } else { None }
}
};
@ -181,7 +181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
}
hir::ItemImpl(.., None, _, ref impl_item_refs) => {
for impl_item_ref in impl_item_refs {
if impl_item_ref.vis == hir::Public {
if impl_item_ref.vis.node.is_pub() {
self.update(impl_item_ref.id.node_id, item_level);
}
}
@ -201,14 +201,14 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
self.update(def.id(), item_level);
}
for field in def.fields() {
if field.vis == hir::Public {
if field.vis.node.is_pub() {
self.update(field.id, item_level);
}
}
}
hir::ItemForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
if foreign_item.vis == hir::Public {
if foreign_item.vis.node.is_pub() {
self.update(foreign_item.id, item_level);
}
}
@ -358,7 +358,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
let module_did = ty::DefIdTree::parent(self.tcx, self.tcx.hir.local_def_id(md.id)).unwrap();
let mut module_id = self.tcx.hir.as_local_node_id(module_did).unwrap();
let level = if md.vis == hir::Public { self.get(module_id) } else { None };
let level = if md.vis.node.is_pub() { self.get(module_id) } else { None };
let level = self.update(md.id, level);
if level.is_none() {
return
@ -1028,7 +1028,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
// .. and it corresponds to a private type in the AST (this returns
// None for type parameters)
match self.tcx.hir.find(node_id) {
Some(hir::map::NodeItem(ref item)) => item.vis != hir::Public,
Some(hir::map::NodeItem(ref item)) => !item.vis.node.is_pub(),
Some(_) | None => false,
}
} else {
@ -1051,7 +1051,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn item_is_public(&self, id: &ast::NodeId, vis: &hir::Visibility) -> bool {
self.access_levels.is_reachable(*id) || *vis == hir::Public
self.access_levels.is_reachable(*id) || vis.node.is_pub()
}
}
@ -1322,7 +1322,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
if s.vis == hir::Public || self.in_variant {
if s.vis.node.is_pub() || self.in_variant {
intravisit::walk_struct_field(self, s);
}
}
@ -1461,29 +1461,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::VisibilityKind::Crate(_) => "crate-visible",
hir::VisibilityKind::Restricted { .. } => "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));
}
}
}

View File

@ -55,6 +55,7 @@ use std::fs::File;
use std::path::{Path, PathBuf};
use syntax::ast::{self, Attribute, NodeId, PatKind};
use syntax::codemap::Spanned;
use syntax::parse::lexer::comments::strip_doc_comment_decoration;
use syntax::parse::token;
use syntax::print::pprust;
@ -631,7 +632,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
node: hir::ItemUse(ref path, _),
..
}) |
Node::NodeVisibility(&hir::Visibility::Restricted { ref path, .. }) => path.def,
Node::NodeVisibility(&Spanned {
node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.def,
Node::NodeExpr(&hir::Expr {
node: hir::ExprStruct(ref qpath, ..),

View File

@ -39,7 +39,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if item.vis == hir::Public || item.span.is_dummy() {
if item.vis.node.is_pub() || item.span.is_dummy() {
return;
}
if let hir::ItemUse(ref path, _) = item.node {
@ -214,4 +214,3 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
}
}

View File

@ -286,7 +286,7 @@ impl Clean<ExternalCrate> for CrateNum {
as_primitive(Def::Mod(cx.tcx.hir.local_def_id(id.id)))
}
hir::ItemUse(ref path, hir::UseKind::Single)
if item.vis == hir::Visibility::Public => {
if item.vis.node.is_pub() => {
as_primitive(path.def).map(|(_, prim, attrs)| {
// Pretend the primitive is local.
(cx.tcx.hir.local_def_id(id.id), prim, attrs)
@ -328,7 +328,7 @@ impl Clean<ExternalCrate> for CrateNum {
as_keyword(Def::Mod(cx.tcx.hir.local_def_id(id.id)))
}
hir::ItemUse(ref path, hir::UseKind::Single)
if item.vis == hir::Visibility::Public => {
if item.vis.node.is_pub() => {
as_keyword(path.def).map(|(_, prim, attrs)| {
(cx.tcx.hir.local_def_id(id.id), prim, attrs)
})
@ -3225,11 +3225,11 @@ pub enum Visibility {
impl Clean<Option<Visibility>> for hir::Visibility {
fn clean(&self, cx: &DocContext) -> Option<Visibility> {
Some(match *self {
hir::Visibility::Public => Visibility::Public,
hir::Visibility::Inherited => Visibility::Inherited,
hir::Visibility::Crate(_) => Visibility::Crate,
hir::Visibility::Restricted { ref path, .. } => {
Some(match self.node {
hir::VisibilityKind::Public => Visibility::Public,
hir::VisibilityKind::Inherited => Visibility::Inherited,
hir::VisibilityKind::Crate(_) => Visibility::Crate,
hir::VisibilityKind::Restricted { ref path, .. } => {
let path = path.clean(cx);
let did = register_def(cx, path.def);
Visibility::Restricted(did, path)
@ -3932,7 +3932,7 @@ impl Clean<Vec<Item>> for doctree::Import {
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
let denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
a.name() == "doc" && match a.meta_item_list() {
Some(l) => attr::list_contains_name(&l, "no_inline") ||
attr::list_contains_name(&l, "hidden"),

View File

@ -17,6 +17,7 @@ use syntax::ast;
use syntax::ast::{Name, NodeId};
use syntax::attr;
use syntax::ptr::P;
use syntax::codemap::Spanned;
use syntax_pos::{self, Span};
use rustc::hir;
@ -53,7 +54,7 @@ impl Module {
Module {
name : name,
id: ast::CRATE_NODE_ID,
vis: hir::Inherited,
vis: Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Inherited },
stab: None,
depr: None,
where_outer: syntax_pos::DUMMY_SP,

View File

@ -15,7 +15,8 @@ use std::mem;
use syntax::ast;
use syntax::attr;
use syntax_pos::Span;
use syntax::codemap::Spanned;
use syntax_pos::{self, Span};
use rustc::hir::map as hir_map;
use rustc::hir::def::Def;
@ -94,7 +95,8 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
self.module = self.visit_mod_contents(krate.span,
krate.attrs.clone(),
hir::Public,
Spanned { span: syntax_pos::DUMMY_SP,
node: hir::VisibilityKind::Public },
ast::CRATE_NODE_ID,
&krate.module,
None);
@ -204,7 +206,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
om.id = id;
// Keep track of if there were any private modules in the path.
let orig_inside_public_path = self.inside_public_path;
self.inside_public_path &= vis == hir::Public;
self.inside_public_path &= vis.node.is_pub();
for i in &m.item_ids {
let item = self.cx.tcx.hir.expect_item(i.id);
self.visit_item(item, None, &mut om);
@ -376,7 +378,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
debug!("Visiting item {:?}", item);
let name = renamed.unwrap_or(item.name);
if item.vis == hir::Public {
if item.vis.node.is_pub() {
let def_id = self.cx.tcx.hir.local_def_id(item.id);
self.store_path(def_id);
}
@ -387,14 +389,14 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
om.foreigns.push(if self.inlining {
hir::ForeignMod {
abi: fm.abi,
items: fm.items.iter().filter(|i| i.vis == hir::Public).cloned().collect(),
items: fm.items.iter().filter(|i| i.vis.node.is_pub()).cloned().collect(),
}
} else {
fm.clone()
});
}
// If we're inlining, skip private items.
_ if self.inlining && item.vis != hir::Public => {}
_ if self.inlining && !item.vis.node.is_pub() => {}
hir::ItemGlobalAsm(..) => {}
hir::ItemExternCrate(orig_name) => {
let def_id = self.cx.tcx.hir.local_def_id(item.id);
@ -414,7 +416,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
// If there was a private module in the current path then don't bother inlining
// anything as it will probably be stripped anyway.
if item.vis == hir::Public && self.inside_public_path {
if item.vis.node.is_pub() && self.inside_public_path {
let please_inline = item.attrs.iter().any(|item| {
match item.meta_item_list() {
Some(ref list) if item.check_name("doc") => {

View File

@ -6032,7 +6032,10 @@ impl<'a> Parser<'a> {
}
if !self.eat_keyword(keywords::Pub) {
return Ok(respan(self.prev_span, VisibilityKind::Inherited))
// We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
// keyword to grab a span from for inherited visibility; an empty span at the
// beginning of the current token would seem to be the "Schelling span".
return Ok(respan(self.span.shrink_to_lo(), VisibilityKind::Inherited))
}
let lo = self.prev_span;

View File

@ -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 | | }

View File

@ -13,18 +13,22 @@
#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
#![feature(no_debug)]
#[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
#[no_mangle] static SHENZHOU: usize = 1;
//~^ WARN static is marked #[no_mangle]
#[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
//~| HELP try making it public
#[no_mangle] const DISCOVERY: usize = 1;
//~^ ERROR const items should never be #[no_mangle]
//~| HELP try a static value
#[no_mangle] // should suggest removal (generics can't be no-mangle)
#[no_mangle]
//~^ HELP remove this attribute
pub fn defiant<T>(_t: T) {}
//~^ WARN functions generic over types must be mangled
#[no_mangle]
fn rio_grande() {} // should suggest `pub`
fn rio_grande() {}
//~^ WARN function is marked
//~| HELP try making it public
mod badlands {
// The private-no-mangle lints shouldn't suggest inserting `pub` when the
@ -32,8 +36,18 @@ mod badlands {
// private module). (Issue #47383)
#[no_mangle] pub static DAUNTLESS: bool = true;
//~^ WARN static is marked
//~| HELP try exporting the item with a `pub use` statement
#[no_mangle] pub fn val_jean() {}
//~^ WARN function is marked
//~| HELP try exporting the item with a `pub use` statement
// ... but we can suggest just-`pub` instead of restricted
#[no_mangle] pub(crate) static VETAR: bool = true;
//~^ WARN static is marked
//~| HELP try making it public
#[no_mangle] pub(crate) fn crossfield() {}
//~^ WARN function is marked
//~| HELP try making it public
}
struct Equinox {
@ -42,20 +56,26 @@ struct Equinox {
#[no_debug] // should suggest removal of deprecated attribute
//~^ WARN deprecated
//~| HELP remove this attribute
fn main() {
while true { // should suggest `loop`
while true {
//~^ WARN denote infinite loops
let mut a = (1); // should suggest no `mut`, no parens
//~| HELP use `loop`
let mut a = (1);
//~^ WARN does not need to be mutable
//~| HELP remove this `mut`
//~| WARN unnecessary parentheses
//~| HELP remove these parentheses
// the line after `mut` has a `\t` at the beginning, this is on purpose
let mut
b = 1;
//~^^ WARN does not need to be mutable
//~| HELP remove this `mut`
let d = Equinox { warp_factor: 9.975 };
match d {
Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
Equinox { warp_factor: warp_factor } => {}
//~^ WARN this pattern is redundant
//~| HELP remove this
}
println!("{} {}", a, b);
}

View File

@ -1,7 +1,7 @@
warning: unnecessary parentheses around assigned value
--> $DIR/suggestions.rs:48:21
--> $DIR/suggestions.rs:64:21
|
LL | let mut a = (1); // should suggest no `mut`, no parens
LL | let mut a = (1);
| ^^^ help: remove these parentheses
|
note: lint level defined here
@ -11,7 +11,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
| ^^^^^^^^^^^^^
warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
--> $DIR/suggestions.rs:43:1
--> $DIR/suggestions.rs:57:1
|
LL | #[no_debug] // should suggest removal of deprecated attribute
| ^^^^^^^^^^^ help: remove this attribute
@ -19,9 +19,9 @@ LL | #[no_debug] // should suggest removal of deprecated attribute
= note: #[warn(deprecated)] on by default
warning: variable does not need to be mutable
--> $DIR/suggestions.rs:48:13
--> $DIR/suggestions.rs:64:13
|
LL | let mut a = (1); // should suggest no `mut`, no parens
LL | let mut a = (1);
| ----^
| |
| help: remove this `mut`
@ -33,7 +33,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
| ^^^^^^^^^^
warning: variable does not need to be mutable
--> $DIR/suggestions.rs:52:13
--> $DIR/suggestions.rs:70:13
|
LL | let mut
| _____________^
@ -47,7 +47,7 @@ LL | || b = 1;
warning: static is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:16:14
|
LL | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
LL | #[no_mangle] static SHENZHOU: usize = 1;
| -^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| help: try making it public: `pub`
@ -55,9 +55,9 @@ LL | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
= note: #[warn(private_no_mangle_statics)] on by default
error: const items should never be #[no_mangle]
--> $DIR/suggestions.rs:18:14
--> $DIR/suggestions.rs:19:14
|
LL | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
LL | #[no_mangle] const DISCOVERY: usize = 1;
| -----^^^^^^^^^^^^^^^^^^^^^^
| |
| help: try a static value: `pub static`
@ -65,19 +65,20 @@ LL | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rat
= note: #[deny(no_mangle_const_items)] on by default
warning: functions generic over types must be mangled
--> $DIR/suggestions.rs:22:1
--> $DIR/suggestions.rs:25:1
|
LL | #[no_mangle] // should suggest removal (generics can't be no-mangle)
LL | #[no_mangle]
| ------------ help: remove this attribute
LL | //~^ HELP remove this attribute
LL | pub fn defiant<T>(_t: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(no_mangle_generic_items)] on by default
warning: function is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:26:1
--> $DIR/suggestions.rs:29:1
|
LL | fn rio_grande() {} // should suggest `pub`
LL | fn rio_grande() {}
| -^^^^^^^^^^^^^^^^^
| |
| help: try making it public: `pub`
@ -85,29 +86,49 @@ LL | fn rio_grande() {} // should suggest `pub`
= note: #[warn(private_no_mangle_fns)] on by default
warning: static is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:33:18
--> $DIR/suggestions.rs:37:18
|
LL | #[no_mangle] pub static DAUNTLESS: bool = true;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try exporting the item with a `pub use` statement
warning: function is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:35:18
--> $DIR/suggestions.rs:40:18
|
LL | #[no_mangle] pub fn val_jean() {}
| ^^^^^^^^^^^^^^^^^^^^
|
= help: try exporting the item with a `pub use` statement
warning: static is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:45:18
|
LL | #[no_mangle] pub(crate) static VETAR: bool = true;
| ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| help: try making it public: `pub`
warning: function is marked #[no_mangle], but not exported
--> $DIR/suggestions.rs:48:18
|
LL | #[no_mangle] pub(crate) fn crossfield() {}
| ----------^^^^^^^^^^^^^^^^^^^
| |
| help: try making it public: `pub`
warning: denote infinite loops with `loop { ... }`
--> $DIR/suggestions.rs:46:5
--> $DIR/suggestions.rs:61:5
|
LL | while true { // should suggest `loop`
LL | while true {
| ^^^^^^^^^^ help: use `loop`
|
= note: #[warn(while_true)] on by default
warning: the `warp_factor:` in this pattern is redundant
--> $DIR/suggestions.rs:57:23
--> $DIR/suggestions.rs:76:23
|
LL | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
LL | Equinox { warp_factor: warp_factor } => {}
| ------------^^^^^^^^^^^^
| |
| help: remove this

View File

@ -17,7 +17,9 @@ warning: unreachable `pub` item
--> $DIR/unreachable_pub-pub_crate.rs:27:24
|
LL | pub use std::env::{Args}; // braced-use has different item spans than unbraced
| ^^^^ help: consider restricting its visibility: `pub(crate)`
| --- ^^^^
| |
| help: consider restricting its visibility: `pub(crate)`
|
= help: or consider exporting it for use by other crates
@ -121,12 +123,13 @@ warning: unreachable `pub` item
--> $DIR/unreachable_pub-pub_crate.rs:50:47
|
LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} }
| -----------^^^^^^^^^^^^^
| |
| help: consider restricting its visibility: `pub(crate)`
| ^^^^^^^^^^^^^^^^^^^^^^^^
LL | }
LL | define_empty_struct_with_visibility!(pub, Fluorine);
| ---------------------------------------------------- in this macro invocation
| ----------------------------------------------------
| | |
| | help: consider restricting its visibility: `pub(crate)`
| in this macro invocation
|
= help: or consider exporting it for use by other crates

View File

@ -17,7 +17,9 @@ warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:22:24
|
LL | pub use std::env::{Args}; // braced-use has different item spans than unbraced
| ^^^^ help: consider restricting its visibility: `crate`
| --- ^^^^
| |
| help: consider restricting its visibility: `crate`
|
= help: or consider exporting it for use by other crates
@ -121,12 +123,13 @@ warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:45:47
|
LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} }
| -----------^^^^^^^^^^^^^
| |
| help: consider restricting its visibility: `crate`
| ^^^^^^^^^^^^^^^^^^^^^^^^
LL | }
LL | define_empty_struct_with_visibility!(pub, Fluorine);
| ---------------------------------------------------- in this macro invocation
| ----------------------------------------------------
| | |
| | help: consider restricting its visibility: `crate`
| in this macro invocation
|
= help: or consider exporting it for use by other crates

View File

@ -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() {}

View File

@ -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`.