@@ -934,6 +934,15 @@ impl<'a> ModuleS<'a> {
934
934
}
935
935
}
936
936
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
+
937
946
pub fn inc_glob_count ( & self ) {
938
947
self . glob_count . set ( self . glob_count . get ( ) + 1 ) ;
939
948
}
@@ -1000,9 +1009,14 @@ enum NameBindingKind<'a> {
1000
1009
Import {
1001
1010
binding : & ' a NameBinding < ' a > ,
1002
1011
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 > > > ,
1003
1014
} ,
1004
1015
}
1005
1016
1017
+ #[ derive( Clone , Debug ) ]
1018
+ struct PrivacyError < ' a > ( Span , Name , & ' a NameBinding < ' a > ) ;
1019
+
1006
1020
impl < ' a > NameBinding < ' a > {
1007
1021
fn create_from_module ( module : Module < ' a > , span : Option < Span > ) -> Self {
1008
1022
let modifiers = if module. is_public {
@@ -1145,6 +1159,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
1145
1159
// The intention is that the callback modifies this flag.
1146
1160
// Once set, the resolver falls out of the walk, preserving the ribs.
1147
1161
resolved : bool ,
1162
+ privacy_errors : Vec < PrivacyError < ' a > > ,
1148
1163
1149
1164
arenas : & ' a ResolverArenas < ' a > ,
1150
1165
}
@@ -1209,6 +1224,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1209
1224
1210
1225
callback : None ,
1211
1226
resolved : false ,
1227
+ privacy_errors : Vec :: new ( ) ,
1212
1228
1213
1229
arenas : arenas,
1214
1230
}
@@ -1255,12 +1271,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1255
1271
self . used_crates . insert ( krate) ;
1256
1272
}
1257
1273
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 ) ,
1260
1276
_ => return ,
1261
1277
} ;
1262
1278
1263
1279
self . used_imports . insert ( ( import_id, ns) ) ;
1280
+ if let Some ( error) = privacy_error. as_ref ( ) {
1281
+ self . privacy_errors . push ( ( * * error) . clone ( ) ) ;
1282
+ }
1264
1283
1265
1284
if !self . make_glob_map {
1266
1285
return ;
@@ -1352,6 +1371,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
1352
1371
// Check to see whether there are type bindings, and, if
1353
1372
// so, whether there is a module within.
1354
1373
if let Some ( module_def) = binding. module ( ) {
1374
+ self . check_privacy ( search_module, name, binding, span) ;
1355
1375
search_module = module_def;
1356
1376
} else {
1357
1377
let msg = format ! ( "Not a module `{}`" , name) ;
@@ -2911,7 +2931,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2911
2931
2912
2932
let name = segments. last ( ) . unwrap ( ) . identifier . name ;
2913
2933
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
+ } )
2915
2938
}
2916
2939
2917
2940
/// Invariant: This must be called only during main resolution, not during
@@ -2958,7 +2981,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
2958
2981
2959
2982
let name = segments. last ( ) . unwrap ( ) . identifier . name ;
2960
2983
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
+ } )
2962
2988
}
2963
2989
2964
2990
fn resolve_identifier_in_local_ribs ( & mut self ,
@@ -3570,6 +3596,37 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
3570
3596
}
3571
3597
}
3572
3598
}
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
+ }
3573
3630
}
3574
3631
3575
3632
@@ -3726,6 +3783,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
3726
3783
resolver. resolve_crate ( krate) ;
3727
3784
3728
3785
check_unused:: check_crate ( & mut resolver, krate) ;
3786
+ resolver. report_privacy_errors ( ) ;
3729
3787
3730
3788
CrateMap {
3731
3789
def_map : resolver. def_map ,
0 commit comments