]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_privacy/lib.rs
Auto merge of #27856 - nikomatsakis:move-def-id-to-rustc, r=eddyb
[rust.git] / src / librustc_privacy / lib.rs
index 2ffb4cbd4bfb07f472f88c2d21e77eb1dc30eb08..ff278f75951469649f90b519219e82a29ec44be4 100644 (file)
 // 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<ast::DefId>, msg: &str) -> CheckResult {
+    fn ensure_public(&self, span: Span, to_check: DefId,
+                     source_did: Option<DefId>, 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.