@@ -934,6 +934,15 @@ impl<'a> ModuleS<'a> {
934934 }
935935 }
936936
937+ fn is_ancestor_of ( & self , module : Module < ' a > ) -> bool {
938+ if self . def_id ( ) == module. def_id ( ) { return true }
939+ match module. parent_link {
940+ ParentLink :: BlockParentLink ( parent, _) |
941+ ParentLink :: ModuleParentLink ( parent, _) => self . is_ancestor_of ( parent) ,
942+ _ => false ,
943+ }
944+ }
945+
937946 pub fn inc_glob_count ( & self ) {
938947 self . glob_count . set ( self . glob_count . get ( ) + 1 ) ;
939948 }
@@ -1000,9 +1009,14 @@ enum NameBindingKind<'a> {
10001009 Import {
10011010 binding : & ' a NameBinding < ' a > ,
10021011 id : NodeId ,
1012+ // Some(error) if using this imported name causes the import to be a privacy error
1013+ privacy_error : Option < Box < PrivacyError < ' a > > > ,
10031014 } ,
10041015}
10051016
1017+ #[ derive( Clone , Debug ) ]
1018+ struct PrivacyError < ' a > ( Span , Name , & ' a NameBinding < ' a > ) ;
1019+
10061020impl < ' a > NameBinding < ' a > {
10071021 fn create_from_module ( module : Module < ' a > , span : Option < Span > ) -> Self {
10081022 let modifiers = if module. is_public {
@@ -1145,6 +1159,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
11451159 // The intention is that the callback modifies this flag.
11461160 // Once set, the resolver falls out of the walk, preserving the ribs.
11471161 resolved : bool ,
1162+ privacy_errors : Vec < PrivacyError < ' a > > ,
11481163
11491164 arenas : & ' a ResolverArenas < ' a > ,
11501165}
@@ -1209,6 +1224,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12091224
12101225 callback : None ,
12111226 resolved : false ,
1227+ privacy_errors : Vec :: new ( ) ,
12121228
12131229 arenas : arenas,
12141230 }
@@ -1255,12 +1271,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12551271 self . used_crates . insert ( krate) ;
12561272 }
12571273
1258- let import_id = match binding. kind {
1259- NameBindingKind :: Import { id, .. } => id ,
1274+ let ( import_id, privacy_error ) = match binding. kind {
1275+ NameBindingKind :: Import { id, ref privacy_error , .. } => ( id , privacy_error ) ,
12601276 _ => return ,
12611277 } ;
12621278
12631279 self . used_imports . insert ( ( import_id, ns) ) ;
1280+ if let Some ( error) = privacy_error. as_ref ( ) {
1281+ self . privacy_errors . push ( ( * * error) . clone ( ) ) ;
1282+ }
12641283
12651284 if !self . make_glob_map {
12661285 return ;
@@ -1352,6 +1371,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13521371 // Check to see whether there are type bindings, and, if
13531372 // so, whether there is a module within.
13541373 if let Some ( module_def) = binding. module ( ) {
1374+ self . check_privacy ( search_module, name, binding, span) ;
13551375 search_module = module_def;
13561376 } else {
13571377 let msg = format ! ( "Not a module `{}`" , name) ;
@@ -2911,7 +2931,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29112931
29122932 let name = segments. last ( ) . unwrap ( ) . identifier . name ;
29132933 let result = self . resolve_name_in_module ( containing_module, name, namespace, false , true ) ;
2914- result. success ( ) . map ( |binding| binding. def ( ) . unwrap ( ) )
2934+ result. success ( ) . map ( |binding| {
2935+ self . check_privacy ( containing_module, name, binding, span) ;
2936+ binding. def ( ) . unwrap ( )
2937+ } )
29152938 }
29162939
29172940 /// Invariant: This must be called only during main resolution, not during
@@ -2958,7 +2981,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29582981
29592982 let name = segments. last ( ) . unwrap ( ) . identifier . name ;
29602983 let result = self . resolve_name_in_module ( containing_module, name, namespace, false , true ) ;
2961- result. success ( ) . map ( |binding| binding. def ( ) . unwrap ( ) )
2984+ result. success ( ) . map ( |binding| {
2985+ self . check_privacy ( containing_module, name, binding, span) ;
2986+ binding. def ( ) . unwrap ( )
2987+ } )
29622988 }
29632989
29642990 fn resolve_identifier_in_local_ribs ( & mut self ,
@@ -3570,6 +3596,37 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
35703596 }
35713597 }
35723598 }
3599+
3600+ fn is_visible ( & self , binding : & ' a NameBinding < ' a > , parent : Module < ' a > ) -> bool {
3601+ binding. is_public ( ) || parent. is_ancestor_of ( self . current_module )
3602+ }
3603+
3604+ fn check_privacy ( & mut self ,
3605+ module : Module < ' a > ,
3606+ name : Name ,
3607+ binding : & ' a NameBinding < ' a > ,
3608+ span : Span ) {
3609+ if !self . is_visible ( binding, module) {
3610+ self . privacy_errors . push ( PrivacyError ( span, name, binding) ) ;
3611+ }
3612+ }
3613+
3614+ fn report_privacy_errors ( & self ) {
3615+ if self . privacy_errors . len ( ) == 0 { return }
3616+ let mut reported_spans = HashSet :: new ( ) ;
3617+ for & PrivacyError ( span, name, binding) in & self . privacy_errors {
3618+ if !reported_spans. insert ( span) { continue }
3619+ if binding. is_extern_crate ( ) {
3620+ // Warn when using an inaccessible extern crate.
3621+ let node_id = binding. module ( ) . unwrap ( ) . extern_crate_id . unwrap ( ) ;
3622+ let msg = format ! ( "extern crate `{}` is private" , name) ;
3623+ self . session . add_lint ( lint:: builtin:: INACCESSIBLE_EXTERN_CRATE , node_id, span, msg) ;
3624+ } else {
3625+ let def = binding. def ( ) . unwrap ( ) ;
3626+ self . session . span_err ( span, & format ! ( "{} `{}` is private" , def. kind_name( ) , name) ) ;
3627+ }
3628+ }
3629+ }
35733630}
35743631
35753632
@@ -3726,6 +3783,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
37263783 resolver. resolve_crate ( krate) ;
37273784
37283785 check_unused:: check_crate ( & mut resolver, krate) ;
3786+ resolver. report_privacy_errors ( ) ;
37293787
37303788 CrateMap {
37313789 def_map : resolver. def_map ,
0 commit comments