diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index c5e5fa65fc6..60e944e5aff 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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) } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8f2ce9a18ee..e59e50ae9e6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index f0fc0d9b1c2..3cc25bfd2d4 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -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); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index dbf99cf30e5..08a130f049b 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -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, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d8bf5fe9b6d..b0b81316148 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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, } } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c6f69a84d03..255009c94c6 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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() diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index d59a20c6522..0c7baea85ad 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -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>, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index c846b627d89..226d19a9124 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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)); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 1f647d811b0..54afd795fc0 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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)) } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 05aa57d8cc5..f1f5e3ef6e1 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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); } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 93294075272..3cfde7a8297 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -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 { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 157da5ee6d5..c55d57cb916 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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)); } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 685c86029b6..447b5f1fe47 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -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, ..), diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index ae5ca5441ad..3a8ed0ea25f 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -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) { } } - diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 65babbffffe..b8abb98edec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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"), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 0807db29976..6fd9ef234f4 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -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, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 6bf1931e468..fdeba93990d 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -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") => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 673157d0ffa..1f062656b81 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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; 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/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index e35675eacd8..4da2700cb9f 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -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); } diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 84a2e4a91ec..8e5dac8be78 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -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 diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.stderr b/src/test/ui/lint/unreachable_pub-pub_crate.stderr index 2948deb2300..1cbfbd21125 100644 --- a/src/test/ui/lint/unreachable_pub-pub_crate.stderr +++ b/src/test/ui/lint/unreachable_pub-pub_crate.stderr @@ -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 diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr index ad88c55d540..25046055aa0 100644 --- a/src/test/ui/lint/unreachable_pub.stderr +++ b/src/test/ui/lint/unreachable_pub.stderr @@ -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 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`.