]> git.lizzy.rs Git - rust.git/blob - src/librustc_privacy/lib.rs
Auto merge of #31785 - sanxiyn:gitmodules, r=alexcrichton
[rust.git] / src / librustc_privacy / lib.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![crate_name = "rustc_privacy"]
12 #![unstable(feature = "rustc_private", issue = "27812")]
13 #![crate_type = "dylib"]
14 #![crate_type = "rlib"]
15 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
16       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
17       html_root_url = "https://doc.rust-lang.org/nightly/")]
18 #![cfg_attr(not(stage0), deny(warnings))]
19
20 #![feature(rustc_diagnostic_macros)]
21 #![feature(rustc_private)]
22 #![feature(staged_api)]
23
24 #[macro_use] extern crate log;
25 #[macro_use] extern crate syntax;
26
27 extern crate rustc;
28 extern crate rustc_front;
29
30 use self::PrivacyResult::*;
31 use self::FieldName::*;
32
33 use std::cmp;
34 use std::mem::replace;
35
36 use rustc_front::hir::{self, PatKind};
37 use rustc_front::intravisit::{self, Visitor};
38
39 use rustc::dep_graph::DepNode;
40 use rustc::lint;
41 use rustc::middle::def::{self, Def};
42 use rustc::middle::def_id::DefId;
43 use rustc::middle::privacy::{AccessLevel, AccessLevels};
44 use rustc::middle::privacy::ImportUse::*;
45 use rustc::middle::privacy::LastPrivate::*;
46 use rustc::middle::privacy::PrivateDep::*;
47 use rustc::middle::privacy::ExternalExports;
48 use rustc::middle::ty;
49 use rustc::util::nodemap::{NodeMap, NodeSet};
50 use rustc::front::map as ast_map;
51
52 use syntax::ast;
53 use syntax::codemap::Span;
54
55 pub mod diagnostics;
56
57 type Context<'a, 'tcx> = (&'a ty::MethodMap<'tcx>, &'a def::ExportMap);
58
59 /// Result of a checking operation - None => no errors were found. Some => an
60 /// error and contains the span and message for reporting that error and
61 /// optionally the same for a note about the error.
62 type CheckResult = Option<(Span, String, Option<(Span, String)>)>;
63
64 ////////////////////////////////////////////////////////////////////////////////
65 /// The parent visitor, used to determine what's the parent of what (node-wise)
66 ////////////////////////////////////////////////////////////////////////////////
67
68 struct ParentVisitor<'a, 'tcx:'a> {
69     tcx: &'a ty::ctxt<'tcx>,
70     parents: NodeMap<ast::NodeId>,
71     curparent: ast::NodeId,
72 }
73
74 impl<'a, 'tcx, 'v> Visitor<'v> for ParentVisitor<'a, 'tcx> {
75     /// We want to visit items in the context of their containing
76     /// module and so forth, so supply a crate for doing a deep walk.
77     fn visit_nested_item(&mut self, item: hir::ItemId) {
78         self.visit_item(self.tcx.map.expect_item(item.id))
79     }
80     fn visit_item(&mut self, item: &hir::Item) {
81         self.parents.insert(item.id, self.curparent);
82
83         let prev = self.curparent;
84         match item.node {
85             hir::ItemMod(..) => { self.curparent = item.id; }
86             // Enum variants are parented to the enum definition itself because
87             // they inherit privacy
88             hir::ItemEnum(ref def, _) => {
89                 for variant in &def.variants {
90                     // The parent is considered the enclosing enum because the
91                     // enum will dictate the privacy visibility of this variant
92                     // instead.
93                     self.parents.insert(variant.node.data.id(), item.id);
94                 }
95             }
96
97             // Trait methods are always considered "public", but if the trait is
98             // private then we need some private item in the chain from the
99             // method to the root. In this case, if the trait is private, then
100             // parent all the methods to the trait to indicate that they're
101             // private.
102             hir::ItemTrait(_, _, _, ref trait_items) if item.vis != hir::Public => {
103                 for trait_item in trait_items {
104                     self.parents.insert(trait_item.id, item.id);
105                 }
106             }
107
108             _ => {}
109         }
110         intravisit::walk_item(self, item);
111         self.curparent = prev;
112     }
113
114     fn visit_foreign_item(&mut self, a: &hir::ForeignItem) {
115         self.parents.insert(a.id, self.curparent);
116         intravisit::walk_foreign_item(self, a);
117     }
118
119     fn visit_fn(&mut self, a: intravisit::FnKind<'v>, b: &'v hir::FnDecl,
120                 c: &'v hir::Block, d: Span, id: ast::NodeId) {
121         // We already took care of some trait methods above, otherwise things
122         // like impl methods and pub trait methods are parented to the
123         // containing module, not the containing trait.
124         if !self.parents.contains_key(&id) {
125             self.parents.insert(id, self.curparent);
126         }
127         intravisit::walk_fn(self, a, b, c, d);
128     }
129
130     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
131         // visit_fn handles methods, but associated consts have to be handled
132         // here.
133         if !self.parents.contains_key(&ii.id) {
134             self.parents.insert(ii.id, self.curparent);
135         }
136         intravisit::walk_impl_item(self, ii);
137     }
138
139     fn visit_variant_data(&mut self, s: &hir::VariantData, _: ast::Name,
140                         _: &'v hir::Generics, item_id: ast::NodeId, _: Span) {
141         // Struct constructors are parented to their struct definitions because
142         // they essentially are the struct definitions.
143         if !s.is_struct() {
144             self.parents.insert(s.id(), item_id);
145         }
146
147         // While we have the id of the struct definition, go ahead and parent
148         // all the fields.
149         for field in s.fields() {
150             self.parents.insert(field.node.id, self.curparent);
151         }
152         intravisit::walk_struct_def(self, s)
153     }
154 }
155
156 ////////////////////////////////////////////////////////////////////////////////
157 /// The embargo visitor, used to determine the exports of the ast
158 ////////////////////////////////////////////////////////////////////////////////
159
160 struct EmbargoVisitor<'a, 'tcx: 'a> {
161     tcx: &'a ty::ctxt<'tcx>,
162     export_map: &'a def::ExportMap,
163
164     // Accessibility levels for reachable nodes
165     access_levels: AccessLevels,
166     // Previous accessibility level, None means unreachable
167     prev_level: Option<AccessLevel>,
168     // Have something changed in the level map?
169     changed: bool,
170 }
171
172 struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
173     ev: &'b mut EmbargoVisitor<'a, 'tcx>,
174 }
175
176 impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
177     fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
178         if let hir::TyPath(..) = ty.node {
179             match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
180                 Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
181                     Some(AccessLevel::Public)
182                 }
183                 def => {
184                     if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
185                         self.get(node_id)
186                     } else {
187                         Some(AccessLevel::Public)
188                     }
189                 }
190             }
191         } else {
192             Some(AccessLevel::Public)
193         }
194     }
195
196     fn trait_level(&self, trait_ref: &hir::TraitRef) -> Option<AccessLevel> {
197         let did = self.tcx.trait_ref_to_def_id(trait_ref);
198         if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
199             self.get(node_id)
200         } else {
201             Some(AccessLevel::Public)
202         }
203     }
204
205     fn get(&self, id: ast::NodeId) -> Option<AccessLevel> {
206         self.access_levels.map.get(&id).cloned()
207     }
208
209     // Updates node level and returns the updated level
210     fn update(&mut self, id: ast::NodeId, level: Option<AccessLevel>) -> Option<AccessLevel> {
211         let old_level = self.get(id);
212         // Accessibility levels can only grow
213         if level > old_level {
214             self.access_levels.map.insert(id, level.unwrap());
215             self.changed = true;
216             level
217         } else {
218             old_level
219         }
220     }
221
222     fn reach<'b>(&'b mut self) -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
223         ReachEverythingInTheInterfaceVisitor { ev: self }
224     }
225 }
226
227 impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
228     /// We want to visit items in the context of their containing
229     /// module and so forth, so supply a crate for doing a deep walk.
230     fn visit_nested_item(&mut self, item: hir::ItemId) {
231         self.visit_item(self.tcx.map.expect_item(item.id))
232     }
233
234     fn visit_item(&mut self, item: &hir::Item) {
235         let inherited_item_level = match item.node {
236             // Impls inherit level from their types and traits
237             hir::ItemImpl(_, _, _, None, ref ty, _) => {
238                 self.ty_level(&ty)
239             }
240             hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, _) => {
241                 cmp::min(self.ty_level(&ty), self.trait_level(trait_ref))
242             }
243             hir::ItemDefaultImpl(_, ref trait_ref) => {
244                 self.trait_level(trait_ref)
245             }
246             // Foreign mods inherit level from parents
247             hir::ItemForeignMod(..) => {
248                 self.prev_level
249             }
250             // Other `pub` items inherit levels from parents
251             _ => {
252                 if item.vis == hir::Public { self.prev_level } else { None }
253             }
254         };
255
256         // Update level of the item itself
257         let item_level = self.update(item.id, inherited_item_level);
258
259         // Update levels of nested things
260         match item.node {
261             hir::ItemEnum(ref def, _) => {
262                 for variant in &def.variants {
263                     let variant_level = self.update(variant.node.data.id(), item_level);
264                     for field in variant.node.data.fields() {
265                         self.update(field.node.id, variant_level);
266                     }
267                 }
268             }
269             hir::ItemImpl(_, _, _, None, _, ref impl_items) => {
270                 for impl_item in impl_items {
271                     if impl_item.vis == hir::Public {
272                         self.update(impl_item.id, item_level);
273                     }
274                 }
275             }
276             hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) => {
277                 for impl_item in impl_items {
278                     self.update(impl_item.id, item_level);
279                 }
280             }
281             hir::ItemTrait(_, _, _, ref trait_items) => {
282                 for trait_item in trait_items {
283                     self.update(trait_item.id, item_level);
284                 }
285             }
286             hir::ItemStruct(ref def, _) => {
287                 if !def.is_struct() {
288                     self.update(def.id(), item_level);
289                 }
290                 for field in def.fields() {
291                     if field.node.kind.visibility() == hir::Public {
292                         self.update(field.node.id, item_level);
293                     }
294                 }
295             }
296             hir::ItemForeignMod(ref foreign_mod) => {
297                 for foreign_item in &foreign_mod.items {
298                     if foreign_item.vis == hir::Public {
299                         self.update(foreign_item.id, item_level);
300                     }
301                 }
302             }
303             _ => {}
304         }
305
306         // Mark all items in interfaces of reachable items as reachable
307         match item.node {
308             // The interface is empty
309             hir::ItemExternCrate(..) => {}
310             // All nested items are checked by visit_item
311             hir::ItemMod(..) => {}
312             // Reexports are handled in visit_mod
313             hir::ItemUse(..) => {}
314             // Visit everything
315             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
316             hir::ItemTrait(..) | hir::ItemTy(..) | hir::ItemImpl(_, _, _, Some(..), _, _) => {
317                 if item_level.is_some() {
318                     self.reach().visit_item(item);
319                 }
320             }
321             // Visit everything, but enum variants have their own levels
322             hir::ItemEnum(ref def, ref generics) => {
323                 if item_level.is_some() {
324                     self.reach().visit_generics(generics);
325                 }
326                 for variant in &def.variants {
327                     if self.get(variant.node.data.id()).is_some() {
328                         for field in variant.node.data.fields() {
329                             self.reach().visit_struct_field(field);
330                         }
331                         // Corner case: if the variant is reachable, but its
332                         // enum is not, make the enum reachable as well.
333                         self.update(item.id, Some(AccessLevel::Reachable));
334                     }
335                 }
336             }
337             // Visit everything, but foreign items have their own levels
338             hir::ItemForeignMod(ref foreign_mod) => {
339                 for foreign_item in &foreign_mod.items {
340                     if self.get(foreign_item.id).is_some() {
341                         self.reach().visit_foreign_item(foreign_item);
342                     }
343                 }
344             }
345             // Visit everything except for private fields
346             hir::ItemStruct(ref struct_def, ref generics) => {
347                 if item_level.is_some() {
348                     self.reach().visit_generics(generics);
349                     for field in struct_def.fields() {
350                         if self.get(field.node.id).is_some() {
351                             self.reach().visit_struct_field(field);
352                         }
353                     }
354                 }
355             }
356             // The interface is empty
357             hir::ItemDefaultImpl(..) => {}
358             // Visit everything except for private impl items
359             hir::ItemImpl(_, _, ref generics, None, _, ref impl_items) => {
360                 if item_level.is_some() {
361                     self.reach().visit_generics(generics);
362                     for impl_item in impl_items {
363                         if self.get(impl_item.id).is_some() {
364                             self.reach().visit_impl_item(impl_item);
365                         }
366                     }
367                 }
368             }
369         }
370
371         let orig_level = self.prev_level;
372         self.prev_level = item_level;
373
374         intravisit::walk_item(self, item);
375
376         self.prev_level = orig_level;
377     }
378
379     fn visit_block(&mut self, b: &'v hir::Block) {
380         let orig_level = replace(&mut self.prev_level, None);
381
382         // Blocks can have public items, for example impls, but they always
383         // start as completely private regardless of publicity of a function,
384         // constant, type, field, etc. in which this block resides
385         intravisit::walk_block(self, b);
386
387         self.prev_level = orig_level;
388     }
389
390     fn visit_mod(&mut self, m: &hir::Mod, _sp: Span, id: ast::NodeId) {
391         // This code is here instead of in visit_item so that the
392         // crate module gets processed as well.
393         if self.prev_level.is_some() {
394             if let Some(exports) = self.export_map.get(&id) {
395                 for export in exports {
396                     if let Some(node_id) = self.tcx.map.as_local_node_id(export.def_id) {
397                         self.update(node_id, Some(AccessLevel::Exported));
398                     }
399                 }
400             }
401         }
402
403         intravisit::walk_mod(self, m);
404     }
405
406     fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
407         self.update(md.id, Some(AccessLevel::Public));
408     }
409 }
410
411 impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
412     // Make the type hidden under a type alias reachable
413     fn reach_aliased_type(&mut self, item: &hir::Item, path: &hir::Path) {
414         if let hir::ItemTy(ref ty, ref generics) = item.node {
415             // See `fn is_public_type_alias` for details
416             self.visit_ty(ty);
417             let provided_params = path.segments.last().unwrap().parameters.types().len();
418             for ty_param in &generics.ty_params[provided_params..] {
419                 if let Some(ref default_ty) = ty_param.default {
420                     self.visit_ty(default_ty);
421                 }
422             }
423         }
424     }
425 }
426
427 impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
428     fn visit_ty(&mut self, ty: &hir::Ty) {
429         if let hir::TyPath(_, ref path) = ty.node {
430             let def = self.ev.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
431             match def {
432                 Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) |
433                 Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => {
434                     if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) {
435                         let item = self.ev.tcx.map.expect_item(node_id);
436                         if let Def::TyAlias(..) = def {
437                             // Type aliases are substituted. Associated type aliases are not
438                             // substituted yet, but ideally they should be.
439                             if self.ev.get(item.id).is_none() {
440                                 self.reach_aliased_type(item, path);
441                             }
442                         } else {
443                             self.ev.update(item.id, Some(AccessLevel::Reachable));
444                         }
445                     }
446                 }
447
448                 _ => {}
449             }
450         }
451
452         intravisit::walk_ty(self, ty);
453     }
454
455     fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
456         let def_id = self.ev.tcx.trait_ref_to_def_id(trait_ref);
457         if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) {
458             let item = self.ev.tcx.map.expect_item(node_id);
459             self.ev.update(item.id, Some(AccessLevel::Reachable));
460         }
461
462         intravisit::walk_trait_ref(self, trait_ref);
463     }
464
465     // Don't recurse into function bodies
466     fn visit_block(&mut self, _: &hir::Block) {}
467     // Don't recurse into expressions in array sizes or const initializers
468     fn visit_expr(&mut self, _: &hir::Expr) {}
469     // Don't recurse into patterns in function arguments
470     fn visit_pat(&mut self, _: &hir::Pat) {}
471 }
472
473 ////////////////////////////////////////////////////////////////////////////////
474 /// The privacy visitor, where privacy checks take place (violations reported)
475 ////////////////////////////////////////////////////////////////////////////////
476
477 struct PrivacyVisitor<'a, 'tcx: 'a> {
478     tcx: &'a ty::ctxt<'tcx>,
479     curitem: ast::NodeId,
480     in_foreign: bool,
481     parents: NodeMap<ast::NodeId>,
482     external_exports: ExternalExports,
483 }
484
485 #[derive(Debug)]
486 enum PrivacyResult {
487     Allowable,
488     ExternallyDenied,
489     DisallowedBy(ast::NodeId),
490 }
491
492 enum FieldName {
493     UnnamedField(usize), // index
494     NamedField(ast::Name),
495 }
496
497 impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
498     // used when debugging
499     fn nodestr(&self, id: ast::NodeId) -> String {
500         self.tcx.map.node_to_string(id).to_string()
501     }
502
503     // Determines whether the given definition is public from the point of view
504     // of the current item.
505     fn def_privacy(&self, did: DefId) -> PrivacyResult {
506         let node_id = if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
507             node_id
508         } else {
509             if self.external_exports.contains(&did) {
510                 debug!("privacy - {:?} was externally exported", did);
511                 return Allowable;
512             }
513             debug!("privacy - is {:?} a public method", did);
514
515             return match self.tcx.impl_or_trait_items.borrow().get(&did) {
516                 Some(&ty::ConstTraitItem(ref ac)) => {
517                     debug!("privacy - it's a const: {:?}", *ac);
518                     match ac.container {
519                         ty::TraitContainer(id) => {
520                             debug!("privacy - recursing on trait {:?}", id);
521                             self.def_privacy(id)
522                         }
523                         ty::ImplContainer(id) => {
524                             match self.tcx.impl_trait_ref(id) {
525                                 Some(t) => {
526                                     debug!("privacy - impl of trait {:?}", id);
527                                     self.def_privacy(t.def_id)
528                                 }
529                                 None => {
530                                     debug!("privacy - found inherent \
531                                             associated constant {:?}",
532                                             ac.vis);
533                                     if ac.vis == hir::Public {
534                                         Allowable
535                                     } else {
536                                         ExternallyDenied
537                                     }
538                                 }
539                             }
540                         }
541                     }
542                 }
543                 Some(&ty::MethodTraitItem(ref meth)) => {
544                     debug!("privacy - well at least it's a method: {:?}",
545                            *meth);
546                     match meth.container {
547                         ty::TraitContainer(id) => {
548                             debug!("privacy - recursing on trait {:?}", id);
549                             self.def_privacy(id)
550                         }
551                         ty::ImplContainer(id) => {
552                             match self.tcx.impl_trait_ref(id) {
553                                 Some(t) => {
554                                     debug!("privacy - impl of trait {:?}", id);
555                                     self.def_privacy(t.def_id)
556                                 }
557                                 None => {
558                                     debug!("privacy - found a method {:?}",
559                                             meth.vis);
560                                     if meth.vis == hir::Public {
561                                         Allowable
562                                     } else {
563                                         ExternallyDenied
564                                     }
565                                 }
566                             }
567                         }
568                     }
569                 }
570                 Some(&ty::TypeTraitItem(ref typedef)) => {
571                     match typedef.container {
572                         ty::TraitContainer(id) => {
573                             debug!("privacy - recursing on trait {:?}", id);
574                             self.def_privacy(id)
575                         }
576                         ty::ImplContainer(id) => {
577                             match self.tcx.impl_trait_ref(id) {
578                                 Some(t) => {
579                                     debug!("privacy - impl of trait {:?}", id);
580                                     self.def_privacy(t.def_id)
581                                 }
582                                 None => {
583                                     debug!("privacy - found a typedef {:?}",
584                                             typedef.vis);
585                                     if typedef.vis == hir::Public {
586                                         Allowable
587                                     } else {
588                                         ExternallyDenied
589                                     }
590                                 }
591                             }
592                         }
593                     }
594                 }
595                 None => {
596                     debug!("privacy - nope, not even a method");
597                     ExternallyDenied
598                 }
599             };
600         };
601
602         debug!("privacy - local {} not public all the way down",
603                self.tcx.map.node_to_string(node_id));
604         // return quickly for things in the same module
605         if self.parents.get(&node_id) == self.parents.get(&self.curitem) {
606             debug!("privacy - same parent, we're done here");
607             return Allowable;
608         }
609
610         // We now know that there is at least one private member between the
611         // destination and the root.
612         let mut closest_private_id = node_id;
613         loop {
614             debug!("privacy - examining {}", self.nodestr(closest_private_id));
615             let vis = match self.tcx.map.find(closest_private_id) {
616                 // If this item is a method, then we know for sure that it's an
617                 // actual method and not a static method. The reason for this is
618                 // that these cases are only hit in the ExprMethodCall
619                 // expression, and ExprCall will have its path checked later
620                 // (the path of the trait/impl) if it's a static method.
621                 //
622                 // With this information, then we can completely ignore all
623                 // trait methods. The privacy violation would be if the trait
624                 // couldn't get imported, not if the method couldn't be used
625                 // (all trait methods are public).
626                 //
627                 // However, if this is an impl method, then we dictate this
628                 // decision solely based on the privacy of the method
629                 // invocation.
630                 // FIXME(#10573) is this the right behavior? Why not consider
631                 //               where the method was defined?
632                 Some(ast_map::NodeImplItem(ii)) => {
633                     match ii.node {
634                         hir::ImplItemKind::Const(..) |
635                         hir::ImplItemKind::Method(..) => {
636                             let imp = self.tcx.map
637                                           .get_parent_did(closest_private_id);
638                             match self.tcx.impl_trait_ref(imp) {
639                                 Some(..) => return Allowable,
640                                 _ if ii.vis == hir::Public => {
641                                     return Allowable
642                                 }
643                                 _ => ii.vis
644                             }
645                         }
646                         hir::ImplItemKind::Type(_) => return Allowable,
647                     }
648                 }
649                 Some(ast_map::NodeTraitItem(_)) => {
650                     return Allowable;
651                 }
652
653                 // This is not a method call, extract the visibility as one
654                 // would normally look at it
655                 Some(ast_map::NodeItem(it)) => it.vis,
656                 Some(ast_map::NodeForeignItem(_)) => {
657                     self.tcx.map.get_foreign_vis(closest_private_id)
658                 }
659                 Some(ast_map::NodeVariant(..)) => {
660                     hir::Public // need to move up a level (to the enum)
661                 }
662                 _ => hir::Public,
663             };
664             if vis != hir::Public { break }
665             // if we've reached the root, then everything was allowable and this
666             // access is public.
667             if closest_private_id == ast::CRATE_NODE_ID { return Allowable }
668             closest_private_id = *self.parents.get(&closest_private_id).unwrap();
669
670             // If we reached the top, then we were public all the way down and
671             // we can allow this access.
672             if closest_private_id == ast::DUMMY_NODE_ID { return Allowable }
673         }
674         debug!("privacy - closest priv {}", self.nodestr(closest_private_id));
675         if self.private_accessible(closest_private_id) {
676             Allowable
677         } else {
678             DisallowedBy(closest_private_id)
679         }
680     }
681
682     /// True if `id` is both local and private-accessible
683     fn local_private_accessible(&self, did: DefId) -> bool {
684         if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
685             self.private_accessible(node_id)
686         } else {
687             false
688         }
689     }
690
691     /// For a local private node in the AST, this function will determine
692     /// whether the node is accessible by the current module that iteration is
693     /// inside.
694     fn private_accessible(&self, id: ast::NodeId) -> bool {
695         let parent = *self.parents.get(&id).unwrap();
696         debug!("privacy - accessible parent {}", self.nodestr(parent));
697
698         // After finding `did`'s closest private member, we roll ourselves back
699         // to see if this private member's parent is anywhere in our ancestry.
700         // By the privacy rules, we can access all of our ancestor's private
701         // members, so that's why we test the parent, and not the did itself.
702         let mut cur = self.curitem;
703         loop {
704             debug!("privacy - questioning {}, {}", self.nodestr(cur), cur);
705             match cur {
706                 // If the relevant parent is in our history, then we're allowed
707                 // to look inside any of our ancestor's immediate private items,
708                 // so this access is valid.
709                 x if x == parent => return true,
710
711                 // If we've reached the root, then we couldn't access this item
712                 // in the first place
713                 ast::DUMMY_NODE_ID => return false,
714
715                 // Keep going up
716                 _ => {}
717             }
718
719             cur = *self.parents.get(&cur).unwrap();
720         }
721     }
722
723     fn report_error(&self, result: CheckResult) -> bool {
724         match result {
725             None => true,
726             Some((span, msg, note)) => {
727                 let mut err = self.tcx.sess.struct_span_err(span, &msg[..]);
728                 if let Some((span, msg)) = note {
729                     err.span_note(span, &msg[..]);
730                 }
731                 err.emit();
732                 false
733             },
734         }
735     }
736
737     /// Guarantee that a particular definition is public. Returns a CheckResult
738     /// which contains any errors found. These can be reported using `report_error`.
739     /// If the result is `None`, no errors were found.
740     fn ensure_public(&self,
741                      span: Span,
742                      to_check: DefId,
743                      source_did: Option<DefId>,
744                      msg: &str)
745                      -> CheckResult {
746         debug!("ensure_public(span={:?}, to_check={:?}, source_did={:?}, msg={:?})",
747                span, to_check, source_did, msg);
748         let def_privacy = self.def_privacy(to_check);
749         debug!("ensure_public: def_privacy={:?}", def_privacy);
750         let id = match def_privacy {
751             ExternallyDenied => {
752                 return Some((span, format!("{} is private", msg), None))
753             }
754             Allowable => return None,
755             DisallowedBy(id) => id,
756         };
757
758         // If we're disallowed by a particular id, then we attempt to
759         // give a nice error message to say why it was disallowed. It
760         // was either because the item itself is private or because
761         // its parent is private and its parent isn't in our
762         // ancestry. (Both the item being checked and its parent must
763         // be local.)
764         let def_id = source_did.unwrap_or(to_check);
765         let node_id = self.tcx.map.as_local_node_id(def_id);
766         let (err_span, err_msg) = if Some(id) == node_id {
767             return Some((span, format!("{} is private", msg), None));
768         } else {
769             (span, format!("{} is inaccessible", msg))
770         };
771         let item = match self.tcx.map.find(id) {
772             Some(ast_map::NodeItem(item)) => {
773                 match item.node {
774                     // If an impl disallowed this item, then this is resolve's
775                     // way of saying that a struct/enum's static method was
776                     // invoked, and the struct/enum itself is private. Crawl
777                     // back up the chains to find the relevant struct/enum that
778                     // was private.
779                     hir::ItemImpl(_, _, _, _, ref ty, _) => {
780                         match ty.node {
781                             hir::TyPath(..) => {}
782                             _ => return Some((err_span, err_msg, None)),
783                         };
784                         let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
785                         let did = def.def_id();
786                         let node_id = self.tcx.map.as_local_node_id(did).unwrap();
787                         match self.tcx.map.get(node_id) {
788                             ast_map::NodeItem(item) => item,
789                             _ => self.tcx.sess.span_bug(item.span,
790                                                         "path is not an item")
791                         }
792                     }
793                     _ => item
794                 }
795             }
796             Some(..) | None => return Some((err_span, err_msg, None)),
797         };
798         let desc = match item.node {
799             hir::ItemMod(..) => "module",
800             hir::ItemTrait(..) => "trait",
801             hir::ItemStruct(..) => "struct",
802             hir::ItemEnum(..) => "enum",
803             _ => return Some((err_span, err_msg, None))
804         };
805         let msg = format!("{} `{}` is private", desc, item.name);
806         Some((err_span, err_msg, Some((span, msg))))
807     }
808
809     // Checks that a field is in scope.
810     fn check_field(&mut self,
811                    span: Span,
812                    def: ty::AdtDef<'tcx>,
813                    v: ty::VariantDef<'tcx>,
814                    name: FieldName) {
815         let field = match name {
816             NamedField(f_name) => {
817                 debug!("privacy - check named field {} in struct {:?}", f_name, def);
818                 v.field_named(f_name)
819             }
820             UnnamedField(idx) => &v.fields[idx]
821         };
822         if field.vis == hir::Public || self.local_private_accessible(field.did) {
823             return;
824         }
825
826         let struct_desc = match def.adt_kind() {
827             ty::AdtKind::Struct =>
828                 format!("struct `{}`", self.tcx.item_path_str(def.did)),
829             // struct variant fields have inherited visibility
830             ty::AdtKind::Enum => return
831         };
832         let msg = match name {
833             NamedField(name) => format!("field `{}` of {} is private",
834                                         name, struct_desc),
835             UnnamedField(idx) => format!("field #{} of {} is private",
836                                          idx, struct_desc),
837         };
838         span_err!(self.tcx.sess, span, E0451,
839                   "{}", &msg[..]);
840     }
841
842     // Given the ID of a method, checks to ensure it's in scope.
843     fn check_static_method(&mut self,
844                            span: Span,
845                            method_id: DefId,
846                            name: ast::Name) {
847         self.report_error(self.ensure_public(span,
848                                              method_id,
849                                              None,
850                                              &format!("method `{}`",
851                                                      name)));
852     }
853
854     // Checks that a path is in scope.
855     fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Name) {
856         debug!("privacy - path {}", self.nodestr(path_id));
857         let path_res = *self.tcx.def_map.borrow().get(&path_id).unwrap();
858         let ck = |tyname: &str| {
859             let ck_public = |def: DefId| {
860                 debug!("privacy - ck_public {:?}", def);
861                 let origdid = path_res.def_id();
862                 self.ensure_public(span,
863                                    def,
864                                    Some(origdid),
865                                    &format!("{} `{}`", tyname, last))
866             };
867
868             match path_res.last_private {
869                 LastMod(AllPublic) => {},
870                 LastMod(DependsOn(def)) => {
871                     self.report_error(ck_public(def));
872                 },
873                 LastImport { value_priv,
874                              value_used: check_value,
875                              type_priv,
876                              type_used: check_type } => {
877                     // This dance with found_error is because we don't want to
878                     // report a privacy error twice for the same directive.
879                     let found_error = match (type_priv, check_type) {
880                         (Some(DependsOn(def)), Used) => {
881                             !self.report_error(ck_public(def))
882                         },
883                         _ => false,
884                     };
885                     if !found_error {
886                         match (value_priv, check_value) {
887                             (Some(DependsOn(def)), Used) => {
888                                 self.report_error(ck_public(def));
889                             },
890                             _ => {},
891                         }
892                     }
893                     // If an import is not used in either namespace, we still
894                     // want to check that it could be legal. Therefore we check
895                     // in both namespaces and only report an error if both would
896                     // be illegal. We only report one error, even if it is
897                     // illegal to import from both namespaces.
898                     match (value_priv, check_value, type_priv, check_type) {
899                         (Some(p), Unused, None, _) |
900                         (None, _, Some(p), Unused) => {
901                             let p = match p {
902                                 AllPublic => None,
903                                 DependsOn(def) => ck_public(def),
904                             };
905                             if p.is_some() {
906                                 self.report_error(p);
907                             }
908                         },
909                         (Some(v), Unused, Some(t), Unused) => {
910                             let v = match v {
911                                 AllPublic => None,
912                                 DependsOn(def) => ck_public(def),
913                             };
914                             let t = match t {
915                                 AllPublic => None,
916                                 DependsOn(def) => ck_public(def),
917                             };
918                             if let (Some(_), Some(t)) = (v, t) {
919                                 self.report_error(Some(t));
920                             }
921                         },
922                         _ => {},
923                     }
924                 },
925             }
926         };
927         // FIXME(#12334) Imports can refer to definitions in both the type and
928         // value namespaces. The privacy information is aware of this, but the
929         // def map is not. Therefore the names we work out below will not always
930         // be accurate and we can get slightly wonky error messages (but type
931         // checking is always correct).
932         match path_res.full_def() {
933             Def::Fn(..) => ck("function"),
934             Def::Static(..) => ck("static"),
935             Def::Const(..) => ck("const"),
936             Def::AssociatedConst(..) => ck("associated const"),
937             Def::Variant(..) => ck("variant"),
938             Def::TyAlias(..) => ck("type"),
939             Def::Enum(..) => ck("enum"),
940             Def::Trait(..) => ck("trait"),
941             Def::Struct(..) => ck("struct"),
942             Def::Method(..) => ck("method"),
943             Def::Mod(..) => ck("module"),
944             _ => {}
945         }
946     }
947
948     // Checks that a method is in scope.
949     fn check_method(&mut self, span: Span, method_def_id: DefId,
950                     name: ast::Name) {
951         match self.tcx.impl_or_trait_item(method_def_id).container() {
952             ty::ImplContainer(_) => {
953                 self.check_static_method(span, method_def_id, name)
954             }
955             // Trait methods are always all public. The only controlling factor
956             // is whether the trait itself is accessible or not.
957             ty::TraitContainer(trait_def_id) => {
958                 self.report_error(self.ensure_public(span, trait_def_id,
959                                                      None, "source trait"));
960             }
961         }
962     }
963 }
964
965 impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
966     /// We want to visit items in the context of their containing
967     /// module and so forth, so supply a crate for doing a deep walk.
968     fn visit_nested_item(&mut self, item: hir::ItemId) {
969         self.visit_item(self.tcx.map.expect_item(item.id))
970     }
971
972     fn visit_item(&mut self, item: &hir::Item) {
973         let orig_curitem = replace(&mut self.curitem, item.id);
974         intravisit::walk_item(self, item);
975         self.curitem = orig_curitem;
976     }
977
978     fn visit_expr(&mut self, expr: &hir::Expr) {
979         match expr.node {
980             hir::ExprField(ref base, name) => {
981                 if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&base).sty {
982                     self.check_field(expr.span,
983                                      def,
984                                      def.struct_variant(),
985                                      NamedField(name.node));
986                 }
987             }
988             hir::ExprTupField(ref base, idx) => {
989                 if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&base).sty {
990                     self.check_field(expr.span,
991                                      def,
992                                      def.struct_variant(),
993                                      UnnamedField(idx.node));
994                 }
995             }
996             hir::ExprMethodCall(name, _, _) => {
997                 let method_call = ty::MethodCall::expr(expr.id);
998                 let method = self.tcx.tables.borrow().method_map[&method_call];
999                 debug!("(privacy checking) checking impl method");
1000                 self.check_method(expr.span, method.def_id, name.node);
1001             }
1002             hir::ExprStruct(..) => {
1003                 let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
1004                 let variant = adt.variant_of_def(self.tcx.resolve_expr(expr));
1005                 // RFC 736: ensure all unmentioned fields are visible.
1006                 // Rather than computing the set of unmentioned fields
1007                 // (i.e. `all_fields - fields`), just check them all.
1008                 for field in &variant.fields {
1009                     self.check_field(expr.span, adt, variant, NamedField(field.name));
1010                 }
1011             }
1012             hir::ExprPath(..) => {
1013
1014                 if let Def::Struct(..) = self.tcx.resolve_expr(expr) {
1015                     let expr_ty = self.tcx.expr_ty(expr);
1016                     let def = match expr_ty.sty {
1017                         ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
1018                             output: ty::FnConverging(ty), ..
1019                         }), ..}) => ty,
1020                         _ => expr_ty
1021                     }.ty_adt_def().unwrap();
1022                     let any_priv = def.struct_variant().fields.iter().any(|f| {
1023                         f.vis != hir::Public && !self.local_private_accessible(f.did)
1024                     });
1025                     if any_priv {
1026                         span_err!(self.tcx.sess, expr.span, E0450,
1027                                   "cannot invoke tuple struct constructor with private \
1028                                    fields");
1029                     }
1030                 }
1031             }
1032             _ => {}
1033         }
1034
1035         intravisit::walk_expr(self, expr);
1036     }
1037
1038     fn visit_pat(&mut self, pattern: &hir::Pat) {
1039         // Foreign functions do not have their patterns mapped in the def_map,
1040         // and there's nothing really relevant there anyway, so don't bother
1041         // checking privacy. If you can name the type then you can pass it to an
1042         // external C function anyway.
1043         if self.in_foreign { return }
1044
1045         match pattern.node {
1046             PatKind::Struct(_, ref fields, _) => {
1047                 let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap();
1048                 let def = self.tcx.def_map.borrow().get(&pattern.id).unwrap().full_def();
1049                 let variant = adt.variant_of_def(def);
1050                 for field in fields {
1051                     self.check_field(pattern.span, adt, variant,
1052                                      NamedField(field.node.name));
1053                 }
1054             }
1055
1056             // Patterns which bind no fields are allowable (the path is check
1057             // elsewhere).
1058             PatKind::TupleStruct(_, Some(ref fields)) => {
1059                 match self.tcx.pat_ty(pattern).sty {
1060                     ty::TyStruct(def, _) => {
1061                         for (i, field) in fields.iter().enumerate() {
1062                             if let PatKind::Wild = field.node {
1063                                 continue
1064                             }
1065                             self.check_field(field.span,
1066                                              def,
1067                                              def.struct_variant(),
1068                                              UnnamedField(i));
1069                         }
1070                     }
1071                     ty::TyEnum(..) => {
1072                         // enum fields have no privacy at this time
1073                     }
1074                     _ => {}
1075                 }
1076
1077             }
1078             _ => {}
1079         }
1080
1081         intravisit::walk_pat(self, pattern);
1082     }
1083
1084     fn visit_foreign_item(&mut self, fi: &hir::ForeignItem) {
1085         self.in_foreign = true;
1086         intravisit::walk_foreign_item(self, fi);
1087         self.in_foreign = false;
1088     }
1089
1090     fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
1091         if !path.segments.is_empty() {
1092             self.check_path(path.span, id, path.segments.last().unwrap().identifier.name);
1093             intravisit::walk_path(self, path);
1094         }
1095     }
1096
1097     fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
1098         let name = if let hir::PathListIdent { name, .. } = item.node {
1099             name
1100         } else if !prefix.segments.is_empty() {
1101             prefix.segments.last().unwrap().identifier.name
1102         } else {
1103             self.tcx.sess.bug("`self` import in an import list with empty prefix");
1104         };
1105         self.check_path(item.span, item.node.id(), name);
1106         intravisit::walk_path_list_item(self, prefix, item);
1107     }
1108 }
1109
1110 ////////////////////////////////////////////////////////////////////////////////
1111 /// The privacy sanity check visitor, ensures unnecessary visibility isn't here
1112 ////////////////////////////////////////////////////////////////////////////////
1113
1114 struct SanePrivacyVisitor<'a, 'tcx: 'a> {
1115     tcx: &'a ty::ctxt<'tcx>,
1116     in_block: bool,
1117 }
1118
1119 impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
1120     /// We want to visit items in the context of their containing
1121     /// module and so forth, so supply a crate for doing a deep walk.
1122     fn visit_nested_item(&mut self, item: hir::ItemId) {
1123         self.visit_item(self.tcx.map.expect_item(item.id))
1124     }
1125
1126     fn visit_item(&mut self, item: &hir::Item) {
1127         self.check_sane_privacy(item);
1128         if self.in_block {
1129             self.check_all_inherited(item);
1130         }
1131
1132         let orig_in_block = self.in_block;
1133
1134         // Modules turn privacy back on, otherwise we inherit
1135         self.in_block = if let hir::ItemMod(..) = item.node { false } else { orig_in_block };
1136
1137         intravisit::walk_item(self, item);
1138         self.in_block = orig_in_block;
1139     }
1140
1141     fn visit_block(&mut self, b: &'v hir::Block) {
1142         let orig_in_block = replace(&mut self.in_block, true);
1143         intravisit::walk_block(self, b);
1144         self.in_block = orig_in_block;
1145     }
1146 }
1147
1148 impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
1149     /// Validates all of the visibility qualifiers placed on the item given. This
1150     /// ensures that there are no extraneous qualifiers that don't actually do
1151     /// anything. In theory these qualifiers wouldn't parse, but that may happen
1152     /// later on down the road...
1153     fn check_sane_privacy(&self, item: &hir::Item) {
1154         let check_inherited = |sp, vis, note: &str| {
1155             if vis != hir::Inherited {
1156                 let mut err = struct_span_err!(self.tcx.sess, sp, E0449,
1157                                                "unnecessary visibility qualifier");
1158                 if !note.is_empty() {
1159                     err.span_note(sp, note);
1160                 }
1161                 err.emit();
1162             }
1163         };
1164
1165         match item.node {
1166             // implementations of traits don't need visibility qualifiers because
1167             // that's controlled by having the trait in scope.
1168             hir::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
1169                 check_inherited(item.span, item.vis,
1170                                 "visibility qualifiers have no effect on trait impls");
1171                 for impl_item in impl_items {
1172                     check_inherited(impl_item.span, impl_item.vis, "");
1173                 }
1174             }
1175             hir::ItemImpl(_, _, _, None, _, _) => {
1176                 check_inherited(item.span, item.vis,
1177                                 "place qualifiers on individual methods instead");
1178             }
1179             hir::ItemDefaultImpl(..) => {
1180                 check_inherited(item.span, item.vis,
1181                                 "visibility qualifiers have no effect on trait impls");
1182             }
1183             hir::ItemForeignMod(..) => {
1184                 check_inherited(item.span, item.vis,
1185                                 "place qualifiers on individual functions instead");
1186             }
1187             hir::ItemStruct(..) | hir::ItemEnum(..) | hir::ItemTrait(..) |
1188             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
1189             hir::ItemMod(..) | hir::ItemExternCrate(..) |
1190             hir::ItemUse(..) | hir::ItemTy(..) => {}
1191         }
1192     }
1193
1194     /// When inside of something like a function or a method, visibility has no
1195     /// control over anything so this forbids any mention of any visibility
1196     fn check_all_inherited(&self, item: &hir::Item) {
1197         let check_inherited = |sp, vis| {
1198             if vis != hir::Inherited {
1199                 span_err!(self.tcx.sess, sp, E0447,
1200                           "visibility has no effect inside functions or block expressions");
1201             }
1202         };
1203
1204         check_inherited(item.span, item.vis);
1205         match item.node {
1206             hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
1207                 for impl_item in impl_items {
1208                     check_inherited(impl_item.span, impl_item.vis);
1209                 }
1210             }
1211             hir::ItemForeignMod(ref fm) => {
1212                 for fi in &fm.items {
1213                     check_inherited(fi.span, fi.vis);
1214                 }
1215             }
1216             hir::ItemStruct(ref vdata, _) => {
1217                 for f in vdata.fields() {
1218                     check_inherited(f.span, f.node.kind.visibility());
1219                 }
1220             }
1221             hir::ItemDefaultImpl(..) | hir::ItemEnum(..) | hir::ItemTrait(..) |
1222             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
1223             hir::ItemMod(..) | hir::ItemExternCrate(..) |
1224             hir::ItemUse(..) | hir::ItemTy(..) => {}
1225         }
1226     }
1227 }
1228
1229 ///////////////////////////////////////////////////////////////////////////////
1230 /// Obsolete visitors for checking for private items in public interfaces.
1231 /// These visitors are supposed to be kept in frozen state and produce an
1232 /// "old error node set". For backward compatibility the new visitor reports
1233 /// warnings instead of hard errors when the erroneous node is not in this old set.
1234 ///////////////////////////////////////////////////////////////////////////////
1235
1236 struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
1237     tcx: &'a ty::ctxt<'tcx>,
1238     access_levels: &'a AccessLevels,
1239     in_variant: bool,
1240     // set of errors produced by this obsolete visitor
1241     old_error_set: NodeSet,
1242 }
1243
1244 struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
1245     inner: &'a ObsoleteVisiblePrivateTypesVisitor<'b, 'tcx>,
1246     /// whether the type refers to private types.
1247     contains_private: bool,
1248     /// whether we've recurred at all (i.e. if we're pointing at the
1249     /// first type on which visit_ty was called).
1250     at_outer_type: bool,
1251     // whether that first type is a public path.
1252     outer_type_is_public_path: bool,
1253 }
1254
1255 impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1256     fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
1257         let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
1258             // `int` etc. (None doesn't seem to occur.)
1259             None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => return false,
1260             Some(def) => def.def_id(),
1261         };
1262
1263         // A path can only be private if:
1264         // it's in this crate...
1265         if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
1266             // .. and it corresponds to a private type in the AST (this returns
1267             // None for type parameters)
1268             match self.tcx.map.find(node_id) {
1269                 Some(ast_map::NodeItem(ref item)) => item.vis != hir::Public,
1270                 Some(_) | None => false,
1271             }
1272         } else {
1273             return false
1274         }
1275     }
1276
1277     fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
1278         // FIXME: this would preferably be using `exported_items`, but all
1279         // traits are exported currently (see `EmbargoVisitor.exported_trait`)
1280         self.access_levels.is_public(trait_id)
1281     }
1282
1283     fn check_ty_param_bound(&mut self,
1284                             ty_param_bound: &hir::TyParamBound) {
1285         if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
1286             if self.path_is_private_type(trait_ref.trait_ref.ref_id) {
1287                 self.old_error_set.insert(trait_ref.trait_ref.ref_id);
1288             }
1289         }
1290     }
1291
1292     fn item_is_public(&self, id: &ast::NodeId, vis: hir::Visibility) -> bool {
1293         self.access_levels.is_reachable(*id) || vis == hir::Public
1294     }
1295 }
1296
1297 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
1298     fn visit_ty(&mut self, ty: &hir::Ty) {
1299         if let hir::TyPath(..) = ty.node {
1300             if self.inner.path_is_private_type(ty.id) {
1301                 self.contains_private = true;
1302                 // found what we're looking for so let's stop
1303                 // working.
1304                 return
1305             } else if self.at_outer_type {
1306                 self.outer_type_is_public_path = true;
1307             }
1308         }
1309         self.at_outer_type = false;
1310         intravisit::walk_ty(self, ty)
1311     }
1312
1313     // don't want to recurse into [, .. expr]
1314     fn visit_expr(&mut self, _: &hir::Expr) {}
1315 }
1316
1317 impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1318     /// We want to visit items in the context of their containing
1319     /// module and so forth, so supply a crate for doing a deep walk.
1320     fn visit_nested_item(&mut self, item: hir::ItemId) {
1321         self.visit_item(self.tcx.map.expect_item(item.id))
1322     }
1323
1324     fn visit_item(&mut self, item: &hir::Item) {
1325         match item.node {
1326             // contents of a private mod can be reexported, so we need
1327             // to check internals.
1328             hir::ItemMod(_) => {}
1329
1330             // An `extern {}` doesn't introduce a new privacy
1331             // namespace (the contents have their own privacies).
1332             hir::ItemForeignMod(_) => {}
1333
1334             hir::ItemTrait(_, _, ref bounds, _) => {
1335                 if !self.trait_is_public(item.id) {
1336                     return
1337                 }
1338
1339                 for bound in bounds.iter() {
1340                     self.check_ty_param_bound(bound)
1341                 }
1342             }
1343
1344             // impls need some special handling to try to offer useful
1345             // error messages without (too many) false positives
1346             // (i.e. we could just return here to not check them at
1347             // all, or some worse estimation of whether an impl is
1348             // publicly visible).
1349             hir::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
1350                 // `impl [... for] Private` is never visible.
1351                 let self_contains_private;
1352                 // impl [... for] Public<...>, but not `impl [... for]
1353                 // Vec<Public>` or `(Public,)` etc.
1354                 let self_is_public_path;
1355
1356                 // check the properties of the Self type:
1357                 {
1358                     let mut visitor = ObsoleteCheckTypeForPrivatenessVisitor {
1359                         inner: self,
1360                         contains_private: false,
1361                         at_outer_type: true,
1362                         outer_type_is_public_path: false,
1363                     };
1364                     visitor.visit_ty(&self_);
1365                     self_contains_private = visitor.contains_private;
1366                     self_is_public_path = visitor.outer_type_is_public_path;
1367                 }
1368
1369                 // miscellaneous info about the impl
1370
1371                 // `true` iff this is `impl Private for ...`.
1372                 let not_private_trait =
1373                     trait_ref.as_ref().map_or(true, // no trait counts as public trait
1374                                               |tr| {
1375                         let did = self.tcx.trait_ref_to_def_id(tr);
1376
1377                         if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
1378                             self.trait_is_public(node_id)
1379                         } else {
1380                             true // external traits must be public
1381                         }
1382                     });
1383
1384                 // `true` iff this is a trait impl or at least one method is public.
1385                 //
1386                 // `impl Public { $( fn ...() {} )* }` is not visible.
1387                 //
1388                 // This is required over just using the methods' privacy
1389                 // directly because we might have `impl<T: Foo<Private>> ...`,
1390                 // and we shouldn't warn about the generics if all the methods
1391                 // are private (because `T` won't be visible externally).
1392                 let trait_or_some_public_method =
1393                     trait_ref.is_some() ||
1394                     impl_items.iter()
1395                               .any(|impl_item| {
1396                                   match impl_item.node {
1397                                       hir::ImplItemKind::Const(..) |
1398                                       hir::ImplItemKind::Method(..) => {
1399                                           self.access_levels.is_reachable(impl_item.id)
1400                                       }
1401                                       hir::ImplItemKind::Type(_) => false,
1402                                   }
1403                               });
1404
1405                 if !self_contains_private &&
1406                         not_private_trait &&
1407                         trait_or_some_public_method {
1408
1409                     intravisit::walk_generics(self, g);
1410
1411                     match *trait_ref {
1412                         None => {
1413                             for impl_item in impl_items {
1414                                 // This is where we choose whether to walk down
1415                                 // further into the impl to check its items. We
1416                                 // should only walk into public items so that we
1417                                 // don't erroneously report errors for private
1418                                 // types in private items.
1419                                 match impl_item.node {
1420                                     hir::ImplItemKind::Const(..) |
1421                                     hir::ImplItemKind::Method(..)
1422                                         if self.item_is_public(&impl_item.id, impl_item.vis) =>
1423                                     {
1424                                         intravisit::walk_impl_item(self, impl_item)
1425                                     }
1426                                     hir::ImplItemKind::Type(..) => {
1427                                         intravisit::walk_impl_item(self, impl_item)
1428                                     }
1429                                     _ => {}
1430                                 }
1431                             }
1432                         }
1433                         Some(ref tr) => {
1434                             // Any private types in a trait impl fall into three
1435                             // categories.
1436                             // 1. mentioned in the trait definition
1437                             // 2. mentioned in the type params/generics
1438                             // 3. mentioned in the associated types of the impl
1439                             //
1440                             // Those in 1. can only occur if the trait is in
1441                             // this crate and will've been warned about on the
1442                             // trait definition (there's no need to warn twice
1443                             // so we don't check the methods).
1444                             //
1445                             // Those in 2. are warned via walk_generics and this
1446                             // call here.
1447                             intravisit::walk_path(self, &tr.path);
1448
1449                             // Those in 3. are warned with this call.
1450                             for impl_item in impl_items {
1451                                 if let hir::ImplItemKind::Type(ref ty) = impl_item.node {
1452                                     self.visit_ty(ty);
1453                                 }
1454                             }
1455                         }
1456                     }
1457                 } else if trait_ref.is_none() && self_is_public_path {
1458                     // impl Public<Private> { ... }. Any public static
1459                     // methods will be visible as `Public::foo`.
1460                     let mut found_pub_static = false;
1461                     for impl_item in impl_items {
1462                         match impl_item.node {
1463                             hir::ImplItemKind::Const(..) => {
1464                                 if self.item_is_public(&impl_item.id, impl_item.vis) {
1465                                     found_pub_static = true;
1466                                     intravisit::walk_impl_item(self, impl_item);
1467                                 }
1468                             }
1469                             hir::ImplItemKind::Method(ref sig, _) => {
1470                                 if sig.explicit_self.node == hir::SelfStatic &&
1471                                       self.item_is_public(&impl_item.id, impl_item.vis) {
1472                                     found_pub_static = true;
1473                                     intravisit::walk_impl_item(self, impl_item);
1474                                 }
1475                             }
1476                             _ => {}
1477                         }
1478                     }
1479                     if found_pub_static {
1480                         intravisit::walk_generics(self, g)
1481                     }
1482                 }
1483                 return
1484             }
1485
1486             // `type ... = ...;` can contain private types, because
1487             // we're introducing a new name.
1488             hir::ItemTy(..) => return,
1489
1490             // not at all public, so we don't care
1491             _ if !self.item_is_public(&item.id, item.vis) => {
1492                 return;
1493             }
1494
1495             _ => {}
1496         }
1497
1498         // We've carefully constructed it so that if we're here, then
1499         // any `visit_ty`'s will be called on things that are in
1500         // public signatures, i.e. things that we're interested in for
1501         // this visitor.
1502         debug!("VisiblePrivateTypesVisitor entering item {:?}", item);
1503         intravisit::walk_item(self, item);
1504     }
1505
1506     fn visit_generics(&mut self, generics: &hir::Generics) {
1507         for ty_param in generics.ty_params.iter() {
1508             for bound in ty_param.bounds.iter() {
1509                 self.check_ty_param_bound(bound)
1510             }
1511         }
1512         for predicate in &generics.where_clause.predicates {
1513             match predicate {
1514                 &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
1515                     for bound in bound_pred.bounds.iter() {
1516                         self.check_ty_param_bound(bound)
1517                     }
1518                 }
1519                 &hir::WherePredicate::RegionPredicate(_) => {}
1520                 &hir::WherePredicate::EqPredicate(ref eq_pred) => {
1521                     self.visit_ty(&eq_pred.ty);
1522                 }
1523             }
1524         }
1525     }
1526
1527     fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
1528         if self.access_levels.is_reachable(item.id) {
1529             intravisit::walk_foreign_item(self, item)
1530         }
1531     }
1532
1533     fn visit_ty(&mut self, t: &hir::Ty) {
1534         debug!("VisiblePrivateTypesVisitor checking ty {:?}", t);
1535         if let hir::TyPath(..) = t.node {
1536             if self.path_is_private_type(t.id) {
1537                 self.old_error_set.insert(t.id);
1538             }
1539         }
1540         intravisit::walk_ty(self, t)
1541     }
1542
1543     fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics, item_id: ast::NodeId) {
1544         if self.access_levels.is_reachable(v.node.data.id()) {
1545             self.in_variant = true;
1546             intravisit::walk_variant(self, v, g, item_id);
1547             self.in_variant = false;
1548         }
1549     }
1550
1551     fn visit_struct_field(&mut self, s: &hir::StructField) {
1552         let vis = match s.node.kind {
1553             hir::NamedField(_, vis) | hir::UnnamedField(vis) => vis
1554         };
1555         if vis == hir::Public || self.in_variant {
1556             intravisit::walk_struct_field(self, s);
1557         }
1558     }
1559
1560     // we don't need to introspect into these at all: an
1561     // expression/block context can't possibly contain exported things.
1562     // (Making them no-ops stops us from traversing the whole AST without
1563     // having to be super careful about our `walk_...` calls above.)
1564     // FIXME(#29524): Unfortunately this ^^^ is not true, blocks can contain
1565     // exported items (e.g. impls) and actual code in rustc itself breaks
1566     // if we don't traverse blocks in `EmbargoVisitor`
1567     fn visit_block(&mut self, _: &hir::Block) {}
1568     fn visit_expr(&mut self, _: &hir::Expr) {}
1569 }
1570
1571 ///////////////////////////////////////////////////////////////////////////////
1572 /// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
1573 /// finds any private components in it.
1574 /// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
1575 /// and traits in public interfaces.
1576 ///////////////////////////////////////////////////////////////////////////////
1577
1578 struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
1579     tcx: &'a ty::ctxt<'tcx>,
1580     // Do not report an error when a private type is found
1581     is_quiet: bool,
1582     // Is private component found?
1583     is_public: bool,
1584     old_error_set: &'a NodeSet,
1585 }
1586
1587 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
1588     // Check if the type alias contain private types when substituted
1589     fn is_public_type_alias(&self, item: &hir::Item, path: &hir::Path) -> bool {
1590         // We substitute type aliases only when determining impl publicity
1591         // FIXME: This will probably change and all type aliases will be substituted,
1592         // requires an amendment to RFC 136.
1593         if !self.is_quiet {
1594             return false
1595         }
1596         // Type alias is considered public if the aliased type is
1597         // public, even if the type alias itself is private. So, something
1598         // like `type A = u8; pub fn f() -> A {...}` doesn't cause an error.
1599         if let hir::ItemTy(ref ty, ref generics) = item.node {
1600             let mut check = SearchInterfaceForPrivateItemsVisitor { is_public: true, ..*self };
1601             check.visit_ty(ty);
1602             // If a private type alias with default type parameters is used in public
1603             // interface we must ensure, that the defaults are public if they are actually used.
1604             // ```
1605             // type Alias<T = Private> = T;
1606             // pub fn f() -> Alias {...} // `Private` is implicitly used here, so it must be public
1607             // ```
1608             let provided_params = path.segments.last().unwrap().parameters.types().len();
1609             for ty_param in &generics.ty_params[provided_params..] {
1610                 if let Some(ref default_ty) = ty_param.default {
1611                     check.visit_ty(default_ty);
1612                 }
1613             }
1614             check.is_public
1615         } else {
1616             false
1617         }
1618     }
1619 }
1620
1621 impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
1622     fn visit_ty(&mut self, ty: &hir::Ty) {
1623         if self.is_quiet && !self.is_public {
1624             // We are in quiet mode and a private type is already found, no need to proceed
1625             return
1626         }
1627         if let hir::TyPath(_, ref path) = ty.node {
1628             let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
1629             match def {
1630                 Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
1631                     // Public
1632                 }
1633                 Def::AssociatedTy(..) if self.is_quiet => {
1634                     // Conservatively approximate the whole type alias as public without
1635                     // recursing into its components when determining impl publicity.
1636                     // For example, `impl <Type as Trait>::Alias {...}` may be a public impl
1637                     // even if both `Type` and `Trait` are private.
1638                     // Ideally, associated types should be substituted in the same way as
1639                     // free type aliases, but this isn't done yet.
1640                     return
1641                 }
1642                 Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) |
1643                 Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => {
1644                     // Non-local means public (private items can't leave their crate, modulo bugs)
1645                     if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
1646                         let item = self.tcx.map.expect_item(node_id);
1647                         if item.vis != hir::Public && !self.is_public_type_alias(item, path) {
1648                             if !self.is_quiet {
1649                                 if self.old_error_set.contains(&ty.id) {
1650                                     span_err!(self.tcx.sess, ty.span, E0446,
1651                                               "private type in public interface");
1652                                 } else {
1653                                     self.tcx.sess.add_lint (
1654                                         lint::builtin::PRIVATE_IN_PUBLIC,
1655                                         node_id,
1656                                         ty.span,
1657                                         format!("private type in public interface"),
1658                                     );
1659                                 }
1660                             }
1661                             self.is_public = false;
1662                         }
1663                     }
1664                 }
1665                 _ => {}
1666             }
1667         }
1668
1669         intravisit::walk_ty(self, ty);
1670     }
1671
1672     fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
1673         if self.is_quiet && !self.is_public {
1674             // We are in quiet mode and a private type is already found, no need to proceed
1675             return
1676         }
1677         // Non-local means public (private items can't leave their crate, modulo bugs)
1678         let def_id = self.tcx.trait_ref_to_def_id(trait_ref);
1679         if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
1680             let item = self.tcx.map.expect_item(node_id);
1681             if item.vis != hir::Public {
1682                 if !self.is_quiet {
1683                     if self.old_error_set.contains(&trait_ref.ref_id) {
1684                         span_err!(self.tcx.sess, trait_ref.path.span, E0445,
1685                                   "private trait in public interface");
1686                     } else {
1687                         self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
1688                                                node_id,
1689                                                trait_ref.path.span,
1690                                                "private trait in public interface (error E0445)"
1691                                                     .to_string());
1692                     }
1693                 }
1694                 self.is_public = false;
1695             }
1696         }
1697
1698         intravisit::walk_trait_ref(self, trait_ref);
1699     }
1700
1701     // Don't recurse into function bodies
1702     fn visit_block(&mut self, _: &hir::Block) {}
1703     // Don't recurse into expressions in array sizes or const initializers
1704     fn visit_expr(&mut self, _: &hir::Expr) {}
1705     // Don't recurse into patterns in function arguments
1706     fn visit_pat(&mut self, _: &hir::Pat) {}
1707 }
1708
1709 struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
1710     tcx: &'a ty::ctxt<'tcx>,
1711     old_error_set: &'a NodeSet,
1712 }
1713
1714 impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1715     // A type is considered public if it doesn't contain any private components
1716     fn is_public_ty(&self, ty: &hir::Ty) -> bool {
1717         let mut check = SearchInterfaceForPrivateItemsVisitor {
1718             tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
1719         };
1720         check.visit_ty(ty);
1721         check.is_public
1722     }
1723
1724     // A trait reference is considered public if it doesn't contain any private components
1725     fn is_public_trait_ref(&self, trait_ref: &hir::TraitRef) -> bool {
1726         let mut check = SearchInterfaceForPrivateItemsVisitor {
1727             tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
1728         };
1729         check.visit_trait_ref(trait_ref);
1730         check.is_public
1731     }
1732 }
1733
1734 impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1735     fn visit_item(&mut self, item: &hir::Item) {
1736         let mut check = SearchInterfaceForPrivateItemsVisitor {
1737             tcx: self.tcx, is_quiet: false, is_public: true, old_error_set: self.old_error_set
1738         };
1739         match item.node {
1740             // Crates are always public
1741             hir::ItemExternCrate(..) => {}
1742             // All nested items are checked by visit_item
1743             hir::ItemMod(..) => {}
1744             // Checked in resolve
1745             hir::ItemUse(..) => {}
1746             // Subitems of these items have inherited publicity
1747             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
1748             hir::ItemEnum(..) | hir::ItemTrait(..) | hir::ItemTy(..) => {
1749                 if item.vis == hir::Public {
1750                     check.visit_item(item);
1751                 }
1752             }
1753             // Subitems of foreign modules have their own publicity
1754             hir::ItemForeignMod(ref foreign_mod) => {
1755                 for foreign_item in &foreign_mod.items {
1756                     if foreign_item.vis == hir::Public {
1757                         check.visit_foreign_item(foreign_item);
1758                     }
1759                 }
1760             }
1761             // Subitems of structs have their own publicity
1762             hir::ItemStruct(ref struct_def, ref generics) => {
1763                 if item.vis == hir::Public {
1764                     check.visit_generics(generics);
1765                     for field in struct_def.fields() {
1766                         if field.node.kind.visibility() == hir::Public {
1767                             check.visit_struct_field(field);
1768                         }
1769                     }
1770                 }
1771             }
1772             // The interface is empty
1773             hir::ItemDefaultImpl(..) => {}
1774             // An inherent impl is public when its type is public
1775             // Subitems of inherent impls have their own publicity
1776             hir::ItemImpl(_, _, ref generics, None, ref ty, ref impl_items) => {
1777                 if self.is_public_ty(ty) {
1778                     check.visit_generics(generics);
1779                     for impl_item in impl_items {
1780                         if impl_item.vis == hir::Public {
1781                             check.visit_impl_item(impl_item);
1782                         }
1783                     }
1784                 }
1785             }
1786             // A trait impl is public when both its type and its trait are public
1787             // Subitems of trait impls have inherited publicity
1788             hir::ItemImpl(_, _, ref generics, Some(ref trait_ref), ref ty, ref impl_items) => {
1789                 if self.is_public_ty(ty) && self.is_public_trait_ref(trait_ref) {
1790                     check.visit_generics(generics);
1791                     for impl_item in impl_items {
1792                         check.visit_impl_item(impl_item);
1793                     }
1794                 }
1795             }
1796         }
1797     }
1798 }
1799
1800 pub fn check_crate(tcx: &ty::ctxt,
1801                    export_map: &def::ExportMap,
1802                    external_exports: ExternalExports)
1803                    -> AccessLevels {
1804     let _task = tcx.dep_graph.in_task(DepNode::Privacy);
1805
1806     let krate = tcx.map.krate();
1807
1808     // Sanity check to make sure that all privacy usage and controls are
1809     // reasonable.
1810     let mut visitor = SanePrivacyVisitor {
1811         tcx: tcx,
1812         in_block: false,
1813     };
1814     intravisit::walk_crate(&mut visitor, krate);
1815
1816     // Figure out who everyone's parent is
1817     let mut visitor = ParentVisitor {
1818         tcx: tcx,
1819         parents: NodeMap(),
1820         curparent: ast::DUMMY_NODE_ID,
1821     };
1822     intravisit::walk_crate(&mut visitor, krate);
1823
1824     // Use the parent map to check the privacy of everything
1825     let mut visitor = PrivacyVisitor {
1826         curitem: ast::DUMMY_NODE_ID,
1827         in_foreign: false,
1828         tcx: tcx,
1829         parents: visitor.parents,
1830         external_exports: external_exports,
1831     };
1832     intravisit::walk_crate(&mut visitor, krate);
1833
1834     tcx.sess.abort_if_errors();
1835
1836     // Build up a set of all exported items in the AST. This is a set of all
1837     // items which are reachable from external crates based on visibility.
1838     let mut visitor = EmbargoVisitor {
1839         tcx: tcx,
1840         export_map: export_map,
1841         access_levels: Default::default(),
1842         prev_level: Some(AccessLevel::Public),
1843         changed: false,
1844     };
1845     loop {
1846         intravisit::walk_crate(&mut visitor, krate);
1847         if visitor.changed {
1848             visitor.changed = false;
1849         } else {
1850             break
1851         }
1852     }
1853     visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public));
1854
1855     {
1856         let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
1857             tcx: tcx,
1858             access_levels: &visitor.access_levels,
1859             in_variant: false,
1860             old_error_set: NodeSet(),
1861         };
1862         intravisit::walk_crate(&mut visitor, krate);
1863
1864         // Check for private types and traits in public interfaces
1865         let mut visitor = PrivateItemsInPublicInterfacesVisitor {
1866             tcx: tcx,
1867             old_error_set: &visitor.old_error_set,
1868         };
1869         krate.visit_all_items(&mut visitor);
1870     }
1871
1872     visitor.access_levels
1873 }
1874
1875 __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }