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).  r? @nrc cc @Manishearth
This commit is contained in:
commit
45935640f0
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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>,
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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, ..),
|
||||
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -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,
|
||||
|
@ -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") => {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 | | }
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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…
x
Reference in New Issue
Block a user