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