]> git.lizzy.rs Git - rust.git/blob - src/librustc_privacy/lib.rs
3b865e6ce0ff8638f9fbe2cb67e80d0f25b77867
[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 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
12        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
13        html_root_url = "https://doc.rust-lang.org/nightly/")]
14
15 #![feature(rustc_diagnostic_macros)]
16
17 #![recursion_limit="256"]
18
19 #[macro_use] extern crate rustc;
20 #[macro_use] extern crate syntax;
21 extern crate rustc_typeck;
22 extern crate syntax_pos;
23 extern crate rustc_data_structures;
24
25 use rustc::hir::{self, GenericParamKind, PatKind};
26 use rustc::hir::def::Def;
27 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
28 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
29 use rustc::hir::itemlikevisit::DeepVisitor;
30 use rustc::lint;
31 use rustc::middle::privacy::{AccessLevel, AccessLevels};
32 use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind};
33 use rustc::ty::fold::TypeVisitor;
34 use rustc::ty::query::Providers;
35 use rustc::ty::subst::UnpackedKind;
36 use rustc::util::nodemap::NodeSet;
37 use syntax::ast::{self, CRATE_NODE_ID, Ident};
38 use syntax::symbol::keywords;
39 use syntax_pos::Span;
40
41 use std::cmp;
42 use std::mem::replace;
43 use rustc_data_structures::fx::FxHashSet;
44 use rustc_data_structures::sync::Lrc;
45
46 mod diagnostics;
47
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Visitor used to determine if pub(restricted) is used anywhere in the crate.
50 ///
51 /// This is done so that `private_in_public` warnings can be turned into hard errors
52 /// in crates that have been updated to use pub(restricted).
53 ////////////////////////////////////////////////////////////////////////////////
54 struct PubRestrictedVisitor<'a, 'tcx: 'a> {
55     tcx:  TyCtxt<'a, 'tcx, 'tcx>,
56     has_pub_restricted: bool,
57 }
58
59 impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> {
60     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
61         NestedVisitorMap::All(&self.tcx.hir)
62     }
63     fn visit_vis(&mut self, vis: &'tcx hir::Visibility) {
64         self.has_pub_restricted = self.has_pub_restricted || vis.is_pub_restricted();
65     }
66 }
67
68 ////////////////////////////////////////////////////////////////////////////////
69 /// The embargo visitor, used to determine the exports of the ast
70 ////////////////////////////////////////////////////////////////////////////////
71
72 struct EmbargoVisitor<'a, 'tcx: 'a> {
73     tcx: TyCtxt<'a, 'tcx, 'tcx>,
74
75     // Accessibility levels for reachable nodes
76     access_levels: AccessLevels,
77     // Previous accessibility level, None means unreachable
78     prev_level: Option<AccessLevel>,
79     // Have something changed in the level map?
80     changed: bool,
81 }
82
83 struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
84     item_def_id: DefId,
85     ev: &'b mut EmbargoVisitor<'a, 'tcx>,
86 }
87
88 impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
89     fn item_ty_level(&self, item_def_id: DefId) -> Option<AccessLevel> {
90         let ty_def_id = match self.tcx.type_of(item_def_id).sty {
91             ty::TyAdt(adt, _) => adt.did,
92             ty::TyForeign(did) => did,
93             ty::TyDynamic(ref obj, ..) if obj.principal().is_some() =>
94                 obj.principal().unwrap().def_id(),
95             ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id,
96             _ => return Some(AccessLevel::Public)
97         };
98         if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) {
99             self.get(node_id)
100         } else {
101             Some(AccessLevel::Public)
102         }
103     }
104
105     fn impl_trait_level(&self, impl_def_id: DefId) -> Option<AccessLevel> {
106         if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) {
107             if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) {
108                 return self.get(node_id);
109             }
110         }
111         Some(AccessLevel::Public)
112     }
113
114     fn get(&self, id: ast::NodeId) -> Option<AccessLevel> {
115         self.access_levels.map.get(&id).cloned()
116     }
117
118     // Updates node level and returns the updated level
119     fn update(&mut self, id: ast::NodeId, level: Option<AccessLevel>) -> Option<AccessLevel> {
120         let old_level = self.get(id);
121         // Accessibility levels can only grow
122         if level > old_level {
123             self.access_levels.map.insert(id, level.unwrap());
124             self.changed = true;
125             level
126         } else {
127             old_level
128         }
129     }
130
131     fn reach<'b>(&'b mut self, item_id: ast::NodeId)
132                  -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
133         ReachEverythingInTheInterfaceVisitor {
134             item_def_id: self.tcx.hir.local_def_id(item_id),
135             ev: self,
136         }
137     }
138 }
139
140 impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
141     /// We want to visit items in the context of their containing
142     /// module and so forth, so supply a crate for doing a deep walk.
143     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
144         NestedVisitorMap::All(&self.tcx.hir)
145     }
146
147     fn visit_item(&mut self, item: &'tcx hir::Item) {
148         let inherited_item_level = match item.node {
149             // Impls inherit level from their types and traits
150             hir::ItemImpl(..) => {
151                 let def_id = self.tcx.hir.local_def_id(item.id);
152                 cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id))
153             }
154             // Foreign mods inherit level from parents
155             hir::ItemForeignMod(..) => {
156                 self.prev_level
157             }
158             // Other `pub` items inherit levels from parents
159             hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
160             hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
161             hir::ItemStatic(..) | hir::ItemStruct(..) |
162             hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
163             hir::ItemExistential(..) |
164             hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
165                 if item.vis == hir::Public { self.prev_level } else { None }
166             }
167         };
168
169         // Update level of the item itself
170         let item_level = self.update(item.id, inherited_item_level);
171
172         // Update levels of nested things
173         match item.node {
174             hir::ItemEnum(ref def, _) => {
175                 for variant in &def.variants {
176                     let variant_level = self.update(variant.node.data.id(), item_level);
177                     for field in variant.node.data.fields() {
178                         self.update(field.id, variant_level);
179                     }
180                 }
181             }
182             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
183                 for impl_item_ref in impl_item_refs {
184                     if impl_item_ref.vis == hir::Public {
185                         self.update(impl_item_ref.id.node_id, item_level);
186                     }
187                 }
188             }
189             hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
190                 for impl_item_ref in impl_item_refs {
191                     self.update(impl_item_ref.id.node_id, item_level);
192                 }
193             }
194             hir::ItemTrait(.., ref trait_item_refs) => {
195                 for trait_item_ref in trait_item_refs {
196                     self.update(trait_item_ref.id.node_id, item_level);
197                 }
198             }
199             hir::ItemStruct(ref def, _) | hir::ItemUnion(ref def, _) => {
200                 if !def.is_struct() {
201                     self.update(def.id(), item_level);
202                 }
203                 for field in def.fields() {
204                     if field.vis == hir::Public {
205                         self.update(field.id, item_level);
206                     }
207                 }
208             }
209             hir::ItemForeignMod(ref foreign_mod) => {
210                 for foreign_item in &foreign_mod.items {
211                     if foreign_item.vis == hir::Public {
212                         self.update(foreign_item.id, item_level);
213                     }
214                 }
215             }
216             hir::ItemExistential(..) |
217             hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
218             hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
219             hir::ItemFn(..) | hir::ItemExternCrate(..) => {}
220         }
221
222         // Mark all items in interfaces of reachable items as reachable
223         match item.node {
224             // The interface is empty
225             hir::ItemExternCrate(..) => {}
226             // All nested items are checked by visit_item
227             hir::ItemMod(..) => {}
228             // Re-exports are handled in visit_mod
229             hir::ItemUse(..) => {}
230             // The interface is empty
231             hir::ItemGlobalAsm(..) => {}
232             // Checked by visit_ty
233             hir::ItemExistential(..) => {}
234             // Visit everything
235             hir::ItemConst(..) | hir::ItemStatic(..) |
236             hir::ItemFn(..) | hir::ItemTy(..) => {
237                 if item_level.is_some() {
238                     self.reach(item.id).generics().predicates().ty();
239                 }
240             }
241             hir::ItemTrait(.., ref trait_item_refs) => {
242                 if item_level.is_some() {
243                     self.reach(item.id).generics().predicates();
244
245                     for trait_item_ref in trait_item_refs {
246                         let mut reach = self.reach(trait_item_ref.id.node_id);
247                         reach.generics().predicates();
248
249                         if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
250                            !trait_item_ref.defaultness.has_value() {
251                             // No type to visit.
252                         } else {
253                             reach.ty();
254                         }
255                     }
256                 }
257             }
258             hir::ItemTraitAlias(..) => {
259                 if item_level.is_some() {
260                     self.reach(item.id).generics().predicates();
261                 }
262             }
263             // Visit everything except for private impl items
264             hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
265                 if item_level.is_some() {
266                     self.reach(item.id).generics().predicates().impl_trait_ref();
267
268                     for impl_item_ref in impl_item_refs {
269                         let id = impl_item_ref.id.node_id;
270                         if trait_ref.is_some() || self.get(id).is_some() {
271                             self.reach(id).generics().predicates().ty();
272                         }
273                     }
274                 }
275             }
276
277             // Visit everything, but enum variants have their own levels
278             hir::ItemEnum(ref def, _) => {
279                 if item_level.is_some() {
280                     self.reach(item.id).generics().predicates();
281                 }
282                 for variant in &def.variants {
283                     if self.get(variant.node.data.id()).is_some() {
284                         for field in variant.node.data.fields() {
285                             self.reach(field.id).ty();
286                         }
287                         // Corner case: if the variant is reachable, but its
288                         // enum is not, make the enum reachable as well.
289                         self.update(item.id, Some(AccessLevel::Reachable));
290                     }
291                 }
292             }
293             // Visit everything, but foreign items have their own levels
294             hir::ItemForeignMod(ref foreign_mod) => {
295                 for foreign_item in &foreign_mod.items {
296                     if self.get(foreign_item.id).is_some() {
297                         self.reach(foreign_item.id).generics().predicates().ty();
298                     }
299                 }
300             }
301             // Visit everything except for private fields
302             hir::ItemStruct(ref struct_def, _) |
303             hir::ItemUnion(ref struct_def, _) => {
304                 if item_level.is_some() {
305                     self.reach(item.id).generics().predicates();
306                     for field in struct_def.fields() {
307                         if self.get(field.id).is_some() {
308                             self.reach(field.id).ty();
309                         }
310                     }
311                 }
312             }
313         }
314
315         let orig_level = self.prev_level;
316         self.prev_level = item_level;
317
318         intravisit::walk_item(self, item);
319
320         self.prev_level = orig_level;
321     }
322
323     fn visit_block(&mut self, b: &'tcx hir::Block) {
324         let orig_level = replace(&mut self.prev_level, None);
325
326         // Blocks can have public items, for example impls, but they always
327         // start as completely private regardless of publicity of a function,
328         // constant, type, field, etc. in which this block resides
329         intravisit::walk_block(self, b);
330
331         self.prev_level = orig_level;
332     }
333
334     fn visit_mod(&mut self, m: &'tcx hir::Mod, _sp: Span, id: ast::NodeId) {
335         // This code is here instead of in visit_item so that the
336         // crate module gets processed as well.
337         if self.prev_level.is_some() {
338             let def_id = self.tcx.hir.local_def_id(id);
339             if let Some(exports) = self.tcx.module_exports(def_id) {
340                 for export in exports.iter() {
341                     if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
342                         if export.vis == ty::Visibility::Public {
343                             self.update(node_id, Some(AccessLevel::Exported));
344                         }
345                     }
346                 }
347             }
348         }
349
350         intravisit::walk_mod(self, m, id);
351     }
352
353     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
354         if md.legacy {
355             self.update(md.id, Some(AccessLevel::Public));
356             return
357         }
358
359         let module_did = ty::DefIdTree::parent(self.tcx, self.tcx.hir.local_def_id(md.id)).unwrap();
360         let mut module_id = self.tcx.hir.as_local_node_id(module_did).unwrap();
361         let level = if md.vis == hir::Public { self.get(module_id) } else { None };
362         let level = self.update(md.id, level);
363         if level.is_none() {
364             return
365         }
366
367         loop {
368             let module = if module_id == ast::CRATE_NODE_ID {
369                 &self.tcx.hir.krate().module
370             } else if let hir::ItemMod(ref module) = self.tcx.hir.expect_item(module_id).node {
371                 module
372             } else {
373                 unreachable!()
374             };
375             for id in &module.item_ids {
376                 self.update(id.id, level);
377             }
378             let def_id = self.tcx.hir.local_def_id(module_id);
379             if let Some(exports) = self.tcx.module_exports(def_id) {
380                 for export in exports.iter() {
381                     if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
382                         self.update(node_id, level);
383                     }
384                 }
385             }
386
387             if module_id == ast::CRATE_NODE_ID {
388                 break
389             }
390             module_id = self.tcx.hir.get_parent_node(module_id);
391         }
392     }
393
394     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
395         if let hir::TyImplTraitExistential(item_id, _, _) = ty.node {
396             if self.get(item_id.id).is_some() {
397                 // Reach the (potentially private) type and the API being exposed
398                 self.reach(item_id.id).ty().predicates();
399             }
400         }
401
402         intravisit::walk_ty(self, ty);
403     }
404 }
405
406 impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
407     fn generics(&mut self) -> &mut Self {
408         for param in &self.ev.tcx.generics_of(self.item_def_id).params {
409             match param.kind {
410                 GenericParamDefKind::Type { has_default, .. } => {
411                     if has_default {
412                         self.ev.tcx.type_of(param.def_id).visit_with(self);
413                     }
414                 }
415                 GenericParamDefKind::Lifetime => {}
416             }
417         }
418         self
419     }
420
421     fn predicates(&mut self) -> &mut Self {
422         let predicates = self.ev.tcx.predicates_of(self.item_def_id);
423         for predicate in &predicates.predicates {
424             predicate.visit_with(self);
425             match predicate {
426                 &ty::Predicate::Trait(poly_predicate) => {
427                     self.check_trait_ref(poly_predicate.skip_binder().trait_ref);
428                 },
429                 &ty::Predicate::Projection(poly_predicate) => {
430                     let tcx = self.ev.tcx;
431                     self.check_trait_ref(
432                         poly_predicate.skip_binder().projection_ty.trait_ref(tcx)
433                     );
434                 },
435                 _ => (),
436             };
437         }
438         self
439     }
440
441     fn ty(&mut self) -> &mut Self {
442         let ty = self.ev.tcx.type_of(self.item_def_id);
443         self.walk_ty(ty)
444     }
445
446     fn walk_ty(&mut self, ty: Ty<'tcx>) -> &mut Self {
447         ty.visit_with(self);
448         if let ty::TyFnDef(def_id, _) = ty.sty {
449             if def_id == self.item_def_id {
450                 self.ev.tcx.fn_sig(def_id).visit_with(self);
451             }
452         }
453         self
454     }
455
456     fn impl_trait_ref(&mut self) -> &mut Self {
457         if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
458             self.check_trait_ref(impl_trait_ref);
459             impl_trait_ref.super_visit_with(self);
460         }
461         self
462     }
463
464     fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
465         if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) {
466             let item = self.ev.tcx.hir.expect_item(node_id);
467             self.ev.update(item.id, Some(AccessLevel::Reachable));
468         }
469     }
470 }
471
472 impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
473     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
474         let ty_def_id = match ty.sty {
475             ty::TyAdt(adt, _) => Some(adt.did),
476             ty::TyForeign(did) => Some(did),
477             ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
478             ty::TyProjection(ref proj) => Some(proj.item_def_id),
479             ty::TyFnDef(def_id, ..) |
480             ty::TyClosure(def_id, ..) |
481             ty::TyGenerator(def_id, ..) |
482             ty::TyAnon(def_id, _) => Some(def_id),
483             _ => None
484         };
485
486         if let Some(def_id) = ty_def_id {
487             if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(def_id) {
488                 self.ev.update(node_id, Some(AccessLevel::Reachable));
489             }
490         }
491
492         ty.super_visit_with(self)
493     }
494 }
495
496 //////////////////////////////////////////////////////////////////////////////////////
497 /// Name privacy visitor, checks privacy and reports violations.
498 /// Most of name privacy checks are performed during the main resolution phase,
499 /// or later in type checking when field accesses and associated items are resolved.
500 /// This pass performs remaining checks for fields in struct expressions and patterns.
501 //////////////////////////////////////////////////////////////////////////////////////
502
503 struct NamePrivacyVisitor<'a, 'tcx: 'a> {
504     tcx: TyCtxt<'a, 'tcx, 'tcx>,
505     tables: &'a ty::TypeckTables<'tcx>,
506     current_item: ast::NodeId,
507     empty_tables: &'a ty::TypeckTables<'tcx>,
508 }
509
510 impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
511     // Checks that a field in a struct constructor (expression or pattern) is accessible.
512     fn check_field(&mut self,
513                    use_ctxt: Span, // Syntax context of the field name at the use site
514                    span: Span, // Span of the field pattern, e.g. `x: 0`
515                    def: &'tcx ty::AdtDef, // Definition of the struct or enum
516                    field: &'tcx ty::FieldDef) { // Definition of the field
517         let ident = Ident::new(keywords::Invalid.name(), use_ctxt);
518         let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1;
519         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
520             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
521                              field.ident, def.variant_descr(), self.tcx.item_path_str(def.did))
522                 .span_label(span, format!("field `{}` is private", field.ident))
523                 .emit();
524         }
525     }
526 }
527
528 // Set the correct TypeckTables for the given `item_id` (or an empty table if
529 // there is no TypeckTables for the item).
530 fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
531                            item_id: ast::NodeId,
532                            tables: &mut &'a ty::TypeckTables<'tcx>,
533                            empty_tables: &'a ty::TypeckTables<'tcx>)
534                            -> &'a ty::TypeckTables<'tcx> {
535     let def_id = tcx.hir.local_def_id(item_id);
536
537     if tcx.has_typeck_tables(def_id) {
538         replace(tables, tcx.typeck_tables_of(def_id))
539     } else {
540         replace(tables, empty_tables)
541     }
542 }
543
544 impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
545     /// We want to visit items in the context of their containing
546     /// module and so forth, so supply a crate for doing a deep walk.
547     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
548         NestedVisitorMap::All(&self.tcx.hir)
549     }
550
551     fn visit_nested_body(&mut self, body: hir::BodyId) {
552         let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body));
553         let body = self.tcx.hir.body(body);
554         self.visit_body(body);
555         self.tables = orig_tables;
556     }
557
558     fn visit_item(&mut self, item: &'tcx hir::Item) {
559         let orig_current_item = replace(&mut self.current_item, item.id);
560         let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables);
561         intravisit::walk_item(self, item);
562         self.current_item = orig_current_item;
563         self.tables = orig_tables;
564     }
565
566     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
567         let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables);
568         intravisit::walk_trait_item(self, ti);
569         self.tables = orig_tables;
570     }
571
572     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
573         let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables);
574         intravisit::walk_impl_item(self, ii);
575         self.tables = orig_tables;
576     }
577
578     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
579         match expr.node {
580             hir::ExprStruct(ref qpath, ref fields, ref base) => {
581                 let def = self.tables.qpath_def(qpath, expr.hir_id);
582                 let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap();
583                 let variant = adt.variant_of_def(def);
584                 if let Some(ref base) = *base {
585                     // If the expression uses FRU we need to make sure all the unmentioned fields
586                     // are checked for privacy (RFC 736). Rather than computing the set of
587                     // unmentioned fields, just check them all.
588                     for (vf_index, variant_field) in variant.fields.iter().enumerate() {
589                         let field = fields.iter().find(|f| {
590                             self.tcx.field_index(f.id, self.tables) == vf_index
591                         });
592                         let (use_ctxt, span) = match field {
593                             Some(field) => (field.ident.span, field.span),
594                             None => (base.span, base.span),
595                         };
596                         self.check_field(use_ctxt, span, adt, variant_field);
597                     }
598                 } else {
599                     for field in fields {
600                         let use_ctxt = field.ident.span;
601                         let index = self.tcx.field_index(field.id, self.tables);
602                         self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
603                     }
604                 }
605             }
606             _ => {}
607         }
608
609         intravisit::walk_expr(self, expr);
610     }
611
612     fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
613         match pat.node {
614             PatKind::Struct(ref qpath, ref fields, _) => {
615                 let def = self.tables.qpath_def(qpath, pat.hir_id);
616                 let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
617                 let variant = adt.variant_of_def(def);
618                 for field in fields {
619                     let use_ctxt = field.node.ident.span;
620                     let index = self.tcx.field_index(field.node.id, self.tables);
621                     self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
622                 }
623             }
624             _ => {}
625         }
626
627         intravisit::walk_pat(self, pat);
628     }
629 }
630
631 ////////////////////////////////////////////////////////////////////////////////////////////
632 /// Type privacy visitor, checks types for privacy and reports violations.
633 /// Both explicitly written types and inferred types of expressions and patters are checked.
634 /// Checks are performed on "semantic" types regardless of names and their hygiene.
635 ////////////////////////////////////////////////////////////////////////////////////////////
636
637 struct TypePrivacyVisitor<'a, 'tcx: 'a> {
638     tcx: TyCtxt<'a, 'tcx, 'tcx>,
639     tables: &'a ty::TypeckTables<'tcx>,
640     current_item: DefId,
641     in_body: bool,
642     span: Span,
643     empty_tables: &'a ty::TypeckTables<'tcx>,
644     visited_anon_tys: FxHashSet<DefId>
645 }
646
647 impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
648     fn def_id_visibility(&self, did: DefId) -> ty::Visibility {
649         match self.tcx.hir.as_local_node_id(did) {
650             Some(node_id) => {
651                 let vis = match self.tcx.hir.get(node_id) {
652                     hir::map::NodeItem(item) => &item.vis,
653                     hir::map::NodeForeignItem(foreign_item) => &foreign_item.vis,
654                     hir::map::NodeImplItem(impl_item) => &impl_item.vis,
655                     hir::map::NodeTraitItem(..) |
656                     hir::map::NodeVariant(..) => {
657                         return self.def_id_visibility(self.tcx.hir.get_parent_did(node_id));
658                     }
659                     hir::map::NodeStructCtor(vdata) => {
660                         let struct_node_id = self.tcx.hir.get_parent(node_id);
661                         let struct_vis = match self.tcx.hir.get(struct_node_id) {
662                             hir::map::NodeItem(item) => &item.vis,
663                             node => bug!("unexpected node kind: {:?}", node),
664                         };
665                         let mut ctor_vis
666                             = ty::Visibility::from_hir(struct_vis, struct_node_id, self.tcx);
667                         for field in vdata.fields() {
668                             let field_vis = ty::Visibility::from_hir(&field.vis, node_id, self.tcx);
669                             if ctor_vis.is_at_least(field_vis, self.tcx) {
670                                 ctor_vis = field_vis;
671                             }
672                         }
673
674                         // If the structure is marked as non_exhaustive then lower the
675                         // visibility to within the crate.
676                         let struct_def_id = self.tcx.hir.get_parent_did(node_id);
677                         let adt_def = self.tcx.adt_def(struct_def_id);
678                         if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
679                             ctor_vis = ty::Visibility::Restricted(
680                                 DefId::local(CRATE_DEF_INDEX));
681                         }
682
683                         return ctor_vis;
684                     }
685                     node => bug!("unexpected node kind: {:?}", node)
686                 };
687                 ty::Visibility::from_hir(vis, node_id, self.tcx)
688             }
689             None => self.tcx.visibility(did),
690         }
691     }
692
693     fn item_is_accessible(&self, did: DefId) -> bool {
694         self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx)
695     }
696
697     // Take node ID of an expression or pattern and check its type for privacy.
698     fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
699         self.span = span;
700         if self.tables.node_id_to_type(id).visit_with(self) {
701             return true;
702         }
703         if self.tables.node_substs(id).visit_with(self) {
704             return true;
705         }
706         if let Some(adjustments) = self.tables.adjustments().get(id) {
707             for adjustment in adjustments {
708                 if adjustment.target.visit_with(self) {
709                     return true;
710                 }
711             }
712         }
713         false
714     }
715
716     fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
717         if !self.item_is_accessible(trait_ref.def_id) {
718             let msg = format!("trait `{}` is private", trait_ref);
719             self.tcx.sess.span_err(self.span, &msg);
720             return true;
721         }
722
723         trait_ref.super_visit_with(self)
724     }
725 }
726
727 impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
728     /// We want to visit items in the context of their containing
729     /// module and so forth, so supply a crate for doing a deep walk.
730     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
731         NestedVisitorMap::All(&self.tcx.hir)
732     }
733
734     fn visit_nested_body(&mut self, body: hir::BodyId) {
735         let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body));
736         let orig_in_body = replace(&mut self.in_body, true);
737         let body = self.tcx.hir.body(body);
738         self.visit_body(body);
739         self.tables = orig_tables;
740         self.in_body = orig_in_body;
741     }
742
743     fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty) {
744         self.span = hir_ty.span;
745         if self.in_body {
746             // Types in bodies.
747             if self.tables.node_id_to_type(hir_ty.hir_id).visit_with(self) {
748                 return;
749             }
750         } else {
751             // Types in signatures.
752             // FIXME: This is very ineffective. Ideally each HIR type should be converted
753             // into a semantic type only once and the result should be cached somehow.
754             if rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty).visit_with(self) {
755                 return;
756             }
757         }
758
759         intravisit::walk_ty(self, hir_ty);
760     }
761
762     fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef) {
763         self.span = trait_ref.path.span;
764         if !self.in_body {
765             // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
766             // The traits' privacy in bodies is already checked as a part of trait object types.
767             let (principal, projections) =
768                 rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref);
769             if self.check_trait_ref(*principal.skip_binder()) {
770                 return;
771             }
772             for poly_predicate in projections {
773                 let tcx = self.tcx;
774                 if self.check_trait_ref(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) {
775                     return;
776                 }
777             }
778         }
779
780         intravisit::walk_trait_ref(self, trait_ref);
781     }
782
783     // Check types of expressions
784     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
785         if self.check_expr_pat_type(expr.hir_id, expr.span) {
786             // Do not check nested expressions if the error already happened.
787             return;
788         }
789         match expr.node {
790             hir::ExprAssign(.., ref rhs) | hir::ExprMatch(ref rhs, ..) => {
791                 // Do not report duplicate errors for `x = y` and `match x { ... }`.
792                 if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
793                     return;
794                 }
795             }
796             hir::ExprMethodCall(_, span, _) => {
797                 // Method calls have to be checked specially.
798                 let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id();
799                 self.span = span;
800                 if self.tcx.type_of(def_id).visit_with(self) {
801                     return;
802                 }
803             }
804             _ => {}
805         }
806
807         intravisit::walk_expr(self, expr);
808     }
809
810     // Prohibit access to associated items with insufficient nominal visibility.
811     //
812     // Additionally, until better reachability analysis for macros 2.0 is available,
813     // we prohibit access to private statics from other crates, this allows to give
814     // more code internal visibility at link time. (Access to private functions
815     // is already prohibited by type privacy for function types.)
816     fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: ast::NodeId, span: Span) {
817         let def = match *qpath {
818             hir::QPath::Resolved(_, ref path) => match path.def {
819                 Def::Method(..) | Def::AssociatedConst(..) |
820                 Def::AssociatedTy(..) | Def::Static(..) => Some(path.def),
821                 _ => None,
822             }
823             hir::QPath::TypeRelative(..) => {
824                 let hir_id = self.tcx.hir.node_to_hir_id(id);
825                 self.tables.type_dependent_defs().get(hir_id).cloned()
826             }
827         };
828         if let Some(def) = def {
829             let def_id = def.def_id();
830             let is_local_static = if let Def::Static(..) = def { def_id.is_local() } else { false };
831             if !self.item_is_accessible(def_id) && !is_local_static {
832                 let name = match *qpath {
833                     hir::QPath::Resolved(_, ref path) => format!("{}", path),
834                     hir::QPath::TypeRelative(_, ref segment) => segment.name.to_string(),
835                 };
836                 let msg = format!("{} `{}` is private", def.kind_name(), name);
837                 self.tcx.sess.span_err(span, &msg);
838                 return;
839             }
840         }
841
842         intravisit::walk_qpath(self, qpath, id, span);
843     }
844
845     // Check types of patterns
846     fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
847         if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
848             // Do not check nested patterns if the error already happened.
849             return;
850         }
851
852         intravisit::walk_pat(self, pattern);
853     }
854
855     fn visit_local(&mut self, local: &'tcx hir::Local) {
856         if let Some(ref init) = local.init {
857             if self.check_expr_pat_type(init.hir_id, init.span) {
858                 // Do not report duplicate errors for `let x = y`.
859                 return;
860             }
861         }
862
863         intravisit::walk_local(self, local);
864     }
865
866     // Check types in item interfaces
867     fn visit_item(&mut self, item: &'tcx hir::Item) {
868         let orig_current_item = self.current_item;
869         let orig_tables = update_tables(self.tcx,
870                                         item.id,
871                                         &mut self.tables,
872                                         self.empty_tables);
873         let orig_in_body = replace(&mut self.in_body, false);
874         self.current_item = self.tcx.hir.local_def_id(item.id);
875         intravisit::walk_item(self, item);
876         self.tables = orig_tables;
877         self.in_body = orig_in_body;
878         self.current_item = orig_current_item;
879     }
880
881     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
882         let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables);
883         intravisit::walk_trait_item(self, ti);
884         self.tables = orig_tables;
885     }
886
887     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
888         let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables);
889         intravisit::walk_impl_item(self, ii);
890         self.tables = orig_tables;
891     }
892 }
893
894 impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
895     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
896         match ty.sty {
897             ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) |
898             ty::TyFnDef(def_id, ..) |
899             ty::TyForeign(def_id) => {
900                 if !self.item_is_accessible(def_id) {
901                     let msg = format!("type `{}` is private", ty);
902                     self.tcx.sess.span_err(self.span, &msg);
903                     return true;
904                 }
905                 if let ty::TyFnDef(..) = ty.sty {
906                     if self.tcx.fn_sig(def_id).visit_with(self) {
907                         return true;
908                     }
909                 }
910                 // Inherent static methods don't have self type in substs,
911                 // we have to check it additionally.
912                 if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
913                     if let ty::ImplContainer(impl_def_id) = assoc_item.container {
914                         if self.tcx.type_of(impl_def_id).visit_with(self) {
915                             return true;
916                         }
917                     }
918                 }
919             }
920             ty::TyDynamic(ref predicates, ..) => {
921                 let is_private = predicates.skip_binder().iter().any(|predicate| {
922                     let def_id = match *predicate {
923                         ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id,
924                         ty::ExistentialPredicate::Projection(proj) =>
925                             proj.trait_ref(self.tcx).def_id,
926                         ty::ExistentialPredicate::AutoTrait(def_id) => def_id,
927                     };
928                     !self.item_is_accessible(def_id)
929                 });
930                 if is_private {
931                     let msg = format!("type `{}` is private", ty);
932                     self.tcx.sess.span_err(self.span, &msg);
933                     return true;
934                 }
935             }
936             ty::TyProjection(ref proj) => {
937                 let tcx = self.tcx;
938                 if self.check_trait_ref(proj.trait_ref(tcx)) {
939                     return true;
940                 }
941             }
942             ty::TyAnon(def_id, ..) => {
943                 for predicate in &self.tcx.predicates_of(def_id).predicates {
944                     let trait_ref = match *predicate {
945                         ty::Predicate::Trait(ref poly_trait_predicate) => {
946                             Some(poly_trait_predicate.skip_binder().trait_ref)
947                         }
948                         ty::Predicate::Projection(ref poly_projection_predicate) => {
949                             if poly_projection_predicate.skip_binder().ty.visit_with(self) {
950                                 return true;
951                             }
952                             Some(poly_projection_predicate.skip_binder()
953                                                           .projection_ty.trait_ref(self.tcx))
954                         }
955                         ty::Predicate::TypeOutlives(..) => None,
956                         _ => bug!("unexpected predicate: {:?}", predicate),
957                     };
958                     if let Some(trait_ref) = trait_ref {
959                         if !self.item_is_accessible(trait_ref.def_id) {
960                             let msg = format!("trait `{}` is private", trait_ref);
961                             self.tcx.sess.span_err(self.span, &msg);
962                             return true;
963                         }
964                         for subst in trait_ref.substs.iter() {
965                             // Skip repeated `TyAnon`s to avoid infinite recursion.
966                             if let UnpackedKind::Type(ty) = subst.unpack() {
967                                 if let ty::TyAnon(def_id, ..) = ty.sty {
968                                     if !self.visited_anon_tys.insert(def_id) {
969                                         continue;
970                                     }
971                                 }
972                             }
973                             if subst.visit_with(self) {
974                                 return true;
975                             }
976                         }
977                     }
978                 }
979             }
980             _ => {}
981         }
982
983         ty.super_visit_with(self)
984     }
985 }
986
987 ///////////////////////////////////////////////////////////////////////////////
988 /// Obsolete visitors for checking for private items in public interfaces.
989 /// These visitors are supposed to be kept in frozen state and produce an
990 /// "old error node set". For backward compatibility the new visitor reports
991 /// warnings instead of hard errors when the erroneous node is not in this old set.
992 ///////////////////////////////////////////////////////////////////////////////
993
994 struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
995     tcx: TyCtxt<'a, 'tcx, 'tcx>,
996     access_levels: &'a AccessLevels,
997     in_variant: bool,
998     // set of errors produced by this obsolete visitor
999     old_error_set: NodeSet,
1000 }
1001
1002 struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
1003     inner: &'a ObsoleteVisiblePrivateTypesVisitor<'b, 'tcx>,
1004     /// whether the type refers to private types.
1005     contains_private: bool,
1006     /// whether we've recurred at all (i.e. if we're pointing at the
1007     /// first type on which visit_ty was called).
1008     at_outer_type: bool,
1009     // whether that first type is a public path.
1010     outer_type_is_public_path: bool,
1011 }
1012
1013 impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1014     fn path_is_private_type(&self, path: &hir::Path) -> bool {
1015         let did = match path.def {
1016             Def::PrimTy(..) | Def::SelfTy(..) => return false,
1017             def => def.def_id(),
1018         };
1019
1020         // A path can only be private if:
1021         // it's in this crate...
1022         if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
1023             // .. and it corresponds to a private type in the AST (this returns
1024             // None for type parameters)
1025             match self.tcx.hir.find(node_id) {
1026                 Some(hir::map::NodeItem(ref item)) => item.vis != hir::Public,
1027                 Some(_) | None => false,
1028             }
1029         } else {
1030             return false
1031         }
1032     }
1033
1034     fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
1035         // FIXME: this would preferably be using `exported_items`, but all
1036         // traits are exported currently (see `EmbargoVisitor.exported_trait`)
1037         self.access_levels.is_public(trait_id)
1038     }
1039
1040     fn check_ty_param_bound(&mut self, bound: &hir::GenericBound) {
1041         if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
1042             if self.path_is_private_type(&trait_ref.trait_ref.path) {
1043                 self.old_error_set.insert(trait_ref.trait_ref.ref_id);
1044             }
1045         }
1046     }
1047
1048     fn item_is_public(&self, id: &ast::NodeId, vis: &hir::Visibility) -> bool {
1049         self.access_levels.is_reachable(*id) || *vis == hir::Public
1050     }
1051 }
1052
1053 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
1054     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
1055         NestedVisitorMap::None
1056     }
1057
1058     fn visit_ty(&mut self, ty: &hir::Ty) {
1059         if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = ty.node {
1060             if self.inner.path_is_private_type(path) {
1061                 self.contains_private = true;
1062                 // found what we're looking for so let's stop
1063                 // working.
1064                 return
1065             }
1066         }
1067         if let hir::TyPath(_) = ty.node {
1068             if self.at_outer_type {
1069                 self.outer_type_is_public_path = true;
1070             }
1071         }
1072         self.at_outer_type = false;
1073         intravisit::walk_ty(self, ty)
1074     }
1075
1076     // don't want to recurse into [, .. expr]
1077     fn visit_expr(&mut self, _: &hir::Expr) {}
1078 }
1079
1080 impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1081     /// We want to visit items in the context of their containing
1082     /// module and so forth, so supply a crate for doing a deep walk.
1083     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1084         NestedVisitorMap::All(&self.tcx.hir)
1085     }
1086
1087     fn visit_item(&mut self, item: &'tcx hir::Item) {
1088         match item.node {
1089             // contents of a private mod can be re-exported, so we need
1090             // to check internals.
1091             hir::ItemMod(_) => {}
1092
1093             // An `extern {}` doesn't introduce a new privacy
1094             // namespace (the contents have their own privacies).
1095             hir::ItemForeignMod(_) => {}
1096
1097             hir::ItemTrait(.., ref bounds, _) => {
1098                 if !self.trait_is_public(item.id) {
1099                     return
1100                 }
1101
1102                 for bound in bounds.iter() {
1103                     self.check_ty_param_bound(bound)
1104                 }
1105             }
1106
1107             // impls need some special handling to try to offer useful
1108             // error messages without (too many) false positives
1109             // (i.e. we could just return here to not check them at
1110             // all, or some worse estimation of whether an impl is
1111             // publicly visible).
1112             hir::ItemImpl(.., ref g, ref trait_ref, ref self_, ref impl_item_refs) => {
1113                 // `impl [... for] Private` is never visible.
1114                 let self_contains_private;
1115                 // impl [... for] Public<...>, but not `impl [... for]
1116                 // Vec<Public>` or `(Public,)` etc.
1117                 let self_is_public_path;
1118
1119                 // check the properties of the Self type:
1120                 {
1121                     let mut visitor = ObsoleteCheckTypeForPrivatenessVisitor {
1122                         inner: self,
1123                         contains_private: false,
1124                         at_outer_type: true,
1125                         outer_type_is_public_path: false,
1126                     };
1127                     visitor.visit_ty(&self_);
1128                     self_contains_private = visitor.contains_private;
1129                     self_is_public_path = visitor.outer_type_is_public_path;
1130                 }
1131
1132                 // miscellaneous info about the impl
1133
1134                 // `true` iff this is `impl Private for ...`.
1135                 let not_private_trait =
1136                     trait_ref.as_ref().map_or(true, // no trait counts as public trait
1137                                               |tr| {
1138                         let did = tr.path.def.def_id();
1139
1140                         if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
1141                             self.trait_is_public(node_id)
1142                         } else {
1143                             true // external traits must be public
1144                         }
1145                     });
1146
1147                 // `true` iff this is a trait impl or at least one method is public.
1148                 //
1149                 // `impl Public { $( fn ...() {} )* }` is not visible.
1150                 //
1151                 // This is required over just using the methods' privacy
1152                 // directly because we might have `impl<T: Foo<Private>> ...`,
1153                 // and we shouldn't warn about the generics if all the methods
1154                 // are private (because `T` won't be visible externally).
1155                 let trait_or_some_public_method =
1156                     trait_ref.is_some() ||
1157                     impl_item_refs.iter()
1158                                  .any(|impl_item_ref| {
1159                                      let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1160                                      match impl_item.node {
1161                                          hir::ImplItemKind::Const(..) |
1162                                          hir::ImplItemKind::Method(..) => {
1163                                              self.access_levels.is_reachable(impl_item.id)
1164                                          }
1165                                          hir::ImplItemKind::Type(_) => false,
1166                                      }
1167                                  });
1168
1169                 if !self_contains_private &&
1170                         not_private_trait &&
1171                         trait_or_some_public_method {
1172
1173                     intravisit::walk_generics(self, g);
1174
1175                     match *trait_ref {
1176                         None => {
1177                             for impl_item_ref in impl_item_refs {
1178                                 // This is where we choose whether to walk down
1179                                 // further into the impl to check its items. We
1180                                 // should only walk into public items so that we
1181                                 // don't erroneously report errors for private
1182                                 // types in private items.
1183                                 let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1184                                 match impl_item.node {
1185                                     hir::ImplItemKind::Const(..) |
1186                                     hir::ImplItemKind::Method(..)
1187                                         if self.item_is_public(&impl_item.id, &impl_item.vis) =>
1188                                     {
1189                                         intravisit::walk_impl_item(self, impl_item)
1190                                     }
1191                                     hir::ImplItemKind::Type(..) => {
1192                                         intravisit::walk_impl_item(self, impl_item)
1193                                     }
1194                                     _ => {}
1195                                 }
1196                             }
1197                         }
1198                         Some(ref tr) => {
1199                             // Any private types in a trait impl fall into three
1200                             // categories.
1201                             // 1. mentioned in the trait definition
1202                             // 2. mentioned in the type params/generics
1203                             // 3. mentioned in the associated types of the impl
1204                             //
1205                             // Those in 1. can only occur if the trait is in
1206                             // this crate and will've been warned about on the
1207                             // trait definition (there's no need to warn twice
1208                             // so we don't check the methods).
1209                             //
1210                             // Those in 2. are warned via walk_generics and this
1211                             // call here.
1212                             intravisit::walk_path(self, &tr.path);
1213
1214                             // Those in 3. are warned with this call.
1215                             for impl_item_ref in impl_item_refs {
1216                                 let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1217                                 if let hir::ImplItemKind::Type(ref ty) = impl_item.node {
1218                                     self.visit_ty(ty);
1219                                 }
1220                             }
1221                         }
1222                     }
1223                 } else if trait_ref.is_none() && self_is_public_path {
1224                     // impl Public<Private> { ... }. Any public static
1225                     // methods will be visible as `Public::foo`.
1226                     let mut found_pub_static = false;
1227                     for impl_item_ref in impl_item_refs {
1228                         if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
1229                             let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1230                             match impl_item_ref.kind {
1231                                 hir::AssociatedItemKind::Const => {
1232                                     found_pub_static = true;
1233                                     intravisit::walk_impl_item(self, impl_item);
1234                                 }
1235                                 hir::AssociatedItemKind::Method { has_self: false } => {
1236                                     found_pub_static = true;
1237                                     intravisit::walk_impl_item(self, impl_item);
1238                                 }
1239                                 _ => {}
1240                             }
1241                         }
1242                     }
1243                     if found_pub_static {
1244                         intravisit::walk_generics(self, g)
1245                     }
1246                 }
1247                 return
1248             }
1249
1250             // `type ... = ...;` can contain private types, because
1251             // we're introducing a new name.
1252             hir::ItemTy(..) => return,
1253
1254             // not at all public, so we don't care
1255             _ if !self.item_is_public(&item.id, &item.vis) => {
1256                 return;
1257             }
1258
1259             _ => {}
1260         }
1261
1262         // We've carefully constructed it so that if we're here, then
1263         // any `visit_ty`'s will be called on things that are in
1264         // public signatures, i.e. things that we're interested in for
1265         // this visitor.
1266         intravisit::walk_item(self, item);
1267     }
1268
1269     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
1270         generics.params.iter().for_each(|param| match param.kind {
1271             GenericParamKind::Lifetime { .. } => {}
1272             GenericParamKind::Type { .. } => {
1273                 for bound in &param.bounds {
1274                     self.check_ty_param_bound(bound);
1275                 }
1276             }
1277         });
1278         for predicate in &generics.where_clause.predicates {
1279             match predicate {
1280                 &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
1281                     for bound in bound_pred.bounds.iter() {
1282                         self.check_ty_param_bound(bound)
1283                     }
1284                 }
1285                 &hir::WherePredicate::RegionPredicate(_) => {}
1286                 &hir::WherePredicate::EqPredicate(ref eq_pred) => {
1287                     self.visit_ty(&eq_pred.rhs_ty);
1288                 }
1289             }
1290         }
1291     }
1292
1293     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
1294         if self.access_levels.is_reachable(item.id) {
1295             intravisit::walk_foreign_item(self, item)
1296         }
1297     }
1298
1299     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
1300         if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = t.node {
1301             if self.path_is_private_type(path) {
1302                 self.old_error_set.insert(t.id);
1303             }
1304         }
1305         intravisit::walk_ty(self, t)
1306     }
1307
1308     fn visit_variant(&mut self,
1309                      v: &'tcx hir::Variant,
1310                      g: &'tcx hir::Generics,
1311                      item_id: ast::NodeId) {
1312         if self.access_levels.is_reachable(v.node.data.id()) {
1313             self.in_variant = true;
1314             intravisit::walk_variant(self, v, g, item_id);
1315             self.in_variant = false;
1316         }
1317     }
1318
1319     fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
1320         if s.vis == hir::Public || self.in_variant {
1321             intravisit::walk_struct_field(self, s);
1322         }
1323     }
1324
1325     // we don't need to introspect into these at all: an
1326     // expression/block context can't possibly contain exported things.
1327     // (Making them no-ops stops us from traversing the whole AST without
1328     // having to be super careful about our `walk_...` calls above.)
1329     fn visit_block(&mut self, _: &'tcx hir::Block) {}
1330     fn visit_expr(&mut self, _: &'tcx hir::Expr) {}
1331 }
1332
1333 ///////////////////////////////////////////////////////////////////////////////
1334 /// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
1335 /// finds any private components in it.
1336 /// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
1337 /// and traits in public interfaces.
1338 ///////////////////////////////////////////////////////////////////////////////
1339
1340 struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
1341     tcx: TyCtxt<'a, 'tcx, 'tcx>,
1342     item_def_id: DefId,
1343     span: Span,
1344     /// The visitor checks that each component type is at least this visible
1345     required_visibility: ty::Visibility,
1346     /// The visibility of the least visible component that has been visited
1347     min_visibility: ty::Visibility,
1348     has_pub_restricted: bool,
1349     has_old_errors: bool,
1350     in_assoc_ty: bool,
1351 }
1352
1353 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
1354     fn generics(&mut self) -> &mut Self {
1355         for param in &self.tcx.generics_of(self.item_def_id).params {
1356             match param.kind {
1357                 GenericParamDefKind::Type { has_default, .. } => {
1358                     if has_default {
1359                         self.tcx.type_of(param.def_id).visit_with(self);
1360                     }
1361                 }
1362                 GenericParamDefKind::Lifetime => {}
1363             }
1364         }
1365         self
1366     }
1367
1368     fn predicates(&mut self) -> &mut Self {
1369         let predicates = self.tcx.predicates_of(self.item_def_id);
1370         for predicate in &predicates.predicates {
1371             predicate.visit_with(self);
1372             match predicate {
1373                 &ty::Predicate::Trait(poly_predicate) => {
1374                     self.check_trait_ref(poly_predicate.skip_binder().trait_ref);
1375                 },
1376                 &ty::Predicate::Projection(poly_predicate) => {
1377                     let tcx = self.tcx;
1378                     self.check_trait_ref(
1379                         poly_predicate.skip_binder().projection_ty.trait_ref(tcx)
1380                     );
1381                 },
1382                 _ => (),
1383             };
1384         }
1385         self
1386     }
1387
1388     fn ty(&mut self) -> &mut Self {
1389         let ty = self.tcx.type_of(self.item_def_id);
1390         ty.visit_with(self);
1391         if let ty::TyFnDef(def_id, _) = ty.sty {
1392             if def_id == self.item_def_id {
1393                 self.tcx.fn_sig(def_id).visit_with(self);
1394             }
1395         }
1396         self
1397     }
1398
1399     fn impl_trait_ref(&mut self) -> &mut Self {
1400         if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) {
1401             self.check_trait_ref(impl_trait_ref);
1402             impl_trait_ref.super_visit_with(self);
1403         }
1404         self
1405     }
1406
1407     fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
1408         // Non-local means public (private items can't leave their crate, modulo bugs)
1409         if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) {
1410             let item = self.tcx.hir.expect_item(node_id);
1411             let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
1412             if !vis.is_at_least(self.min_visibility, self.tcx) {
1413                 self.min_visibility = vis;
1414             }
1415             if !vis.is_at_least(self.required_visibility, self.tcx) {
1416                 if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
1417                     struct_span_err!(self.tcx.sess, self.span, E0445,
1418                                      "private trait `{}` in public interface", trait_ref)
1419                         .span_label(self.span, format!(
1420                                     "can't leak private trait"))
1421                         .emit();
1422                 } else {
1423                     self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC,
1424                                        node_id,
1425                                        self.span,
1426                                        &format!("private trait `{}` in public \
1427                                                  interface (error E0445)", trait_ref));
1428                 }
1429             }
1430         }
1431     }
1432 }
1433
1434 impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
1435     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
1436         let ty_def_id = match ty.sty {
1437             ty::TyAdt(adt, _) => Some(adt.did),
1438             ty::TyForeign(did) => Some(did),
1439             ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
1440             ty::TyProjection(ref proj) => {
1441                 if self.required_visibility == ty::Visibility::Invisible {
1442                     // Conservatively approximate the whole type alias as public without
1443                     // recursing into its components when determining impl publicity.
1444                     // For example, `impl <Type as Trait>::Alias {...}` may be a public impl
1445                     // even if both `Type` and `Trait` are private.
1446                     // Ideally, associated types should be substituted in the same way as
1447                     // free type aliases, but this isn't done yet.
1448                     return false;
1449                 }
1450                 let trait_ref = proj.trait_ref(self.tcx);
1451                 Some(trait_ref.def_id)
1452             }
1453             _ => None
1454         };
1455
1456         if let Some(def_id) = ty_def_id {
1457             // Non-local means public (private items can't leave their crate, modulo bugs)
1458             if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
1459                 let vis = match self.tcx.hir.find(node_id) {
1460                     Some(hir::map::NodeItem(item)) => &item.vis,
1461                     Some(hir::map::NodeForeignItem(item)) => &item.vis,
1462                     _ => bug!("expected item of foreign item"),
1463                 };
1464
1465                 let vis = ty::Visibility::from_hir(vis, node_id, self.tcx);
1466
1467                 if !vis.is_at_least(self.min_visibility, self.tcx) {
1468                     self.min_visibility = vis;
1469                 }
1470                 if !vis.is_at_least(self.required_visibility, self.tcx) {
1471                     if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
1472                         let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
1473                             "private type `{}` in public interface", ty);
1474                         err.span_label(self.span, "can't leak private type");
1475                         err.emit();
1476                     } else {
1477                         self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC,
1478                                            node_id,
1479                                            self.span,
1480                                            &format!("private type `{}` in public \
1481                                                      interface (error E0446)", ty));
1482                     }
1483                 }
1484             }
1485         }
1486
1487         ty.super_visit_with(self)
1488     }
1489 }
1490
1491 struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
1492     tcx: TyCtxt<'a, 'tcx, 'tcx>,
1493     has_pub_restricted: bool,
1494     old_error_set: &'a NodeSet,
1495     inner_visibility: ty::Visibility,
1496 }
1497
1498 impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1499     fn check(&self, item_id: ast::NodeId, required_visibility: ty::Visibility)
1500              -> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
1501         let mut has_old_errors = false;
1502
1503         // Slow path taken only if there any errors in the crate.
1504         for &id in self.old_error_set {
1505             // Walk up the nodes until we find `item_id` (or we hit a root).
1506             let mut id = id;
1507             loop {
1508                 if id == item_id {
1509                     has_old_errors = true;
1510                     break;
1511                 }
1512                 let parent = self.tcx.hir.get_parent_node(id);
1513                 if parent == id {
1514                     break;
1515                 }
1516                 id = parent;
1517             }
1518
1519             if has_old_errors {
1520                 break;
1521             }
1522         }
1523
1524         SearchInterfaceForPrivateItemsVisitor {
1525             tcx: self.tcx,
1526             item_def_id: self.tcx.hir.local_def_id(item_id),
1527             span: self.tcx.hir.span(item_id),
1528             min_visibility: ty::Visibility::Public,
1529             required_visibility,
1530             has_pub_restricted: self.has_pub_restricted,
1531             has_old_errors,
1532             in_assoc_ty: false,
1533         }
1534     }
1535 }
1536
1537 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1538     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1539         NestedVisitorMap::OnlyBodies(&self.tcx.hir)
1540     }
1541
1542     fn visit_item(&mut self, item: &'tcx hir::Item) {
1543         let tcx = self.tcx;
1544         let min = |vis1: ty::Visibility, vis2| {
1545             if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
1546         };
1547
1548         let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx);
1549
1550         match item.node {
1551             // Crates are always public
1552             hir::ItemExternCrate(..) => {}
1553             // All nested items are checked by visit_item
1554             hir::ItemMod(..) => {}
1555             // Checked in resolve
1556             hir::ItemUse(..) => {}
1557             // No subitems
1558             hir::ItemGlobalAsm(..) => {}
1559             // Checked in visit_ty
1560             hir::ItemExistential(..) => {}
1561             // Subitems of these items have inherited publicity
1562             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
1563             hir::ItemTy(..) => {
1564                 self.check(item.id, item_visibility).generics().predicates().ty();
1565
1566                 // Recurse for e.g. `impl Trait` (see `visit_ty`).
1567                 self.inner_visibility = item_visibility;
1568                 intravisit::walk_item(self, item);
1569             }
1570             hir::ItemTrait(.., ref trait_item_refs) => {
1571                 self.check(item.id, item_visibility).generics().predicates();
1572
1573                 for trait_item_ref in trait_item_refs {
1574                     let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
1575                     check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
1576                     check.generics().predicates();
1577
1578                     if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
1579                        !trait_item_ref.defaultness.has_value() {
1580                         // No type to visit.
1581                     } else {
1582                         check.ty();
1583                     }
1584                 }
1585             }
1586             hir::ItemTraitAlias(..) => {
1587                 self.check(item.id, item_visibility).generics().predicates();
1588             }
1589             hir::ItemEnum(ref def, _) => {
1590                 self.check(item.id, item_visibility).generics().predicates();
1591
1592                 for variant in &def.variants {
1593                     for field in variant.node.data.fields() {
1594                         self.check(field.id, item_visibility).ty();
1595                     }
1596                 }
1597             }
1598             // Subitems of foreign modules have their own publicity
1599             hir::ItemForeignMod(ref foreign_mod) => {
1600                 for foreign_item in &foreign_mod.items {
1601                     let vis = ty::Visibility::from_hir(&foreign_item.vis, item.id, tcx);
1602                     self.check(foreign_item.id, vis).generics().predicates().ty();
1603                 }
1604             }
1605             // Subitems of structs and unions have their own publicity
1606             hir::ItemStruct(ref struct_def, _) |
1607             hir::ItemUnion(ref struct_def, _) => {
1608                 self.check(item.id, item_visibility).generics().predicates();
1609
1610                 for field in struct_def.fields() {
1611                     let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx);
1612                     self.check(field.id, min(item_visibility, field_visibility)).ty();
1613                 }
1614             }
1615             // An inherent impl is public when its type is public
1616             // Subitems of inherent impls have their own publicity
1617             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
1618                 let ty_vis =
1619                     self.check(item.id, ty::Visibility::Invisible).ty().min_visibility;
1620                 self.check(item.id, ty_vis).generics().predicates();
1621
1622                 for impl_item_ref in impl_item_refs {
1623                     let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1624                     let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx);
1625                     let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis));
1626                     check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
1627                     check.generics().predicates().ty();
1628
1629                     // Recurse for e.g. `impl Trait` (see `visit_ty`).
1630                     self.inner_visibility = impl_item_vis;
1631                     intravisit::walk_impl_item(self, impl_item);
1632                 }
1633             }
1634             // A trait impl is public when both its type and its trait are public
1635             // Subitems of trait impls have inherited publicity
1636             hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
1637                 let vis = self.check(item.id, ty::Visibility::Invisible)
1638                               .ty().impl_trait_ref().min_visibility;
1639                 self.check(item.id, vis).generics().predicates();
1640                 for impl_item_ref in impl_item_refs {
1641                     let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1642                     let mut check = self.check(impl_item.id, vis);
1643                     check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
1644                     check.generics().predicates().ty();
1645
1646                     // Recurse for e.g. `impl Trait` (see `visit_ty`).
1647                     self.inner_visibility = vis;
1648                     intravisit::walk_impl_item(self, impl_item);
1649                 }
1650             }
1651         }
1652     }
1653
1654     fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {
1655         // handled in `visit_item` above
1656     }
1657
1658     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
1659         if let hir::TyImplTraitExistential(ref exist_item, _, _) = ty.node {
1660             // Check the traits being exposed, as they're separate,
1661             // e.g. `impl Iterator<Item=T>` has two predicates,
1662             // `X: Iterator` and `<X as Iterator>::Item == T`,
1663             // where `X` is the `impl Iterator<Item=T>` itself,
1664             // stored in `predicates_of`, not in the `Ty` itself.
1665
1666             self.check(exist_item.id, self.inner_visibility).predicates();
1667         }
1668
1669         intravisit::walk_ty(self, ty);
1670     }
1671
1672     // Don't recurse into expressions in array sizes or const initializers
1673     fn visit_expr(&mut self, _: &'tcx hir::Expr) {}
1674     // Don't recurse into patterns in function arguments
1675     fn visit_pat(&mut self, _: &'tcx hir::Pat) {}
1676 }
1677
1678 pub fn provide(providers: &mut Providers) {
1679     *providers = Providers {
1680         privacy_access_levels,
1681         ..*providers
1682     };
1683 }
1684
1685 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Lrc<AccessLevels> {
1686     tcx.privacy_access_levels(LOCAL_CRATE)
1687 }
1688
1689 fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1690                                    krate: CrateNum)
1691                                    -> Lrc<AccessLevels> {
1692     assert_eq!(krate, LOCAL_CRATE);
1693
1694     let krate = tcx.hir.krate();
1695     let empty_tables = ty::TypeckTables::empty(None);
1696
1697     // Check privacy of names not checked in previous compilation stages.
1698     let mut visitor = NamePrivacyVisitor {
1699         tcx,
1700         tables: &empty_tables,
1701         current_item: CRATE_NODE_ID,
1702         empty_tables: &empty_tables,
1703     };
1704     intravisit::walk_crate(&mut visitor, krate);
1705
1706     // Check privacy of explicitly written types and traits as well as
1707     // inferred types of expressions and patterns.
1708     let mut visitor = TypePrivacyVisitor {
1709         tcx,
1710         tables: &empty_tables,
1711         current_item: DefId::local(CRATE_DEF_INDEX),
1712         in_body: false,
1713         span: krate.span,
1714         empty_tables: &empty_tables,
1715         visited_anon_tys: FxHashSet()
1716     };
1717     intravisit::walk_crate(&mut visitor, krate);
1718
1719     // Build up a set of all exported items in the AST. This is a set of all
1720     // items which are reachable from external crates based on visibility.
1721     let mut visitor = EmbargoVisitor {
1722         tcx,
1723         access_levels: Default::default(),
1724         prev_level: Some(AccessLevel::Public),
1725         changed: false,
1726     };
1727     loop {
1728         intravisit::walk_crate(&mut visitor, krate);
1729         if visitor.changed {
1730             visitor.changed = false;
1731         } else {
1732             break
1733         }
1734     }
1735     visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public));
1736
1737     {
1738         let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
1739             tcx,
1740             access_levels: &visitor.access_levels,
1741             in_variant: false,
1742             old_error_set: NodeSet(),
1743         };
1744         intravisit::walk_crate(&mut visitor, krate);
1745
1746
1747         let has_pub_restricted = {
1748             let mut pub_restricted_visitor = PubRestrictedVisitor {
1749                 tcx,
1750                 has_pub_restricted: false
1751             };
1752             intravisit::walk_crate(&mut pub_restricted_visitor, krate);
1753             pub_restricted_visitor.has_pub_restricted
1754         };
1755
1756         // Check for private types and traits in public interfaces
1757         let mut visitor = PrivateItemsInPublicInterfacesVisitor {
1758             tcx,
1759             has_pub_restricted,
1760             old_error_set: &visitor.old_error_set,
1761             inner_visibility: ty::Visibility::Public,
1762         };
1763         krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
1764     }
1765
1766     Lrc::new(visitor.access_levels)
1767 }
1768
1769 __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }