X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_privacy%2Flib.rs;h=ff278f75951469649f90b519219e82a29ec44be4;hb=db67cbe43dfce043c664c53d709b91252d5afc9e;hp=2ffb4cbd4bfb07f472f88c2d21e77eb1dc30eb08;hpb=4e9300c02b62cc8cc5ca909e8b867b5202e1e167;p=rust.git diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 2ffb4cbd4bf..ff278f75951 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -11,13 +11,13 @@ // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) #![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_privacy"] -#![unstable(feature = "rustc_private")] +#![unstable(feature = "rustc_private", issue = "27812")] #![staged_api] #![crate_type = "dylib"] #![crate_type = "rlib"] -#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/nightly/")] + html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] @@ -34,8 +34,8 @@ use std::mem::replace; use rustc::ast_map; -use rustc::metadata::csearch; use rustc::middle::def; +use rustc::middle::def_id::DefId; use rustc::middle::privacy::ImportUse::*; use rustc::middle::privacy::LastPrivate::*; use rustc::middle::privacy::PrivateDep::*; @@ -44,7 +44,6 @@ use rustc::util::nodemap::{NodeMap, NodeSet}; use syntax::ast; -use syntax::ast_util::{is_local, local_def}; use syntax::codemap::Span; use syntax::visit::{self, Visitor}; @@ -261,16 +260,16 @@ fn visit_item(&mut self, item: &ast::Item) { def::DefPrimTy(..) => true, def => { let did = def.def_id(); - !is_local(did) || + !did.is_local() || self.exported_items.contains(&did.node) } } } _ => true, }; - let tr = self.tcx.impl_trait_ref(local_def(item.id)); + let tr = self.tcx.impl_trait_ref(DefId::local(item.id)); let public_trait = tr.clone().map_or(false, |tr| { - !is_local(tr.def_id) || + !tr.def_id.is_local() || self.exported_items.contains(&tr.def_id.node) }); @@ -331,7 +330,7 @@ fn visit_item(&mut self, item: &ast::Item) { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { let did = def.def_id(); - if is_local(did) { + if did.is_local() { self.exported_items.insert(did.node); } } @@ -360,7 +359,7 @@ fn visit_mod(&mut self, m: &ast::Mod, _sp: Span, id: ast::NodeId) { if self.prev_exported { assert!(self.export_map.contains_key(&id), "wut {}", id); for export in self.export_map.get(&id).unwrap() { - if is_local(export.def_id) { + if export.def_id.is_local() { self.reexports.insert(export.def_id.node); } } @@ -401,8 +400,8 @@ fn nodestr(&self, id: ast::NodeId) -> String { // Determines whether the given definition is public from the point of view // of the current item. - fn def_privacy(&self, did: ast::DefId) -> PrivacyResult { - if !is_local(did) { + fn def_privacy(&self, did: DefId) -> PrivacyResult { + if !did.is_local() { if self.external_exports.contains(&did) { debug!("privacy - {:?} was externally exported", did); return Allowable; @@ -628,8 +627,8 @@ fn report_error(&self, result: CheckResult) -> bool { /// Guarantee that a particular definition is public. Returns a CheckResult /// which contains any errors found. These can be reported using `report_error`. /// If the result is `None`, no errors were found. - fn ensure_public(&self, span: Span, to_check: ast::DefId, - source_did: Option, msg: &str) -> CheckResult { + fn ensure_public(&self, span: Span, to_check: DefId, + source_did: Option, msg: &str) -> CheckResult { let id = match self.def_privacy(to_check) { ExternallyDenied => { return Some((span, format!("{} is private", msg), None)) @@ -662,7 +661,7 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId, }; let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def(); let did = def.def_id(); - assert!(is_local(did)); + assert!(did.is_local()); match self.tcx.map.get(did.node) { ast_map::NodeItem(item) => item, _ => self.tcx.sess.span_bug(item.span, @@ -688,28 +687,26 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId, // Checks that a field is in scope. fn check_field(&mut self, span: Span, - id: ast::DefId, + def: ty::AdtDef<'tcx>, + v: ty::VariantDef<'tcx>, name: FieldName) { - let fields = self.tcx.lookup_struct_fields(id); let field = match name { NamedField(f_name) => { - debug!("privacy - check named field {} in struct {:?}", f_name, id); - fields.iter().find(|f| f.name == f_name).unwrap() + debug!("privacy - check named field {} in struct {:?}", f_name, def); + v.field_named(f_name) } - UnnamedField(idx) => &fields[idx] + UnnamedField(idx) => &v.fields[idx] }; if field.vis == ast::Public || - (is_local(field.id) && self.private_accessible(field.id.node)) { + (field.did.is_local() && self.private_accessible(field.did.node)) { return } - let struct_type = self.tcx.lookup_item_type(id).ty; - let struct_desc = match struct_type.sty { - ty::TyStruct(_, _) => - format!("struct `{}`", self.tcx.item_path_str(id)), + let struct_desc = match def.adt_kind() { + ty::AdtKind::Struct => + format!("struct `{}`", self.tcx.item_path_str(def.did)), // struct variant fields have inherited visibility - ty::TyEnum(..) => return, - _ => self.tcx.sess.span_bug(span, "can't find struct for field") + ty::AdtKind::Enum => return }; let msg = match name { NamedField(name) => format!("field `{}` of {} is private", @@ -723,7 +720,7 @@ fn check_field(&mut self, // Given the ID of a method, checks to ensure it's in scope. fn check_static_method(&mut self, span: Span, - method_id: ast::DefId, + method_id: DefId, name: ast::Name) { // If the method is a default method, we need to use the def_id of // the default implementation. @@ -750,7 +747,7 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Name) { debug!("privacy - path {}", self.nodestr(path_id)); let path_res = *self.tcx.def_map.borrow().get(&path_id).unwrap(); let ck = |tyname: &str| { - let ck_public = |def: ast::DefId| { + let ck_public = |def: DefId| { debug!("privacy - ck_public {:?}", def); let origdid = path_res.def_id(); self.ensure_public(span, @@ -840,7 +837,7 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Name) { } // Checks that a method is in scope. - fn check_method(&mut self, span: Span, method_def_id: ast::DefId, + fn check_method(&mut self, span: Span, method_def_id: DefId, name: ast::Name) { match self.tcx.impl_or_trait_item(method_def_id).container() { ty::ImplContainer(_) => { @@ -862,11 +859,11 @@ fn visit_item(&mut self, item: &ast::Item) { if let ast::ViewPathList(ref prefix, ref list) = vpath.node { for pid in list { match pid.node { - ast::PathListIdent { id, name } => { + ast::PathListIdent { id, name, .. } => { debug!("privacy - ident item {}", id); self.check_path(pid.span, id, name.name); } - ast::PathListMod { id } => { + ast::PathListMod { id, .. } => { debug!("privacy - mod item {}", id); let name = prefix.segments.last().unwrap().identifier.name; self.check_path(pid.span, id, name); @@ -883,13 +880,19 @@ fn visit_item(&mut self, item: &ast::Item) { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { ast::ExprField(ref base, ident) => { - if let ty::TyStruct(id, _) = self.tcx.expr_ty_adjusted(&**base).sty { - self.check_field(expr.span, id, NamedField(ident.node.name)); + if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty { + self.check_field(expr.span, + def, + def.struct_variant(), + NamedField(ident.node.name)); } } ast::ExprTupField(ref base, idx) => { - if let ty::TyStruct(id, _) = self.tcx.expr_ty_adjusted(&**base).sty { - self.check_field(expr.span, id, UnnamedField(idx.node)); + if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty { + self.check_field(expr.span, + def, + def.struct_variant(), + UnnamedField(idx.node)); } } ast::ExprMethodCall(ident, _, _) => { @@ -898,67 +901,36 @@ fn visit_expr(&mut self, expr: &ast::Expr) { debug!("(privacy checking) checking impl method"); self.check_method(expr.span, method.def_id, ident.node.name); } - ast::ExprStruct(_, ref fields, _) => { - match self.tcx.expr_ty(expr).sty { - ty::TyStruct(ctor_id, _) => { - // RFC 736: ensure all unmentioned fields are visible. - // Rather than computing the set of unmentioned fields - // (i.e. `all_fields - fields`), just check them all. - let all_fields = self.tcx.lookup_struct_fields(ctor_id); - for field in all_fields { - self.check_field(expr.span, ctor_id, - NamedField(field.name)); - } - } - ty::TyEnum(_, _) => { - match self.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() { - def::DefVariant(_, variant_id, _) => { - for field in fields { - self.check_field(expr.span, variant_id, - NamedField(field.ident.node.name)); - } - } - _ => self.tcx.sess.span_bug(expr.span, - "resolve didn't \ - map enum struct \ - constructor to a \ - variant def"), - } - } - _ => self.tcx.sess.span_bug(expr.span, "struct expr \ - didn't have \ - struct type?!"), + ast::ExprStruct(..) => { + let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap(); + let variant = adt.variant_of_def(self.tcx.resolve_expr(expr)); + // RFC 736: ensure all unmentioned fields are visible. + // Rather than computing the set of unmentioned fields + // (i.e. `all_fields - fields`), just check them all. + for field in &variant.fields { + self.check_field(expr.span, adt, variant, NamedField(field.name)); } } ast::ExprPath(..) => { - let guard = |did: ast::DefId| { - let fields = self.tcx.lookup_struct_fields(did); - let any_priv = fields.iter().any(|f| { + + if let def::DefStruct(_) = self.tcx.resolve_expr(expr) { + let expr_ty = self.tcx.expr_ty(expr); + let def = match expr_ty.sty { + ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig { + output: ty::FnConverging(ty), .. + }), ..}) => ty, + _ => expr_ty + }.ty_adt_def().unwrap(); + let any_priv = def.struct_variant().fields.iter().any(|f| { f.vis != ast::Public && ( - !is_local(f.id) || - !self.private_accessible(f.id.node)) - }); + !f.did.is_local() || + !self.private_accessible(f.did.node)) + }); if any_priv { self.tcx.sess.span_err(expr.span, - "cannot invoke tuple struct constructor \ - with private fields"); - } - }; - match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { - Some(def::DefStruct(did)) => { - guard(if is_local(did) { - local_def(self.tcx.map.get_parent(did.node)) - } else { - // "tuple structs" with zero fields (such as - // `pub struct Foo;`) don't have a ctor_id, hence - // the unwrap_or to the same struct id. - let maybe_did = - csearch::get_tuple_struct_definition_if_ctor( - &self.tcx.sess.cstore, did); - maybe_did.unwrap_or(did) - }) + "cannot invoke tuple struct constructor \ + with private fields"); } - _ => {} } } _ => {} @@ -976,31 +948,12 @@ fn visit_pat(&mut self, pattern: &ast::Pat) { match pattern.node { ast::PatStruct(_, ref fields, _) => { - match self.tcx.pat_ty(pattern).sty { - ty::TyStruct(id, _) => { - for field in fields { - self.check_field(pattern.span, id, - NamedField(field.node.ident.name)); - } - } - ty::TyEnum(_, _) => { - match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) { - Some(def::DefVariant(_, variant_id, _)) => { - for field in fields { - self.check_field(pattern.span, variant_id, - NamedField(field.node.ident.name)); - } - } - _ => self.tcx.sess.span_bug(pattern.span, - "resolve didn't \ - map enum struct \ - pattern to a \ - variant def"), - } - } - _ => self.tcx.sess.span_bug(pattern.span, - "struct pattern didn't have \ - struct type?!"), + let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap(); + let def = self.tcx.def_map.borrow().get(&pattern.id).unwrap().full_def(); + let variant = adt.variant_of_def(def); + for field in fields { + self.check_field(pattern.span, adt, variant, + NamedField(field.node.ident.name)); } } @@ -1008,12 +961,15 @@ struct type?!"), // elsewhere). ast::PatEnum(_, Some(ref fields)) => { match self.tcx.pat_ty(pattern).sty { - ty::TyStruct(id, _) => { + ty::TyStruct(def, _) => { for (i, field) in fields.iter().enumerate() { if let ast::PatWild(..) = field.node { continue } - self.check_field(field.span, id, UnnamedField(i)); + self.check_field(field.span, + def, + def.struct_variant(), + UnnamedField(i)); } } ty::TyEnum(..) => { @@ -1212,7 +1168,7 @@ fn path_is_private_type(&self, path_id: ast::NodeId) -> bool { }; // A path can only be private if: // it's in this crate... - if !is_local(did) { + if !did.is_local() { return false } @@ -1321,7 +1277,7 @@ fn visit_item(&mut self, item: &ast::Item) { |tr| { let did = self.tcx.trait_ref_to_def_id(tr); - !is_local(did) || self.trait_is_public(did.node) + !did.is_local() || self.trait_is_public(did.node) }); // `true` iff this is a trait impl or at least one method is public.