Make priv in pub hard error for crates using pub(restricted)
This commit is contained in:
parent
28626ca5b1
commit
60c1c961c7
|
@ -1468,6 +1468,18 @@ pub enum Visibility {
|
||||||
Inherited,
|
Inherited,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Visibility {
|
||||||
|
pub fn is_pub_restricted(&self) -> bool {
|
||||||
|
use self::Visibility::*;
|
||||||
|
match self {
|
||||||
|
&Public |
|
||||||
|
&Inherited => false,
|
||||||
|
&Crate |
|
||||||
|
&Restricted { .. } => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
|
@ -45,6 +45,26 @@ use std::mem::replace;
|
||||||
|
|
||||||
pub mod diagnostics;
|
pub mod diagnostics;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Visitor used to determine if pub(restricted) is used anywhere in the crate.
|
||||||
|
///
|
||||||
|
/// This is done so that `private_in_public` warnings can be turned into hard errors
|
||||||
|
/// in crates that have been updated to use pub(restricted).
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct PubRestrictedVisitor<'a, 'tcx: 'a> {
|
||||||
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
has_pub_restricted: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> {
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, '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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// The embargo visitor, used to determine the exports of the ast
|
/// The embargo visitor, used to determine the exports of the ast
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -891,6 +911,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
|
||||||
required_visibility: ty::Visibility,
|
required_visibility: ty::Visibility,
|
||||||
/// The visibility of the least visible component that has been visited
|
/// The visibility of the least visible component that has been visited
|
||||||
min_visibility: ty::Visibility,
|
min_visibility: ty::Visibility,
|
||||||
|
has_pub_restricted: bool,
|
||||||
has_old_errors: bool,
|
has_old_errors: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +972,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
|
||||||
self.min_visibility = vis;
|
self.min_visibility = vis;
|
||||||
}
|
}
|
||||||
if !vis.is_at_least(self.required_visibility, self.tcx) {
|
if !vis.is_at_least(self.required_visibility, self.tcx) {
|
||||||
if self.has_old_errors {
|
if self.has_pub_restricted || self.has_old_errors {
|
||||||
let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
|
let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
|
||||||
"private type `{}` in public interface", ty);
|
"private type `{}` in public interface", ty);
|
||||||
err.span_label(self.span, &format!("can't leak private type"));
|
err.span_label(self.span, &format!("can't leak private type"));
|
||||||
|
@ -986,7 +1007,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
|
||||||
self.min_visibility = vis;
|
self.min_visibility = vis;
|
||||||
}
|
}
|
||||||
if !vis.is_at_least(self.required_visibility, self.tcx) {
|
if !vis.is_at_least(self.required_visibility, self.tcx) {
|
||||||
if self.has_old_errors {
|
if self.has_pub_restricted || self.has_old_errors {
|
||||||
struct_span_err!(self.tcx.sess, self.span, E0445,
|
struct_span_err!(self.tcx.sess, self.span, E0445,
|
||||||
"private trait `{}` in public interface", trait_ref)
|
"private trait `{}` in public interface", trait_ref)
|
||||||
.span_label(self.span, &format!(
|
.span_label(self.span, &format!(
|
||||||
|
@ -1008,6 +1029,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
|
||||||
|
|
||||||
struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
|
struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
has_pub_restricted: bool,
|
||||||
old_error_set: &'a NodeSet,
|
old_error_set: &'a NodeSet,
|
||||||
inner_visibility: ty::Visibility,
|
inner_visibility: ty::Visibility,
|
||||||
}
|
}
|
||||||
|
@ -1044,6 +1066,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
|
||||||
span: self.tcx.hir.span(item_id),
|
span: self.tcx.hir.span(item_id),
|
||||||
min_visibility: ty::Visibility::Public,
|
min_visibility: ty::Visibility::Public,
|
||||||
required_visibility: required_visibility,
|
required_visibility: required_visibility,
|
||||||
|
has_pub_restricted: self.has_pub_restricted,
|
||||||
has_old_errors: has_old_errors,
|
has_old_errors: has_old_errors,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1227,9 +1250,20 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
intravisit::walk_crate(&mut visitor, krate);
|
intravisit::walk_crate(&mut visitor, krate);
|
||||||
|
|
||||||
|
|
||||||
|
let has_pub_restricted = {
|
||||||
|
let mut pub_restricted_visitor = PubRestrictedVisitor {
|
||||||
|
tcx: tcx,
|
||||||
|
has_pub_restricted: false
|
||||||
|
};
|
||||||
|
intravisit::walk_crate(&mut pub_restricted_visitor, krate);
|
||||||
|
pub_restricted_visitor.has_pub_restricted
|
||||||
|
};
|
||||||
|
|
||||||
// Check for private types and traits in public interfaces
|
// Check for private types and traits in public interfaces
|
||||||
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
|
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
|
has_pub_restricted: has_pub_restricted,
|
||||||
old_error_set: &visitor.old_error_set,
|
old_error_set: &visitor.old_error_set,
|
||||||
inner_visibility: ty::Visibility::Public,
|
inner_visibility: ty::Visibility::Public,
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,16 +8,12 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![deny(warnings)]
|
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
mod foo {
|
mod foo {
|
||||||
struct Priv;
|
struct Priv;
|
||||||
mod bar {
|
mod bar {
|
||||||
use foo::Priv;
|
use foo::Priv;
|
||||||
pub(super) fn f(_: Priv) {}
|
pub(super) fn f(_: Priv) {}
|
||||||
pub(crate) fn g(_: Priv) {} //~ ERROR E0446
|
pub(crate) fn g(_: Priv) {} //~ ERROR E0446
|
||||||
//~^ this was previously accepted
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue