Auto merge of #32875 - jseyfried:1422_implementation, r=nikomatsakis
Implement `pub(restricted)` privacy (RFC 1422) This implements `pub(restricted)` privacy from RFC 1422 (cc #32409) behind a feature gate. `pub(restricted)` paths currently cannot use re-exported modules both for simplicity of implementation and for future compatibility with RFC 1560 (cf #31783). r? @nikomatsakis
This commit is contained in:
commit
ae33aa74f4
26 changed files with 478 additions and 196 deletions
|
@ -203,6 +203,9 @@ pub trait Visitor<'v> : Sized {
|
||||||
fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
|
fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
|
||||||
walk_macro_def(self, macro_def)
|
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>) {
|
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) {
|
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);
|
visitor.visit_name(item.span, item.name);
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemExternCrate(opt_name) => {
|
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) {
|
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);
|
visitor.visit_name(foreign_item.span, foreign_item.name);
|
||||||
|
|
||||||
match foreign_item.node {
|
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) {
|
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);
|
visitor.visit_name(impl_item.span, impl_item.name);
|
||||||
walk_list!(visitor, visit_attribute, &impl_item.attrs);
|
walk_list!(visitor, visit_attribute, &impl_item.attrs);
|
||||||
match impl_item.node {
|
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) {
|
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_name(struct_field.span, struct_field.name);
|
||||||
visitor.visit_ty(&struct_field.ty);
|
visitor.visit_ty(&struct_field.ty);
|
||||||
walk_list!(visitor, visit_attribute, &struct_field.attrs);
|
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);
|
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)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct IdRange {
|
pub struct IdRange {
|
||||||
pub min: NodeId,
|
pub min: NodeId,
|
||||||
|
|
|
@ -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 {
|
pub fn lower_visibility(lctx: &LoweringContext, v: &Visibility) -> hir::Visibility {
|
||||||
match *v {
|
match *v {
|
||||||
Visibility::Public => hir::Public,
|
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,
|
Visibility::Inherited => hir::Inherited,
|
||||||
_ => panic!(lctx.diagnostic().fatal("pub(restricted) is not implemented yet!"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub use self::TyParamBound::*;
|
||||||
pub use self::UnOp::*;
|
pub use self::UnOp::*;
|
||||||
pub use self::UnsafeSource::*;
|
pub use self::UnsafeSource::*;
|
||||||
pub use self::ViewPath_::*;
|
pub use self::ViewPath_::*;
|
||||||
pub use self::Visibility::*;
|
pub use self::Visibility::{Public, Inherited};
|
||||||
pub use self::PathParameters::*;
|
pub use self::PathParameters::*;
|
||||||
|
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
|
@ -1434,6 +1434,8 @@ pub struct PolyTraitRef {
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum Visibility {
|
pub enum Visibility {
|
||||||
Public,
|
Public,
|
||||||
|
Crate,
|
||||||
|
Restricted { path: P<Path>, id: NodeId },
|
||||||
Inherited,
|
Inherited,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,8 @@ pub fn arg_to_string(arg: &hir::Arg) -> String {
|
||||||
pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
|
pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
|
||||||
match *vis {
|
match *vis {
|
||||||
hir::Public => format!("pub {}", s),
|
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(),
|
hir::Inherited => s.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,6 +900,9 @@ impl<'a> State<'a> {
|
||||||
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
|
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
|
||||||
match *vis {
|
match *vis {
|
||||||
hir::Public => self.word_nbsp("pub"),
|
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(()),
|
hir::Inherited => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,6 +287,15 @@ impl Visibility {
|
||||||
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self {
|
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self {
|
||||||
match *visibility {
|
match *visibility {
|
||||||
hir::Public => Visibility::Public,
|
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)),
|
hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1023,7 +1023,8 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
|
||||||
self.min_visibility = vis;
|
self.min_visibility = vis;
|
||||||
}
|
}
|
||||||
if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
|
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,
|
span_err!(self.tcx.sess, ty.span, E0446,
|
||||||
"private type in public interface");
|
"private type in public interface");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1053,7 +1054,8 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
|
||||||
self.min_visibility = vis;
|
self.min_visibility = vis;
|
||||||
}
|
}
|
||||||
if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
|
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,
|
span_err!(self.tcx.sess, trait_ref.path.span, E0445,
|
||||||
"private trait in public interface");
|
"private trait in public interface");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -53,10 +53,10 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, Span) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToNameBinding<'a> for (Def, Span, DefModifiers) {
|
impl<'a> ToNameBinding<'a> for (Def, Span, DefModifiers, ty::Visibility) {
|
||||||
fn to_name_binding(self) -> NameBinding<'a> {
|
fn to_name_binding(self) -> NameBinding<'a> {
|
||||||
let kind = NameBindingKind::Def(self.0);
|
let kind = NameBindingKind::Def(self.0);
|
||||||
NameBinding { modifiers: self.2, kind: kind, span: Some(self.1) }
|
NameBinding { modifiers: self.2, kind: kind, span: Some(self.1), vis: self.3 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,12 +105,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
let parent = *parent_ref;
|
let parent = *parent_ref;
|
||||||
let name = item.name;
|
let name = item.name;
|
||||||
let sp = item.span;
|
let sp = item.span;
|
||||||
let is_public = item.vis == hir::Public;
|
let modifiers = DefModifiers::IMPORTABLE;
|
||||||
let modifiers = if is_public {
|
self.current_module = parent;
|
||||||
DefModifiers::PUBLIC
|
let vis = self.resolve_visibility(&item.vis);
|
||||||
} else {
|
|
||||||
DefModifiers::empty()
|
|
||||||
} | DefModifiers::IMPORTABLE;
|
|
||||||
|
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemUse(ref view_path) => {
|
ItemUse(ref view_path) => {
|
||||||
|
@ -172,7 +169,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
subclass,
|
subclass,
|
||||||
view_path.span,
|
view_path.span,
|
||||||
item.id,
|
item.id,
|
||||||
is_public,
|
vis,
|
||||||
is_prelude);
|
is_prelude);
|
||||||
}
|
}
|
||||||
ViewPathList(_, ref source_items) => {
|
ViewPathList(_, ref source_items) => {
|
||||||
|
@ -223,7 +220,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
subclass,
|
subclass,
|
||||||
source_item.span,
|
source_item.span,
|
||||||
source_item.node.id(),
|
source_item.node.id(),
|
||||||
is_public,
|
vis,
|
||||||
is_prelude);
|
is_prelude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,7 +230,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
GlobImport,
|
GlobImport,
|
||||||
view_path.span,
|
view_path.span,
|
||||||
item.id,
|
item.id,
|
||||||
is_public,
|
vis,
|
||||||
is_prelude);
|
is_prelude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +246,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
};
|
};
|
||||||
let parent_link = ModuleParentLink(parent, name);
|
let parent_link = ModuleParentLink(parent, name);
|
||||||
let def = Def::Mod(def_id);
|
let def = Def::Mod(def_id);
|
||||||
let module = self.new_extern_crate_module(parent_link, def, is_public, item.id);
|
let module = self.new_extern_crate_module(parent_link, def, vis, item.id);
|
||||||
self.define(parent, name, TypeNS, (module, sp));
|
self.define(parent, name, TypeNS, (module, sp));
|
||||||
|
|
||||||
self.build_reduced_graph_for_external_crate(module);
|
self.build_reduced_graph_for_external_crate(module);
|
||||||
|
@ -259,7 +256,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
ItemMod(..) => {
|
ItemMod(..) => {
|
||||||
let parent_link = ModuleParentLink(parent, name);
|
let parent_link = ModuleParentLink(parent, name);
|
||||||
let def = Def::Mod(self.ast_map.local_def_id(item.id));
|
let def = Def::Mod(self.ast_map.local_def_id(item.id));
|
||||||
let module = self.new_module(parent_link, Some(def), false, is_public);
|
let module = self.new_module(parent_link, Some(def), false, vis);
|
||||||
self.define(parent, name, TypeNS, (module, sp));
|
self.define(parent, name, TypeNS, (module, sp));
|
||||||
parent.module_children.borrow_mut().insert(item.id, module);
|
parent.module_children.borrow_mut().insert(item.id, module);
|
||||||
*parent_ref = module;
|
*parent_ref = module;
|
||||||
|
@ -271,38 +268,32 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
ItemStatic(_, m, _) => {
|
ItemStatic(_, m, _) => {
|
||||||
let mutbl = m == hir::MutMutable;
|
let mutbl = m == hir::MutMutable;
|
||||||
let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
|
let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
|
||||||
self.define(parent, name, ValueNS, (def, sp, modifiers));
|
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||||
}
|
}
|
||||||
ItemConst(_, _) => {
|
ItemConst(_, _) => {
|
||||||
let def = Def::Const(self.ast_map.local_def_id(item.id));
|
let def = Def::Const(self.ast_map.local_def_id(item.id));
|
||||||
self.define(parent, name, ValueNS, (def, sp, modifiers));
|
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||||
}
|
}
|
||||||
ItemFn(_, _, _, _, _, _) => {
|
ItemFn(_, _, _, _, _, _) => {
|
||||||
let def = Def::Fn(self.ast_map.local_def_id(item.id));
|
let def = Def::Fn(self.ast_map.local_def_id(item.id));
|
||||||
self.define(parent, name, ValueNS, (def, sp, modifiers));
|
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||||
}
|
}
|
||||||
|
|
||||||
// These items live in the type namespace.
|
// These items live in the type namespace.
|
||||||
ItemTy(..) => {
|
ItemTy(..) => {
|
||||||
let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
|
let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
|
||||||
self.define(parent, name, TypeNS, (def, sp, modifiers));
|
self.define(parent, name, TypeNS, (def, sp, modifiers, vis));
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemEnum(ref enum_definition, _) => {
|
ItemEnum(ref enum_definition, _) => {
|
||||||
let parent_link = ModuleParentLink(parent, name);
|
let parent_link = ModuleParentLink(parent, name);
|
||||||
let def = Def::Enum(self.ast_map.local_def_id(item.id));
|
let def = Def::Enum(self.ast_map.local_def_id(item.id));
|
||||||
let module = self.new_module(parent_link, Some(def), false, is_public);
|
let module = self.new_module(parent_link, Some(def), false, vis);
|
||||||
self.define(parent, name, TypeNS, (module, sp));
|
self.define(parent, name, TypeNS, (module, sp));
|
||||||
|
|
||||||
let variant_modifiers = if is_public {
|
|
||||||
DefModifiers::empty()
|
|
||||||
} else {
|
|
||||||
DefModifiers::PRIVATE_VARIANT
|
|
||||||
};
|
|
||||||
for variant in &(*enum_definition).variants {
|
for variant in &(*enum_definition).variants {
|
||||||
let item_def_id = self.ast_map.local_def_id(item.id);
|
let item_def_id = self.ast_map.local_def_id(item.id);
|
||||||
self.build_reduced_graph_for_variant(variant, item_def_id,
|
self.build_reduced_graph_for_variant(variant, item_def_id, module);
|
||||||
module, variant_modifiers);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,20 +301,20 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
ItemStruct(ref struct_def, _) => {
|
ItemStruct(ref struct_def, _) => {
|
||||||
// Define a name in the type namespace.
|
// Define a name in the type namespace.
|
||||||
let def = Def::Struct(self.ast_map.local_def_id(item.id));
|
let def = Def::Struct(self.ast_map.local_def_id(item.id));
|
||||||
self.define(parent, name, TypeNS, (def, sp, modifiers));
|
self.define(parent, name, TypeNS, (def, sp, modifiers, vis));
|
||||||
|
|
||||||
// If this is a newtype or unit-like struct, define a name
|
// If this is a newtype or unit-like struct, define a name
|
||||||
// in the value namespace as well
|
// in the value namespace as well
|
||||||
if !struct_def.is_struct() {
|
if !struct_def.is_struct() {
|
||||||
let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
|
let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
|
||||||
self.define(parent, name, ValueNS, (def, sp, modifiers));
|
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the def ID and fields of this struct.
|
// Record the def ID and fields of this struct.
|
||||||
let field_names = struct_def.fields()
|
let field_names = struct_def.fields().iter().map(|field| {
|
||||||
.iter()
|
self.resolve_visibility(&field.vis);
|
||||||
.map(|f| f.name)
|
field.name
|
||||||
.collect();
|
}).collect();
|
||||||
let item_def_id = self.ast_map.local_def_id(item.id);
|
let item_def_id = self.ast_map.local_def_id(item.id);
|
||||||
self.structs.insert(item_def_id, field_names);
|
self.structs.insert(item_def_id, field_names);
|
||||||
}
|
}
|
||||||
|
@ -336,7 +327,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
// Add all the items within to a new module.
|
// Add all the items within to a new module.
|
||||||
let parent_link = ModuleParentLink(parent, name);
|
let parent_link = ModuleParentLink(parent, name);
|
||||||
let def = Def::Trait(def_id);
|
let def = Def::Trait(def_id);
|
||||||
let module_parent = self.new_module(parent_link, Some(def), false, is_public);
|
let module_parent = self.new_module(parent_link, Some(def), false, vis);
|
||||||
self.define(parent, name, TypeNS, (module_parent, sp));
|
self.define(parent, name, TypeNS, (module_parent, sp));
|
||||||
|
|
||||||
// Add the names of all the items to the trait info.
|
// Add the names of all the items to the trait info.
|
||||||
|
@ -348,8 +339,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
|
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
|
||||||
};
|
};
|
||||||
|
|
||||||
let modifiers = DefModifiers::PUBLIC; // NB: not DefModifiers::IMPORTABLE
|
let modifiers = DefModifiers::empty(); // NB: not DefModifiers::IMPORTABLE
|
||||||
self.define(module_parent, item.name, ns, (def, item.span, modifiers));
|
self.define(module_parent, item.name, ns, (def, item.span, modifiers, vis));
|
||||||
|
|
||||||
self.trait_item_map.insert((item.name, def_id), item_def_id);
|
self.trait_item_map.insert((item.name, def_id), item_def_id);
|
||||||
}
|
}
|
||||||
|
@ -362,8 +353,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
fn build_reduced_graph_for_variant(&mut self,
|
fn build_reduced_graph_for_variant(&mut self,
|
||||||
variant: &Variant,
|
variant: &Variant,
|
||||||
item_id: DefId,
|
item_id: DefId,
|
||||||
parent: Module<'b>,
|
parent: Module<'b>) {
|
||||||
variant_modifiers: DefModifiers) {
|
|
||||||
let name = variant.node.name;
|
let name = variant.node.name;
|
||||||
if variant.node.data.is_struct() {
|
if variant.node.data.is_struct() {
|
||||||
// Not adding fields for variants as they are not accessed with a self receiver
|
// Not adding fields for variants as they are not accessed with a self receiver
|
||||||
|
@ -373,11 +363,11 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
|
|
||||||
// Variants are always treated as importable to allow them to be glob used.
|
// Variants are always treated as importable to allow them to be glob used.
|
||||||
// All variants are defined in both type and value namespaces as future-proofing.
|
// All variants are defined in both type and value namespaces as future-proofing.
|
||||||
let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers;
|
let modifiers = DefModifiers::IMPORTABLE;
|
||||||
let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
|
let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
|
||||||
|
|
||||||
self.define(parent, name, ValueNS, (def, variant.span, modifiers));
|
self.define(parent, name, ValueNS, (def, variant.span, modifiers, parent.vis));
|
||||||
self.define(parent, name, TypeNS, (def, variant.span, modifiers));
|
self.define(parent, name, TypeNS, (def, variant.span, modifiers, parent.vis));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs the reduced graph for one foreign item.
|
/// Constructs the reduced graph for one foreign item.
|
||||||
|
@ -385,12 +375,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
foreign_item: &ForeignItem,
|
foreign_item: &ForeignItem,
|
||||||
parent: Module<'b>) {
|
parent: Module<'b>) {
|
||||||
let name = foreign_item.name;
|
let name = foreign_item.name;
|
||||||
let is_public = foreign_item.vis == hir::Public;
|
let modifiers = DefModifiers::IMPORTABLE;
|
||||||
let modifiers = if is_public {
|
|
||||||
DefModifiers::PUBLIC
|
|
||||||
} else {
|
|
||||||
DefModifiers::empty()
|
|
||||||
} | DefModifiers::IMPORTABLE;
|
|
||||||
|
|
||||||
let def = match foreign_item.node {
|
let def = match foreign_item.node {
|
||||||
ForeignItemFn(..) => {
|
ForeignItemFn(..) => {
|
||||||
|
@ -400,7 +385,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
|
Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.define(parent, name, ValueNS, (def, foreign_item.span, modifiers));
|
self.current_module = parent;
|
||||||
|
let vis = self.resolve_visibility(&foreign_item.vis);
|
||||||
|
self.define(parent, name, ValueNS, (def, foreign_item.span, modifiers, vis));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) {
|
fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) {
|
||||||
|
@ -412,7 +399,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
block_id);
|
block_id);
|
||||||
|
|
||||||
let parent_link = BlockParentLink(parent, block_id);
|
let parent_link = BlockParentLink(parent, block_id);
|
||||||
let new_module = self.new_module(parent_link, None, false, false);
|
let new_module = self.new_module(parent_link, None, false, parent.vis);
|
||||||
parent.module_children.borrow_mut().insert(block_id, new_module);
|
parent.module_children.borrow_mut().insert(block_id, new_module);
|
||||||
*parent = new_module;
|
*parent = new_module;
|
||||||
}
|
}
|
||||||
|
@ -434,32 +421,27 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = xcdef.name;
|
let name = xcdef.name;
|
||||||
let is_public = xcdef.vis == ty::Visibility::Public || parent.is_trait();
|
let vis = if parent.is_trait() { ty::Visibility::Public } else { xcdef.vis };
|
||||||
|
let modifiers = match parent.is_normal() {
|
||||||
let mut modifiers = DefModifiers::empty();
|
true => DefModifiers::IMPORTABLE,
|
||||||
if is_public {
|
false => DefModifiers::empty(),
|
||||||
modifiers = modifiers | DefModifiers::PUBLIC;
|
};
|
||||||
}
|
|
||||||
if parent.is_normal() {
|
|
||||||
modifiers = modifiers | DefModifiers::IMPORTABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => {
|
Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => {
|
||||||
debug!("(building reduced graph for external crate) building module {} {}",
|
debug!("(building reduced graph for external crate) building module {} {:?}",
|
||||||
name,
|
name, vis);
|
||||||
is_public);
|
|
||||||
let parent_link = ModuleParentLink(parent, name);
|
let parent_link = ModuleParentLink(parent, name);
|
||||||
let module = self.new_module(parent_link, Some(def), true, is_public);
|
let module = self.new_module(parent_link, Some(def), true, vis);
|
||||||
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
|
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
|
||||||
}
|
}
|
||||||
Def::Variant(_, variant_id) => {
|
Def::Variant(_, variant_id) => {
|
||||||
debug!("(building reduced graph for external crate) building variant {}", name);
|
debug!("(building reduced graph for external crate) building variant {}", name);
|
||||||
// Variants are always treated as importable to allow them to be glob used.
|
// Variants are always treated as importable to allow them to be glob used.
|
||||||
// All variants are defined in both type and value namespaces as future-proofing.
|
// All variants are defined in both type and value namespaces as future-proofing.
|
||||||
let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
|
let modifiers = DefModifiers::IMPORTABLE;
|
||||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers));
|
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers, vis));
|
||||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers));
|
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers, vis));
|
||||||
if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
|
if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
|
||||||
// Not adding fields for variants as they are not accessed with a self receiver
|
// Not adding fields for variants as they are not accessed with a self receiver
|
||||||
self.structs.insert(variant_id, Vec::new());
|
self.structs.insert(variant_id, Vec::new());
|
||||||
|
@ -472,7 +454,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
Def::Method(..) => {
|
Def::Method(..) => {
|
||||||
debug!("(building reduced graph for external crate) building value (fn/static) {}",
|
debug!("(building reduced graph for external crate) building value (fn/static) {}",
|
||||||
name);
|
name);
|
||||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers));
|
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers, vis));
|
||||||
}
|
}
|
||||||
Def::Trait(def_id) => {
|
Def::Trait(def_id) => {
|
||||||
debug!("(building reduced graph for external crate) building type {}", name);
|
debug!("(building reduced graph for external crate) building type {}", name);
|
||||||
|
@ -493,21 +475,21 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let parent_link = ModuleParentLink(parent, name);
|
let parent_link = ModuleParentLink(parent, name);
|
||||||
let module = self.new_module(parent_link, Some(def), true, is_public);
|
let module = self.new_module(parent_link, Some(def), true, vis);
|
||||||
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
|
self.try_define(parent, name, TypeNS, (module, DUMMY_SP));
|
||||||
}
|
}
|
||||||
Def::TyAlias(..) | Def::AssociatedTy(..) => {
|
Def::TyAlias(..) | Def::AssociatedTy(..) => {
|
||||||
debug!("(building reduced graph for external crate) building type {}", name);
|
debug!("(building reduced graph for external crate) building type {}", name);
|
||||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers));
|
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers, vis));
|
||||||
}
|
}
|
||||||
Def::Struct(def_id)
|
Def::Struct(def_id)
|
||||||
if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => {
|
if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => {
|
||||||
debug!("(building reduced graph for external crate) building type and value for {}",
|
debug!("(building reduced graph for external crate) building type and value for {}",
|
||||||
name);
|
name);
|
||||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers));
|
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers, vis));
|
||||||
if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
|
if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
|
||||||
let def = Def::Struct(ctor_def_id);
|
let def = Def::Struct(ctor_def_id);
|
||||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers));
|
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers, vis));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the def ID and fields of this struct.
|
// Record the def ID and fields of this struct.
|
||||||
|
|
|
@ -55,6 +55,7 @@ use rustc::middle::cstore::CrateStore;
|
||||||
use rustc::hir::def::*;
|
use rustc::hir::def::*;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::pat_util::pat_bindings;
|
use rustc::hir::pat_util::pat_bindings;
|
||||||
|
use rustc::ty;
|
||||||
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
|
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
|
||||||
use rustc::hir::{Freevar, FreevarMap, TraitMap, GlobMap};
|
use rustc::hir::{Freevar, FreevarMap, TraitMap, GlobMap};
|
||||||
use rustc::util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
|
use rustc::util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
|
||||||
|
@ -820,7 +821,7 @@ enum ParentLink<'a> {
|
||||||
pub struct ModuleS<'a> {
|
pub struct ModuleS<'a> {
|
||||||
parent_link: ParentLink<'a>,
|
parent_link: ParentLink<'a>,
|
||||||
def: Option<Def>,
|
def: Option<Def>,
|
||||||
is_public: bool,
|
vis: ty::Visibility,
|
||||||
|
|
||||||
// If the module is an extern crate, `def` is root of the external crate and `extern_crate_id`
|
// If the module is an extern crate, `def` is root of the external crate and `extern_crate_id`
|
||||||
// is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None).
|
// is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None).
|
||||||
|
@ -864,12 +865,12 @@ impl<'a> ModuleS<'a> {
|
||||||
fn new(parent_link: ParentLink<'a>,
|
fn new(parent_link: ParentLink<'a>,
|
||||||
def: Option<Def>,
|
def: Option<Def>,
|
||||||
external: bool,
|
external: bool,
|
||||||
is_public: bool,
|
vis: ty::Visibility,
|
||||||
arenas: &'a ResolverArenas<'a>) -> Self {
|
arenas: &'a ResolverArenas<'a>) -> Self {
|
||||||
ModuleS {
|
ModuleS {
|
||||||
parent_link: parent_link,
|
parent_link: parent_link,
|
||||||
def: def,
|
def: def,
|
||||||
is_public: is_public,
|
vis: vis,
|
||||||
extern_crate_id: None,
|
extern_crate_id: None,
|
||||||
resolutions: RefCell::new(HashMap::new()),
|
resolutions: RefCell::new(HashMap::new()),
|
||||||
unresolved_imports: RefCell::new(Vec::new()),
|
unresolved_imports: RefCell::new(Vec::new()),
|
||||||
|
@ -892,9 +893,10 @@ impl<'a> ModuleS<'a> {
|
||||||
self.def.as_ref().map(Def::def_id)
|
self.def.as_ref().map(Def::def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `self` resolves to the first module ancestor that `is_normal`.
|
||||||
fn is_normal(&self) -> bool {
|
fn is_normal(&self) -> bool {
|
||||||
match self.def {
|
match self.def {
|
||||||
Some(Def::Mod(_)) | Some(Def::ForeignMod(_)) => true,
|
Some(Def::Mod(_)) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -905,40 +907,18 @@ impl<'a> ModuleS<'a> {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ancestor_of(&self, module: Module<'a>) -> bool {
|
|
||||||
if self.def_id() == module.def_id() { return true }
|
|
||||||
match module.parent_link {
|
|
||||||
ParentLink::BlockParentLink(parent, _) |
|
|
||||||
ParentLink::ModuleParentLink(parent, _) => self.is_ancestor_of(parent),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Debug for ModuleS<'a> {
|
impl<'a> fmt::Debug for ModuleS<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f,
|
write!(f, "{:?}, {:?}", self.def, self.vis)
|
||||||
"{:?}, {}",
|
|
||||||
self.def,
|
|
||||||
if self.is_public {
|
|
||||||
"public"
|
|
||||||
} else {
|
|
||||||
"private"
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
flags DefModifiers: u8 {
|
flags DefModifiers: u8 {
|
||||||
// Enum variants are always considered `PUBLIC`, this is needed for `use Enum::Variant`
|
|
||||||
// or `use Enum::*` to work on private enums.
|
|
||||||
const PUBLIC = 1 << 0,
|
|
||||||
const IMPORTABLE = 1 << 1,
|
const IMPORTABLE = 1 << 1,
|
||||||
// Variants are considered `PUBLIC`, but some of them live in private enums.
|
|
||||||
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
|
|
||||||
const PRIVATE_VARIANT = 1 << 2,
|
|
||||||
const GLOB_IMPORTED = 1 << 3,
|
const GLOB_IMPORTED = 1 << 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -949,6 +929,7 @@ pub struct NameBinding<'a> {
|
||||||
modifiers: DefModifiers,
|
modifiers: DefModifiers,
|
||||||
kind: NameBindingKind<'a>,
|
kind: NameBindingKind<'a>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
|
vis: ty::Visibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -968,13 +949,12 @@ struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
|
||||||
|
|
||||||
impl<'a> NameBinding<'a> {
|
impl<'a> NameBinding<'a> {
|
||||||
fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
|
fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
|
||||||
let modifiers = if module.is_public {
|
NameBinding {
|
||||||
DefModifiers::PUBLIC
|
modifiers: DefModifiers::IMPORTABLE,
|
||||||
} else {
|
kind: NameBindingKind::Module(module),
|
||||||
DefModifiers::empty()
|
span: span,
|
||||||
} | DefModifiers::IMPORTABLE;
|
vis: module.vis,
|
||||||
|
}
|
||||||
NameBinding { modifiers: modifiers, kind: NameBindingKind::Module(module), span: span }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn module(&self) -> Option<Module<'a>> {
|
fn module(&self) -> Option<Module<'a>> {
|
||||||
|
@ -997,8 +977,20 @@ impl<'a> NameBinding<'a> {
|
||||||
self.modifiers.contains(modifiers)
|
self.modifiers.contains(modifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_public(&self) -> bool {
|
fn is_pseudo_public(&self) -> bool {
|
||||||
self.defined_with(DefModifiers::PUBLIC)
|
self.pseudo_vis() == ty::Visibility::Public
|
||||||
|
}
|
||||||
|
|
||||||
|
// We sometimes need to treat variants as `pub` for backwards compatibility
|
||||||
|
fn pseudo_vis(&self) -> ty::Visibility {
|
||||||
|
if self.is_variant() { ty::Visibility::Public } else { self.vis }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_variant(&self) -> bool {
|
||||||
|
match self.kind {
|
||||||
|
NameBindingKind::Def(Def::Variant(..)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_extern_crate(&self) -> bool {
|
fn is_extern_crate(&self) -> bool {
|
||||||
|
@ -1148,8 +1140,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
arenas: &'a ResolverArenas<'a>)
|
arenas: &'a ResolverArenas<'a>)
|
||||||
-> Resolver<'a, 'tcx> {
|
-> Resolver<'a, 'tcx> {
|
||||||
let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
|
let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
|
||||||
|
let vis = ty::Visibility::Public;
|
||||||
let graph_root =
|
let graph_root =
|
||||||
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, true, arenas);
|
ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, vis, arenas);
|
||||||
let graph_root = arenas.alloc_module(graph_root);
|
let graph_root = arenas.alloc_module(graph_root);
|
||||||
|
|
||||||
Resolver {
|
Resolver {
|
||||||
|
@ -1209,17 +1202,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
parent_link: ParentLink<'a>,
|
parent_link: ParentLink<'a>,
|
||||||
def: Option<Def>,
|
def: Option<Def>,
|
||||||
external: bool,
|
external: bool,
|
||||||
is_public: bool) -> Module<'a> {
|
vis: ty::Visibility) -> Module<'a> {
|
||||||
self.arenas.alloc_module(ModuleS::new(parent_link, def, external, is_public, self.arenas))
|
self.arenas.alloc_module(ModuleS::new(parent_link, def, external, vis, self.arenas))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_extern_crate_module(&self,
|
fn new_extern_crate_module(&self,
|
||||||
parent_link: ParentLink<'a>,
|
parent_link: ParentLink<'a>,
|
||||||
def: Def,
|
def: Def,
|
||||||
is_public: bool,
|
vis: ty::Visibility,
|
||||||
local_node_id: NodeId)
|
local_node_id: NodeId)
|
||||||
-> Module<'a> {
|
-> Module<'a> {
|
||||||
let mut module = ModuleS::new(parent_link, Some(def), false, is_public, self.arenas);
|
let mut module = ModuleS::new(parent_link, Some(def), false, vis, self.arenas);
|
||||||
module.extern_crate_id = Some(local_node_id);
|
module.extern_crate_id = Some(local_node_id);
|
||||||
self.arenas.modules.alloc(module)
|
self.arenas.modules.alloc(module)
|
||||||
}
|
}
|
||||||
|
@ -1335,7 +1328,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
// Check to see whether there are type bindings, and, if
|
// Check to see whether there are type bindings, and, if
|
||||||
// so, whether there is a module within.
|
// so, whether there is a module within.
|
||||||
if let Some(module_def) = binding.module() {
|
if let Some(module_def) = binding.module() {
|
||||||
self.check_privacy(search_module, name, binding, span);
|
self.check_privacy(name, binding, span);
|
||||||
search_module = module_def;
|
search_module = module_def;
|
||||||
} else {
|
} else {
|
||||||
let msg = format!("Not a module `{}`", name);
|
let msg = format!("Not a module `{}`", name);
|
||||||
|
@ -1466,7 +1459,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the nearest normal module parent of the given module.
|
/// Returns the nearest normal module parent of the given module.
|
||||||
fn get_nearest_normal_module_parent(&mut self, module_: Module<'a>) -> Option<Module<'a>> {
|
fn get_nearest_normal_module_parent(&self, module_: Module<'a>) -> Option<Module<'a>> {
|
||||||
let mut module_ = module_;
|
let mut module_ = module_;
|
||||||
loop {
|
loop {
|
||||||
match module_.parent_link {
|
match module_.parent_link {
|
||||||
|
@ -1485,7 +1478,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
|
|
||||||
/// Returns the nearest normal module parent of the given module, or the
|
/// Returns the nearest normal module parent of the given module, or the
|
||||||
/// module itself if it is a normal module.
|
/// module itself if it is a normal module.
|
||||||
fn get_nearest_normal_module_parent_or_self(&mut self, module_: Module<'a>) -> Module<'a> {
|
fn get_nearest_normal_module_parent_or_self(&self, module_: Module<'a>) -> Module<'a> {
|
||||||
if module_.is_normal() {
|
if module_.is_normal() {
|
||||||
return module_;
|
return module_;
|
||||||
}
|
}
|
||||||
|
@ -1617,7 +1610,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
|
|
||||||
fn resolve_crate(&mut self, krate: &hir::Crate) {
|
fn resolve_crate(&mut self, krate: &hir::Crate) {
|
||||||
debug!("(resolving crate) starting");
|
debug!("(resolving crate) starting");
|
||||||
|
self.current_module = self.graph_root;
|
||||||
intravisit::walk_crate(self, krate);
|
intravisit::walk_crate(self, krate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1980,6 +1973,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
this.with_self_rib(Def::SelfTy(trait_id, Some((item_id, self_type.id))), |this| {
|
this.with_self_rib(Def::SelfTy(trait_id, Some((item_id, self_type.id))), |this| {
|
||||||
this.with_current_self_type(self_type, |this| {
|
this.with_current_self_type(self_type, |this| {
|
||||||
for impl_item in impl_items {
|
for impl_item in impl_items {
|
||||||
|
this.resolve_visibility(&impl_item.vis);
|
||||||
match impl_item.node {
|
match impl_item.node {
|
||||||
hir::ImplItemKind::Const(..) => {
|
hir::ImplItemKind::Const(..) => {
|
||||||
// If this is a trait impl, ensure the const
|
// If this is a trait impl, ensure the const
|
||||||
|
@ -2772,7 +2766,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
let name = segments.last().unwrap().identifier.name;
|
let name = segments.last().unwrap().identifier.name;
|
||||||
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
|
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
|
||||||
result.success().map(|binding| {
|
result.success().map(|binding| {
|
||||||
self.check_privacy(containing_module, name, binding, span);
|
self.check_privacy(name, binding, span);
|
||||||
binding.def().unwrap()
|
binding.def().unwrap()
|
||||||
}).ok_or(false)
|
}).ok_or(false)
|
||||||
}
|
}
|
||||||
|
@ -2822,7 +2816,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
let name = segments.last().unwrap().identifier.name;
|
let name = segments.last().unwrap().identifier.name;
|
||||||
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
|
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
|
||||||
result.success().map(|binding| {
|
result.success().map(|binding| {
|
||||||
self.check_privacy(containing_module, name, binding, span);
|
self.check_privacy(name, binding, span);
|
||||||
binding.def().unwrap()
|
binding.def().unwrap()
|
||||||
}).ok_or(false)
|
}).ok_or(false)
|
||||||
}
|
}
|
||||||
|
@ -3314,7 +3308,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
// only if both the module is public and the entity is
|
// only if both the module is public and the entity is
|
||||||
// declared as public (due to pruning, we don't explore
|
// declared as public (due to pruning, we don't explore
|
||||||
// outside crate private modules => no need to check this)
|
// outside crate private modules => no need to check this)
|
||||||
if !in_module_is_extern || name_binding.is_public() {
|
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
||||||
lookup_results.push(path);
|
lookup_results.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3339,7 +3333,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !in_module_is_extern || name_binding.is_public() {
|
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
||||||
// add the module to the lookup
|
// add the module to the lookup
|
||||||
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
|
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
|
||||||
worklist.push((module, path_segments, is_extern));
|
worklist.push((module, path_segments, is_extern));
|
||||||
|
@ -3379,16 +3373,51 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_visible(&self, binding: &'a NameBinding<'a>, parent: Module<'a>) -> bool {
|
fn resolve_visibility(&mut self, vis: &hir::Visibility) -> ty::Visibility {
|
||||||
binding.is_public() || parent.is_ancestor_of(self.current_module)
|
let (path, id) = match *vis {
|
||||||
|
hir::Public => return ty::Visibility::Public,
|
||||||
|
hir::Visibility::Crate => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
|
||||||
|
hir::Visibility::Restricted { ref path, id } => (path, id),
|
||||||
|
hir::Inherited => {
|
||||||
|
let current_module =
|
||||||
|
self.get_nearest_normal_module_parent_or_self(self.current_module);
|
||||||
|
let id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
|
||||||
|
return ty::Visibility::Restricted(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let segments: Vec<_> = path.segments.iter().map(|seg| seg.identifier.name).collect();
|
||||||
|
let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, path.span) {
|
||||||
|
Success(module) => {
|
||||||
|
let def = module.def.unwrap();
|
||||||
|
let path_resolution = PathResolution { base_def: def, depth: 0 };
|
||||||
|
self.def_map.borrow_mut().insert(id, path_resolution);
|
||||||
|
ty::Visibility::Restricted(self.ast_map.as_local_node_id(def.def_id()).unwrap())
|
||||||
|
}
|
||||||
|
Failed(Some((span, msg))) => {
|
||||||
|
self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
|
||||||
|
ty::Visibility::Public
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.session.span_err(path.span, "unresolved module path");
|
||||||
|
ty::Visibility::Public
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !self.is_accessible(vis) {
|
||||||
|
let msg = format!("visibilities can only be restricted to ancestor modules");
|
||||||
|
self.session.span_err(path.span, &msg);
|
||||||
|
}
|
||||||
|
vis
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_privacy(&mut self,
|
fn is_accessible(&self, vis: ty::Visibility) -> bool {
|
||||||
module: Module<'a>,
|
let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
|
||||||
name: Name,
|
let node_id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap();
|
||||||
binding: &'a NameBinding<'a>,
|
vis.is_accessible_from(node_id, &self.ast_map)
|
||||||
span: Span) {
|
}
|
||||||
if !self.is_visible(binding, module) {
|
|
||||||
|
fn check_privacy(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Span) {
|
||||||
|
if !self.is_accessible(binding.vis) {
|
||||||
self.privacy_errors.push(PrivacyError(span, name, binding));
|
self.privacy_errors.push(PrivacyError(span, name, binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use UseLexicalScopeFlag::DontUseLexicalScope;
|
||||||
use {names_to_string, module_to_string};
|
use {names_to_string, module_to_string};
|
||||||
use {resolve_error, ResolutionError};
|
use {resolve_error, ResolutionError};
|
||||||
|
|
||||||
|
use rustc::ty;
|
||||||
use rustc::lint;
|
use rustc::lint;
|
||||||
use rustc::hir::def::*;
|
use rustc::hir::def::*;
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ pub struct ImportDirective<'a> {
|
||||||
subclass: ImportDirectiveSubclass,
|
subclass: ImportDirectiveSubclass,
|
||||||
span: Span,
|
span: Span,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
is_public: bool, // see note in ImportResolutionPerNamespace about how to use this
|
vis: ty::Visibility, // see note in ImportResolutionPerNamespace about how to use this
|
||||||
is_prelude: bool,
|
is_prelude: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,10 +73,7 @@ impl<'a> ImportDirective<'a> {
|
||||||
// this returns the binding for the name this directive defines in that namespace.
|
// this returns the binding for the name this directive defines in that namespace.
|
||||||
fn import(&self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
|
fn import(&self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
|
||||||
-> NameBinding<'a> {
|
-> NameBinding<'a> {
|
||||||
let mut modifiers = match self.is_public {
|
let mut modifiers = DefModifiers::IMPORTABLE;
|
||||||
true => DefModifiers::PUBLIC | DefModifiers::IMPORTABLE,
|
|
||||||
false => DefModifiers::empty(),
|
|
||||||
};
|
|
||||||
if let GlobImport = self.subclass {
|
if let GlobImport = self.subclass {
|
||||||
modifiers = modifiers | DefModifiers::GLOB_IMPORTED;
|
modifiers = modifiers | DefModifiers::GLOB_IMPORTED;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +86,7 @@ impl<'a> ImportDirective<'a> {
|
||||||
},
|
},
|
||||||
span: Some(self.span),
|
span: Some(self.span),
|
||||||
modifiers: modifiers,
|
modifiers: modifiers,
|
||||||
|
vis: self.vis,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,8 +183,8 @@ impl<'a> NameResolution<'a> {
|
||||||
// If (1) we don't allow private imports, (2) no public single import can define
|
// If (1) we don't allow private imports, (2) no public single import can define
|
||||||
// the name, and (3) no public glob has defined the name, the resolution depends
|
// the name, and (3) no public glob has defined the name, the resolution depends
|
||||||
// on whether more globs can define the name.
|
// on whether more globs can define the name.
|
||||||
if !allow_private_imports && !directive.is_public &&
|
if !allow_private_imports && directive.vis != ty::Visibility::Public &&
|
||||||
!self.binding.map(NameBinding::is_public).unwrap_or(false) {
|
!self.binding.map(NameBinding::is_pseudo_public).unwrap_or(false) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,14 +242,15 @@ impl<'a> ::ModuleS<'a> {
|
||||||
if let Some(result) = resolution.try_result(ns, allow_private_imports) {
|
if let Some(result) = resolution.try_result(ns, allow_private_imports) {
|
||||||
// If the resolution doesn't depend on glob definability, check privacy and return.
|
// If the resolution doesn't depend on glob definability, check privacy and return.
|
||||||
return result.and_then(|binding| {
|
return result.and_then(|binding| {
|
||||||
let allowed = allow_private_imports || !binding.is_import() || binding.is_public();
|
let allowed = allow_private_imports || !binding.is_import() ||
|
||||||
|
binding.is_pseudo_public();
|
||||||
if allowed { Success(binding) } else { Failed(None) }
|
if allowed { Success(binding) } else { Failed(None) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the globs are determined
|
// Check if the globs are determined
|
||||||
for directive in self.globs.borrow().iter() {
|
for directive in self.globs.borrow().iter() {
|
||||||
if !allow_private_imports && !directive.is_public { continue }
|
if !allow_private_imports && directive.vis != ty::Visibility::Public { continue }
|
||||||
match directive.target_module.get() {
|
match directive.target_module.get() {
|
||||||
None => return Indeterminate,
|
None => return Indeterminate,
|
||||||
Some(target_module) => match target_module.resolve_name(name, ns, false) {
|
Some(target_module) => match target_module.resolve_name(name, ns, false) {
|
||||||
|
@ -285,7 +285,7 @@ impl<'a> ::ModuleS<'a> {
|
||||||
subclass: ImportDirectiveSubclass,
|
subclass: ImportDirectiveSubclass,
|
||||||
span: Span,
|
span: Span,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
is_public: bool,
|
vis: ty::Visibility,
|
||||||
is_prelude: bool) {
|
is_prelude: bool) {
|
||||||
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||||
module_path: module_path,
|
module_path: module_path,
|
||||||
|
@ -293,7 +293,7 @@ impl<'a> ::ModuleS<'a> {
|
||||||
subclass: subclass,
|
subclass: subclass,
|
||||||
span: span,
|
span: span,
|
||||||
id: id,
|
id: id,
|
||||||
is_public: is_public,
|
vis: vis,
|
||||||
is_prelude: is_prelude,
|
is_prelude: is_prelude,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ impl<'a> ::ModuleS<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
|
fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
|
||||||
if !binding.defined_with(DefModifiers::PUBLIC | DefModifiers::IMPORTABLE) { return }
|
if !binding.defined_with(DefModifiers::IMPORTABLE) || !binding.is_pseudo_public() { return }
|
||||||
for &(importer, directive) in self.glob_importers.borrow_mut().iter() {
|
for &(importer, directive) in self.glob_importers.borrow_mut().iter() {
|
||||||
let _ = importer.try_define_child(name, ns, directive.import(binding, None));
|
let _ = importer.try_define_child(name, ns, directive.import(binding, None));
|
||||||
}
|
}
|
||||||
|
@ -413,6 +413,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||||
modifiers: DefModifiers::GLOB_IMPORTED,
|
modifiers: DefModifiers::GLOB_IMPORTED,
|
||||||
kind: NameBindingKind::Def(Def::Err),
|
kind: NameBindingKind::Def(Def::Err),
|
||||||
span: None,
|
span: None,
|
||||||
|
vis: ty::Visibility::Public,
|
||||||
});
|
});
|
||||||
let dummy_binding = e.import_directive.import(dummy_binding, None);
|
let dummy_binding = e.import_directive.import(dummy_binding, None);
|
||||||
|
|
||||||
|
@ -521,7 +522,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||||
span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
|
span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let privacy_error = if !self.resolver.is_visible(binding, target_module) {
|
let privacy_error = if !self.resolver.is_accessible(binding.vis) {
|
||||||
Some(Box::new(PrivacyError(directive.span, source, binding)))
|
Some(Box::new(PrivacyError(directive.span, source, binding)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -567,10 +568,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ast_map = self.resolver.ast_map;
|
||||||
match (&value_result, &type_result) {
|
match (&value_result, &type_result) {
|
||||||
(&Success(name_binding), _) if !name_binding.is_import() &&
|
(&Success(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
|
||||||
directive.is_public &&
|
self.resolver.is_accessible(binding.vis) => {
|
||||||
!name_binding.is_public() => {
|
|
||||||
let msg = format!("`{}` is private, and cannot be reexported", source);
|
let msg = format!("`{}` is private, and cannot be reexported", source);
|
||||||
let note_msg = format!("consider marking `{}` as `pub` in the imported module",
|
let note_msg = format!("consider marking `{}` as `pub` in the imported module",
|
||||||
source);
|
source);
|
||||||
|
@ -579,10 +580,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, &Success(name_binding)) if !name_binding.is_import() &&
|
(_, &Success(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, ast_map) &&
|
||||||
directive.is_public &&
|
self.resolver.is_accessible(binding.vis) => {
|
||||||
!name_binding.is_public() => {
|
if binding.is_extern_crate() {
|
||||||
if name_binding.is_extern_crate() {
|
|
||||||
let msg = format!("extern crate `{}` is private, and cannot be reexported \
|
let msg = format!("extern crate `{}` is private, and cannot be reexported \
|
||||||
(error E0364), consider declaring with `pub`",
|
(error E0364), consider declaring with `pub`",
|
||||||
source);
|
source);
|
||||||
|
@ -662,7 +662,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||||
resolution.borrow().binding().map(|binding| (*name, binding))
|
resolution.borrow().binding().map(|binding| (*name, binding))
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
for ((name, ns), binding) in bindings {
|
for ((name, ns), binding) in bindings {
|
||||||
if binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) {
|
if binding.defined_with(DefModifiers::IMPORTABLE) && binding.is_pseudo_public() {
|
||||||
let _ = module_.try_define_child(name, ns, directive.import(binding, None));
|
let _ = module_.try_define_child(name, ns, directive.import(binding, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -698,15 +698,16 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
if binding.is_public() && (binding.is_import() || binding.is_extern_crate()) {
|
if binding.vis == ty::Visibility::Public &&
|
||||||
|
(binding.is_import() || binding.is_extern_crate()) {
|
||||||
if let Some(def) = binding.def() {
|
if let Some(def) = binding.def() {
|
||||||
reexports.push(Export { name: name, def_id: def.def_id() });
|
reexports.push(Export { name: name, def_id: def.def_id() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let NameBindingKind::Import { binding: orig_binding, id, .. } = binding.kind {
|
if let NameBindingKind::Import { binding: orig_binding, id, .. } = binding.kind {
|
||||||
if ns == TypeNS && binding.is_public() &&
|
if ns == TypeNS && orig_binding.is_variant() &&
|
||||||
orig_binding.defined_with(DefModifiers::PRIVATE_VARIANT) {
|
!orig_binding.vis.is_at_least(binding.vis, &self.resolver.ast_map) {
|
||||||
let msg = format!("variant `{}` is private, and cannot be reexported \
|
let msg = format!("variant `{}` is private, and cannot be reexported \
|
||||||
(error E0364), consider declaring its enum as `pub`",
|
(error E0364), consider declaring its enum as `pub`",
|
||||||
name);
|
name);
|
||||||
|
|
|
@ -122,7 +122,7 @@ fn try_inline_def(cx: &DocContext, tcx: &TyCtxt,
|
||||||
name: Some(tcx.item_name(did).to_string()),
|
name: Some(tcx.item_name(did).to_string()),
|
||||||
attrs: load_attrs(cx, tcx, did),
|
attrs: load_attrs(cx, tcx, did),
|
||||||
inner: inner,
|
inner: inner,
|
||||||
visibility: Some(hir::Public),
|
visibility: Some(clean::Public),
|
||||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
|
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
|
@ -323,7 +323,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
source: clean::Span::empty(),
|
source: clean::Span::empty(),
|
||||||
name: None,
|
name: None,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
visibility: Some(hir::Inherited),
|
visibility: Some(clean::Inherited),
|
||||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
|
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
|
@ -444,7 +444,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
source: clean::Span::empty(),
|
source: clean::Span::empty(),
|
||||||
name: None,
|
name: None,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
visibility: Some(hir::Inherited),
|
visibility: Some(clean::Inherited),
|
||||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
|
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub use self::Attribute::*;
|
||||||
pub use self::TyParamBound::*;
|
pub use self::TyParamBound::*;
|
||||||
pub use self::SelfTy::*;
|
pub use self::SelfTy::*;
|
||||||
pub use self::FunctionRetTy::*;
|
pub use self::FunctionRetTy::*;
|
||||||
|
pub use self::Visibility::*;
|
||||||
|
|
||||||
use syntax;
|
use syntax;
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
|
@ -183,7 +184,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
|
||||||
source: Span::empty(),
|
source: Span::empty(),
|
||||||
name: Some(prim.to_url_str().to_string()),
|
name: Some(prim.to_url_str().to_string()),
|
||||||
attrs: child.attrs.clone(),
|
attrs: child.attrs.clone(),
|
||||||
visibility: Some(hir::Public),
|
visibility: Some(Public),
|
||||||
stability: None,
|
stability: None,
|
||||||
deprecation: None,
|
deprecation: None,
|
||||||
def_id: DefId::local(prim.to_def_index()),
|
def_id: DefId::local(prim.to_def_index()),
|
||||||
|
@ -1391,7 +1392,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
name: Some(self.name.clean(cx)),
|
name: Some(self.name.clean(cx)),
|
||||||
visibility: Some(hir::Inherited),
|
visibility: Some(Inherited),
|
||||||
stability: get_stability(cx, self.def_id),
|
stability: get_stability(cx, self.def_id),
|
||||||
deprecation: get_deprecation(cx, self.def_id),
|
deprecation: get_deprecation(cx, self.def_id),
|
||||||
def_id: self.def_id,
|
def_id: self.def_id,
|
||||||
|
@ -1777,17 +1778,21 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Visibility = hir::Visibility;
|
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
|
||||||
|
pub enum Visibility {
|
||||||
|
Public,
|
||||||
|
Inherited,
|
||||||
|
}
|
||||||
|
|
||||||
impl Clean<Option<Visibility>> for hir::Visibility {
|
impl Clean<Option<Visibility>> for hir::Visibility {
|
||||||
fn clean(&self, _: &DocContext) -> Option<Visibility> {
|
fn clean(&self, _: &DocContext) -> Option<Visibility> {
|
||||||
Some(self.clone())
|
Some(if *self == hir::Visibility::Public { Public } else { Inherited })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<Option<Visibility>> for ty::Visibility {
|
impl Clean<Option<Visibility>> for ty::Visibility {
|
||||||
fn clean(&self, _: &DocContext) -> Option<Visibility> {
|
fn clean(&self, _: &DocContext) -> Option<Visibility> {
|
||||||
Some(if *self == ty::Visibility::Public { hir::Public } else { hir::Inherited })
|
Some(if *self == ty::Visibility::Public { Public } else { Inherited })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1919,7 +1924,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
|
||||||
name: Some(self.name.clean(cx)),
|
name: Some(self.name.clean(cx)),
|
||||||
attrs: inline::load_attrs(cx, cx.tcx(), self.did),
|
attrs: inline::load_attrs(cx, cx.tcx(), self.did),
|
||||||
source: Span::empty(),
|
source: Span::empty(),
|
||||||
visibility: Some(hir::Inherited),
|
visibility: Some(Inherited),
|
||||||
def_id: self.did,
|
def_id: self.did,
|
||||||
inner: VariantItem(Variant { kind: kind }),
|
inner: VariantItem(Variant { kind: kind }),
|
||||||
stability: get_stability(cx, self.did),
|
stability: get_stability(cx, self.did),
|
||||||
|
@ -2341,7 +2346,7 @@ impl Clean<Item> for doctree::DefaultImpl {
|
||||||
attrs: self.attrs.clean(cx),
|
attrs: self.attrs.clean(cx),
|
||||||
source: self.whence.clean(cx),
|
source: self.whence.clean(cx),
|
||||||
def_id: cx.map.local_def_id(self.id),
|
def_id: cx.map.local_def_id(self.id),
|
||||||
visibility: Some(hir::Public),
|
visibility: Some(Public),
|
||||||
stability: None,
|
stability: None,
|
||||||
deprecation: None,
|
deprecation: None,
|
||||||
inner: DefaultImplItem(DefaultImpl {
|
inner: DefaultImplItem(DefaultImpl {
|
||||||
|
@ -2700,7 +2705,7 @@ impl Clean<Item> for doctree::Macro {
|
||||||
name: Some(name.clone()),
|
name: Some(name.clone()),
|
||||||
attrs: self.attrs.clean(cx),
|
attrs: self.attrs.clean(cx),
|
||||||
source: self.whence.clean(cx),
|
source: self.whence.clean(cx),
|
||||||
visibility: hir::Public.clean(cx),
|
visibility: Some(Public),
|
||||||
stability: self.stab.clean(cx),
|
stability: self.stab.clean(cx),
|
||||||
deprecation: self.depr.clean(cx),
|
deprecation: self.depr.clean(cx),
|
||||||
def_id: cx.map.local_def_id(self.id),
|
def_id: cx.map.local_def_id(self.id),
|
||||||
|
|
|
@ -31,7 +31,7 @@ use html::render::{cache, CURRENT_LOCATION_KEY};
|
||||||
/// Helper to render an optional visibility with a space after it (if the
|
/// Helper to render an optional visibility with a space after it (if the
|
||||||
/// visibility is preset)
|
/// visibility is preset)
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct VisSpace<'a>(pub &'a Option<hir::Visibility>);
|
pub struct VisSpace<'a>(pub &'a Option<clean::Visibility>);
|
||||||
/// Similarly to VisSpace, this structure is used to render a function style with a
|
/// Similarly to VisSpace, this structure is used to render a function style with a
|
||||||
/// space after it.
|
/// space after it.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -57,7 +57,7 @@ pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
|
||||||
pub struct AbiSpace(pub Abi);
|
pub struct AbiSpace(pub Abi);
|
||||||
|
|
||||||
impl<'a> VisSpace<'a> {
|
impl<'a> VisSpace<'a> {
|
||||||
pub fn get(self) -> &'a Option<hir::Visibility> {
|
pub fn get(self) -> &'a Option<clean::Visibility> {
|
||||||
let VisSpace(v) = self; v
|
let VisSpace(v) = self; v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -639,8 +639,8 @@ impl<'a> fmt::Display for Method<'a> {
|
||||||
impl<'a> fmt::Display for VisSpace<'a> {
|
impl<'a> fmt::Display for VisSpace<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self.get() {
|
match *self.get() {
|
||||||
Some(hir::Public) => write!(f, "pub "),
|
Some(clean::Public) => write!(f, "pub "),
|
||||||
Some(hir::Inherited) | None => Ok(())
|
Some(clean::Inherited) | None => Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1408,7 +1408,8 @@ impl Context {
|
||||||
match it.inner {
|
match it.inner {
|
||||||
clean::StrippedItem(..) => true,
|
clean::StrippedItem(..) => true,
|
||||||
clean::ModuleItem(ref m) => {
|
clean::ModuleItem(ref m) => {
|
||||||
it.doc_value().is_none() && m.items.is_empty() && it.visibility != Some(hir::Public)
|
it.doc_value().is_none() && m.items.is_empty()
|
||||||
|
&& it.visibility != Some(clean::Public)
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ use rustc::util::nodemap::DefIdSet;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::string::String;
|
use std::string::String;
|
||||||
use std::usize;
|
use std::usize;
|
||||||
use rustc::hir;
|
|
||||||
|
|
||||||
use clean::{self, Attributes, GetDefId};
|
use clean::{self, Attributes, GetDefId};
|
||||||
use clean::Item;
|
use clean::Item;
|
||||||
|
@ -133,13 +132,13 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
clean::StructFieldItem(..) => {
|
clean::StructFieldItem(..) => {
|
||||||
if i.visibility != Some(hir::Public) {
|
if i.visibility != Some(clean::Public) {
|
||||||
return Strip(i).fold();
|
return Strip(i).fold();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clean::ModuleItem(..) => {
|
clean::ModuleItem(..) => {
|
||||||
if i.def_id.is_local() && i.visibility != Some(hir::Public) {
|
if i.def_id.is_local() && i.visibility != Some(clean::Public) {
|
||||||
return Strip(self.fold_item_recur(i).unwrap()).fold()
|
return Strip(self.fold_item_recur(i).unwrap()).fold()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +225,7 @@ impl fold::DocFolder for ImportStripper {
|
||||||
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||||
match i.inner {
|
match i.inner {
|
||||||
clean::ExternCrateItem(..) |
|
clean::ExternCrateItem(..) |
|
||||||
clean::ImportItem(..) if i.visibility != Some(hir::Public) => None,
|
clean::ImportItem(..) if i.visibility != Some(clean::Public) => None,
|
||||||
_ => self.fold_item_recur(i)
|
_ => self.fold_item_recur(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1887,7 +1887,7 @@ pub struct PolyTraitRef {
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum Visibility {
|
pub enum Visibility {
|
||||||
Public,
|
Public,
|
||||||
Crate,
|
Crate(Span),
|
||||||
Restricted { path: P<Path>, id: NodeId },
|
Restricted { path: P<Path>, id: NodeId },
|
||||||
Inherited,
|
Inherited,
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
|
||||||
|
|
||||||
// impl specialization (RFC 1210)
|
// impl specialization (RFC 1210)
|
||||||
("specialization", "1.7.0", Some(31844), Active),
|
("specialization", "1.7.0", Some(31844), Active),
|
||||||
|
|
||||||
|
// pub(restricted) visibilities (RFC 1422)
|
||||||
|
("pub_restricted", "1.9.0", Some(32409), Active),
|
||||||
];
|
];
|
||||||
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
||||||
|
|
||||||
|
@ -608,6 +611,7 @@ pub struct Features {
|
||||||
pub deprecated: bool,
|
pub deprecated: bool,
|
||||||
pub question_mark: bool,
|
pub question_mark: bool,
|
||||||
pub specialization: bool,
|
pub specialization: bool,
|
||||||
|
pub pub_restricted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Features {
|
impl Features {
|
||||||
|
@ -644,6 +648,7 @@ impl Features {
|
||||||
deprecated: false,
|
deprecated: false,
|
||||||
question_mark: false,
|
question_mark: false,
|
||||||
specialization: false,
|
specialization: false,
|
||||||
|
pub_restricted: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1159,6 +1164,15 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
|
||||||
}
|
}
|
||||||
visit::walk_impl_item(self, ii);
|
visit::walk_impl_item(self, ii);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_vis(&mut self, vis: &'v ast::Visibility) {
|
||||||
|
let span = match *vis {
|
||||||
|
ast::Visibility::Crate(span) => span,
|
||||||
|
ast::Visibility::Restricted { ref path, .. } => path.span,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
self.gate_feature("pub_restricted", span, "`pub(restricted)` syntax is experimental");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
|
fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
|
||||||
|
@ -1256,6 +1270,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
|
||||||
deprecated: cx.has_feature("deprecated"),
|
deprecated: cx.has_feature("deprecated"),
|
||||||
question_mark: cx.has_feature("question_mark"),
|
question_mark: cx.has_feature("question_mark"),
|
||||||
specialization: cx.has_feature("specialization"),
|
specialization: cx.has_feature("specialization"),
|
||||||
|
pub_restricted: cx.has_feature("pub_restricted"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -850,7 +850,7 @@ pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructF
|
||||||
span: fld.new_span(f.span),
|
span: fld.new_span(f.span),
|
||||||
id: fld.new_id(f.id),
|
id: fld.new_id(f.id),
|
||||||
ident: f.ident.map(|ident| fld.fold_ident(ident)),
|
ident: f.ident.map(|ident| fld.fold_ident(ident)),
|
||||||
vis: f.vis,
|
vis: fld.fold_vis(f.vis),
|
||||||
ty: fld.fold_ty(f.ty),
|
ty: fld.fold_ty(f.ty),
|
||||||
attrs: fold_attrs(f.attrs, fld),
|
attrs: fold_attrs(f.attrs, fld),
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ bitflags! {
|
||||||
const RESTRICTION_STMT_EXPR = 1 << 0,
|
const RESTRICTION_STMT_EXPR = 1 << 0,
|
||||||
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
|
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
|
||||||
const NO_NONINLINE_MOD = 1 << 2,
|
const NO_NONINLINE_MOD = 1 << 2,
|
||||||
|
const ALLOW_MODULE_PATHS = 1 << 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,7 +561,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
|
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
|
||||||
self.check_strict_keywords();
|
if !self.restrictions.contains(Restrictions::ALLOW_MODULE_PATHS) {
|
||||||
|
self.check_strict_keywords();
|
||||||
|
}
|
||||||
self.check_reserved_keywords();
|
self.check_reserved_keywords();
|
||||||
match self.token {
|
match self.token {
|
||||||
token::Ident(i, _) => {
|
token::Ident(i, _) => {
|
||||||
|
@ -4937,7 +4940,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let mut attrs = self.parse_outer_attributes()?;
|
let mut attrs = self.parse_outer_attributes()?;
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
let vis = self.parse_visibility()?;
|
let vis = self.parse_visibility(true)?;
|
||||||
let defaultness = self.parse_defaultness()?;
|
let defaultness = self.parse_defaultness()?;
|
||||||
let (name, node) = if self.eat_keyword(keywords::Type) {
|
let (name, node) = if self.eat_keyword(keywords::Type) {
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
|
@ -5249,7 +5252,7 @@ impl<'a> Parser<'a> {
|
||||||
|p| {
|
|p| {
|
||||||
let attrs = p.parse_outer_attributes()?;
|
let attrs = p.parse_outer_attributes()?;
|
||||||
let lo = p.span.lo;
|
let lo = p.span.lo;
|
||||||
let vis = p.parse_visibility()?;
|
let vis = p.parse_visibility(false)?;
|
||||||
let ty = p.parse_ty_sum()?;
|
let ty = p.parse_ty_sum()?;
|
||||||
Ok(StructField {
|
Ok(StructField {
|
||||||
span: mk_sp(lo, p.span.hi),
|
span: mk_sp(lo, p.span.hi),
|
||||||
|
@ -5289,20 +5292,26 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse an element of a struct definition
|
/// Parse an element of a struct definition
|
||||||
fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
|
fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
|
||||||
|
|
||||||
let attrs = self.parse_outer_attributes()?;
|
let attrs = self.parse_outer_attributes()?;
|
||||||
|
let vis = self.parse_visibility(true)?;
|
||||||
if self.eat_keyword(keywords::Pub) {
|
self.parse_single_struct_field(vis, attrs)
|
||||||
return self.parse_single_struct_field(Visibility::Public, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.parse_single_struct_field(Visibility::Inherited, attrs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse visibility: PUB or nothing
|
fn parse_visibility(&mut self, allow_restricted: bool) -> PResult<'a, Visibility> {
|
||||||
fn parse_visibility(&mut self) -> PResult<'a, Visibility> {
|
if !self.eat_keyword(keywords::Pub) {
|
||||||
if self.eat_keyword(keywords::Pub) { Ok(Visibility::Public) }
|
Ok(Visibility::Inherited)
|
||||||
else { Ok(Visibility::Inherited) }
|
} else if !allow_restricted || !self.eat(&token::OpenDelim(token::Paren)) {
|
||||||
|
Ok(Visibility::Public)
|
||||||
|
} else if self.eat_keyword(keywords::Crate) {
|
||||||
|
let span = self.last_span;
|
||||||
|
self.expect(&token::CloseDelim(token::Paren))?;
|
||||||
|
Ok(Visibility::Crate(span))
|
||||||
|
} else {
|
||||||
|
let path = self.with_res(Restrictions::ALLOW_MODULE_PATHS,
|
||||||
|
|this| this.parse_path(NoTypesAllowed))?;
|
||||||
|
self.expect(&token::CloseDelim(token::Paren))?;
|
||||||
|
Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse defaultness: DEFAULT or nothing
|
/// Parse defaultness: DEFAULT or nothing
|
||||||
|
@ -5764,7 +5773,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
|
|
||||||
let visibility = self.parse_visibility()?;
|
let visibility = self.parse_visibility(true)?;
|
||||||
|
|
||||||
if self.eat_keyword(keywords::Use) {
|
if self.eat_keyword(keywords::Use) {
|
||||||
// USE ITEM
|
// USE ITEM
|
||||||
|
@ -6014,7 +6023,7 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
|
fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
|
||||||
let attrs = self.parse_outer_attributes()?;
|
let attrs = self.parse_outer_attributes()?;
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
let visibility = self.parse_visibility()?;
|
let visibility = self.parse_visibility(true)?;
|
||||||
|
|
||||||
if self.check_keyword(keywords::Static) {
|
if self.check_keyword(keywords::Static) {
|
||||||
// FOREIGN STATIC ITEM
|
// FOREIGN STATIC ITEM
|
||||||
|
|
|
@ -435,7 +435,7 @@ pub fn mac_to_string(arg: &ast::Mac) -> String {
|
||||||
pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
|
pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
|
||||||
match *vis {
|
match *vis {
|
||||||
ast::Visibility::Public => format!("pub {}", s),
|
ast::Visibility::Public => format!("pub {}", s),
|
||||||
ast::Visibility::Crate => format!("pub(crate) {}", s),
|
ast::Visibility::Crate(_) => format!("pub(crate) {}", s),
|
||||||
ast::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
|
ast::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
|
||||||
ast::Visibility::Inherited => s.to_string()
|
ast::Visibility::Inherited => s.to_string()
|
||||||
}
|
}
|
||||||
|
@ -1386,7 +1386,7 @@ impl<'a> State<'a> {
|
||||||
pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
|
pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
|
||||||
match *vis {
|
match *vis {
|
||||||
ast::Visibility::Public => self.word_nbsp("pub"),
|
ast::Visibility::Public => self.word_nbsp("pub"),
|
||||||
ast::Visibility::Crate => self.word_nbsp("pub(crate)"),
|
ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"),
|
||||||
ast::Visibility::Restricted { ref path, .. } =>
|
ast::Visibility::Restricted { ref path, .. } =>
|
||||||
self.word_nbsp(&format!("pub({})", path)),
|
self.word_nbsp(&format!("pub({})", path)),
|
||||||
ast::Visibility::Inherited => Ok(())
|
ast::Visibility::Inherited => Ok(())
|
||||||
|
|
|
@ -231,6 +231,7 @@ pub fn walk_trait_ref<'v,V>(visitor: &mut V,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||||
|
visitor.visit_vis(&item.vis);
|
||||||
visitor.visit_ident(item.span, item.ident);
|
visitor.visit_ident(item.span, item.ident);
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemKind::ExternCrate(opt_name) => {
|
ItemKind::ExternCrate(opt_name) => {
|
||||||
|
@ -470,6 +471,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,
|
pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||||
foreign_item: &'v ForeignItem) {
|
foreign_item: &'v ForeignItem) {
|
||||||
|
visitor.visit_vis(&foreign_item.vis);
|
||||||
visitor.visit_ident(foreign_item.span, foreign_item.ident);
|
visitor.visit_ident(foreign_item.span, foreign_item.ident);
|
||||||
|
|
||||||
match foreign_item.node {
|
match foreign_item.node {
|
||||||
|
@ -592,6 +594,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) {
|
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
|
||||||
|
visitor.visit_vis(&impl_item.vis);
|
||||||
visitor.visit_ident(impl_item.span, impl_item.ident);
|
visitor.visit_ident(impl_item.span, impl_item.ident);
|
||||||
walk_list!(visitor, visit_attribute, &impl_item.attrs);
|
walk_list!(visitor, visit_attribute, &impl_item.attrs);
|
||||||
match impl_item.node {
|
match impl_item.node {
|
||||||
|
@ -619,6 +622,7 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||||
|
|
||||||
pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
|
pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||||
struct_field: &'v StructField) {
|
struct_field: &'v StructField) {
|
||||||
|
visitor.visit_vis(&struct_field.vis);
|
||||||
walk_opt_ident(visitor, struct_field.span, struct_field.ident);
|
walk_opt_ident(visitor, struct_field.span, struct_field.ident);
|
||||||
visitor.visit_ty(&struct_field.ty);
|
visitor.visit_ty(&struct_field.ty);
|
||||||
walk_list!(visitor, visit_attribute, &struct_field.attrs);
|
walk_list!(visitor, visit_attribute, &struct_field.attrs);
|
||||||
|
@ -812,8 +816,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) {
|
pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
|
||||||
match *vis {
|
if let Visibility::Restricted { ref path, id } = *vis {
|
||||||
Visibility::Restricted { ref path, id } => visitor.visit_path(path, id),
|
visitor.visit_path(path, id);
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
23
src/test/auxiliary/pub_restricted.rs
Normal file
23
src/test/auxiliary/pub_restricted.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
#![feature(pub_restricted)]
|
||||||
|
|
||||||
|
pub(crate) struct Crate;
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Universe {
|
||||||
|
pub x: i32,
|
||||||
|
pub(crate) y: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Universe {
|
||||||
|
pub fn f(&self) {}
|
||||||
|
pub(crate) fn g(&self) {}
|
||||||
|
}
|
25
src/test/compile-fail/privacy/restricted/feature-gate.rs
Normal file
25
src/test/compile-fail/privacy/restricted/feature-gate.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
pub(crate) //~ ERROR experimental
|
||||||
|
mod foo {}
|
||||||
|
|
||||||
|
pub(self) //~ ERROR experimental
|
||||||
|
mod bar {}
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
pub(self) x: i32, //~ ERROR experimental
|
||||||
|
}
|
||||||
|
impl S {
|
||||||
|
pub(self) fn f() {} //~ ERROR experimental
|
||||||
|
}
|
||||||
|
extern {
|
||||||
|
pub(self) fn f(); //~ ERROR experimental
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
#![feature(rustc_attrs, pub_restricted)]
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
pub use foo::bar::S;
|
||||||
|
mod bar {
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct S {
|
||||||
|
pub(foo) x: i32,
|
||||||
|
}
|
||||||
|
impl S {
|
||||||
|
pub(foo) fn f(&self) -> i32 { 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct S2 {
|
||||||
|
pub(crate) x: bool,
|
||||||
|
}
|
||||||
|
impl S2 {
|
||||||
|
pub(crate) fn f(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::ops::Deref for S {
|
||||||
|
type Target = S2;
|
||||||
|
fn deref(&self) -> &S2 { unimplemented!() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_error]
|
||||||
|
fn main() { //~ ERROR compilation successful
|
||||||
|
let s = foo::S::default();
|
||||||
|
let _: bool = s.x;
|
||||||
|
let _: bool = s.f();
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
#![feature(pub_restricted)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
struct Priv;
|
||||||
|
mod bar {
|
||||||
|
use foo::Priv;
|
||||||
|
pub(super) fn f(_: Priv) {}
|
||||||
|
pub(crate) fn f(_: Priv) {} //~ ERROR private
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
#![feature(pub_restricted)]
|
||||||
|
#![deny(private_in_public)]
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
pub mod bar {
|
||||||
|
pub struct S {
|
||||||
|
pub(foo) x: i32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
use foo::bar::S;
|
||||||
|
S { x: 0 }; // ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use foo::bar::S;
|
||||||
|
S { x: 0 }; //~ ERROR private
|
||||||
|
}
|
62
src/test/compile-fail/privacy/restricted/test.rs
Normal file
62
src/test/compile-fail/privacy/restricted/test.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
// aux-build:pub_restricted.rs
|
||||||
|
|
||||||
|
#![feature(pub_restricted)]
|
||||||
|
#![deny(private_in_public)]
|
||||||
|
#![allow(warnings)]
|
||||||
|
extern crate pub_restricted;
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
pub mod bar {
|
||||||
|
pub(super) fn f() {}
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct S {
|
||||||
|
pub(super) x: i32,
|
||||||
|
}
|
||||||
|
impl S {
|
||||||
|
pub(super) fn f(&self) {}
|
||||||
|
pub(super) fn g() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn f() {
|
||||||
|
use foo::bar::S;
|
||||||
|
pub(self) use foo::bar::f; // ok
|
||||||
|
pub(super) use foo::bar::f as g; //~ ERROR cannot be reexported
|
||||||
|
S::default().x; // ok
|
||||||
|
S::default().f(); // ok
|
||||||
|
S::g(); // ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
use foo::bar::S;
|
||||||
|
use foo::bar::f; //~ ERROR private
|
||||||
|
S::default().x; //~ ERROR private
|
||||||
|
S::default().f(); //~ ERROR private
|
||||||
|
S::g(); //~ ERROR private
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use pub_restricted::Universe;
|
||||||
|
use pub_restricted::Crate; //~ ERROR private
|
||||||
|
|
||||||
|
let u = Universe::default();
|
||||||
|
let _ = u.x;
|
||||||
|
let _ = u.y; //~ ERROR private
|
||||||
|
u.f();
|
||||||
|
u.g(); //~ ERROR private
|
||||||
|
}
|
||||||
|
|
||||||
|
mod pathological {
|
||||||
|
pub(bad::path) mod m1 {} //~ ERROR failed to resolve module path
|
||||||
|
pub(foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue