Skip to content

Implement pub(restricted) privacy (RFC 1422) #32875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 17, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
@@ -203,6 +203,9 @@ pub trait Visitor<'v> : Sized {
fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
walk_macro_def(self, macro_def)
}
fn visit_vis(&mut self, vis: &'v Visibility) {
walk_vis(self, vis)
}
}

pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
@@ -288,6 +291,7 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
}

pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_vis(&item.vis);
visitor.visit_name(item.span, item.name);
match item.node {
ItemExternCrate(opt_name) => {
@@ -529,6 +533,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
}

pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
visitor.visit_vis(&foreign_item.vis);
visitor.visit_name(foreign_item.span, foreign_item.name);

match foreign_item.node {
@@ -662,6 +667,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
}

pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
visitor.visit_vis(&impl_item.vis);
visitor.visit_name(impl_item.span, impl_item.name);
walk_list!(visitor, visit_attribute, &impl_item.attrs);
match impl_item.node {
@@ -690,6 +696,7 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &
}

pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
visitor.visit_vis(&struct_field.vis);
visitor.visit_name(struct_field.span, struct_field.name);
visitor.visit_ty(&struct_field.ty);
walk_list!(visitor, visit_attribute, &struct_field.attrs);
@@ -839,6 +846,12 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
walk_list!(visitor, visit_attribute, &arm.attrs);
}

pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
if let Visibility::Restricted { ref path, id } = *vis {
visitor.visit_path(path, id)
}
}

#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct IdRange {
pub min: NodeId,
4 changes: 3 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -1708,8 +1708,10 @@ pub fn lower_capture_clause(_lctx: &LoweringContext, c: CaptureBy) -> hir::Captu
pub fn lower_visibility(lctx: &LoweringContext, v: &Visibility) -> hir::Visibility {
match *v {
Visibility::Public => hir::Public,
Visibility::Crate(_) => hir::Visibility::Crate,
Visibility::Restricted { ref path, id } =>
hir::Visibility::Restricted { path: P(lower_path(lctx, path)), id: id },
Visibility::Inherited => hir::Inherited,
_ => panic!(lctx.diagnostic().fatal("pub(restricted) is not implemented yet!"))
}
}

4 changes: 3 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ pub use self::TyParamBound::*;
pub use self::UnOp::*;
pub use self::UnsafeSource::*;
pub use self::ViewPath_::*;
pub use self::Visibility::*;
pub use self::Visibility::{Public, Inherited};
pub use self::PathParameters::*;

use hir::def::Def;
@@ -1434,6 +1434,8 @@ pub struct PolyTraitRef {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Visibility {
Public,
Crate,
Restricted { path: P<Path>, id: NodeId },
Inherited,
}

5 changes: 5 additions & 0 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
@@ -325,6 +325,8 @@ pub fn arg_to_string(arg: &hir::Arg) -> String {
pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
match *vis {
hir::Public => format!("pub {}", s),
hir::Visibility::Crate => format!("pub(crate) {}", s),
hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
hir::Inherited => s.to_string(),
}
}
@@ -898,6 +900,9 @@ 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 => self.word_nbsp("pub(crate)"),
hir::Visibility::Restricted { ref path, .. } =>
self.word_nbsp(&format!("pub({})", path)),
hir::Inherited => Ok(()),
}
}
9 changes: 9 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -287,6 +287,15 @@ 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(ast::CRATE_NODE_ID),
hir::Visibility::Restricted { id, .. } => match tcx.def_map.borrow().get(&id) {
Some(resolution) => Visibility::Restricted({
tcx.map.as_local_node_id(resolution.base_def.def_id()).unwrap()
}),
// 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.
None => Visibility::Public,
},
hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
}
}
6 changes: 4 additions & 2 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
@@ -1023,7 +1023,8 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
self.min_visibility = vis;
}
if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
if self.old_error_set.contains(&ty.id) {
if self.tcx.sess.features.borrow().pub_restricted ||
self.old_error_set.contains(&ty.id) {
span_err!(self.tcx.sess, ty.span, E0446,
"private type in public interface");
} else {
@@ -1053,7 +1054,8 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
self.min_visibility = vis;
}
if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
if self.old_error_set.contains(&trait_ref.ref_id) {
if self.tcx.sess.features.borrow().pub_restricted ||
self.old_error_set.contains(&trait_ref.ref_id) {
span_err!(self.tcx.sess, trait_ref.path.span, E0445,
"private trait in public interface");
} else {
Loading