@@ -46,9 +46,10 @@ use rustc_index::vec::IndexVec;
4646use rustc_metadata:: creader:: { CStore , CrateLoader } ;
4747use rustc_middle:: hir:: exports:: ExportMap ;
4848use rustc_middle:: middle:: cstore:: { CrateStore , MetadataLoaderDyn } ;
49+ use rustc_middle:: middle:: privacy:: AccessLevel ;
4950use rustc_middle:: span_bug;
5051use rustc_middle:: ty:: query:: Providers ;
51- use rustc_middle:: ty:: { self , DefIdTree , MainDefinition , ResolverOutputs } ;
52+ use rustc_middle:: ty:: { self , DefIdTree , MainDefinition , ResolverOutputs , Visibility } ;
5253use rustc_session:: lint;
5354use rustc_session:: lint:: { BuiltinLintDiagnostics , LintBuffer } ;
5455use rustc_session:: Session ;
@@ -1032,6 +1033,8 @@ pub struct Resolver<'a> {
10321033 legacy_const_generic_args : FxHashMap < DefId , Option < Vec < usize > > > ,
10331034
10341035 main_def : Option < MainDefinition > ,
1036+
1037+ nodes_access_level : FxHashMap < LocalDefId , AccessLevel > ,
10351038}
10361039
10371040/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1393,6 +1396,8 @@ impl<'a> Resolver<'a> {
13931396 trait_impl_items : Default :: default ( ) ,
13941397 legacy_const_generic_args : Default :: default ( ) ,
13951398 main_def : Default :: default ( ) ,
1399+
1400+ nodes_access_level : Default :: default ( ) ,
13961401 } ;
13971402
13981403 let root_parent_scope = ParentScope :: module ( graph_root, & resolver) ;
@@ -1435,10 +1440,12 @@ impl<'a> Resolver<'a> {
14351440 let maybe_unused_extern_crates = self . maybe_unused_extern_crates ;
14361441 let glob_map = self . glob_map ;
14371442 let main_def = self . main_def ;
1443+ let access_levels = self . nodes_access_level ;
14381444 ResolverOutputs {
14391445 definitions,
14401446 cstore : Box :: new ( self . crate_loader . into_cstore ( ) ) ,
14411447 visibilities,
1448+ access_levels,
14421449 extern_crate_map,
14431450 export_map,
14441451 glob_map,
@@ -1456,6 +1463,7 @@ impl<'a> Resolver<'a> {
14561463 pub fn clone_outputs ( & self ) -> ResolverOutputs {
14571464 ResolverOutputs {
14581465 definitions : self . definitions . clone ( ) ,
1466+ access_levels : self . nodes_access_level . clone ( ) ,
14591467 cstore : Box :: new ( self . cstore ( ) . clone ( ) ) ,
14601468 visibilities : self . visibilities . clone ( ) ,
14611469 extern_crate_map : self . extern_crate_map . clone ( ) ,
@@ -1512,6 +1520,7 @@ impl<'a> Resolver<'a> {
15121520 pub fn resolve_crate ( & mut self , krate : & Crate ) {
15131521 self . session . time ( "resolve_crate" , || {
15141522 self . session . time ( "finalize_imports" , || ImportResolver { r : self } . finalize_imports ( ) ) ;
1523+ self . session . time ( "resolve_export_privacy" , || self . resolve_export_privacy ( ) ) ;
15151524 self . session . time ( "finalize_macro_resolutions" , || self . finalize_macro_resolutions ( ) ) ;
15161525 self . session . time ( "late_resolve_crate" , || self . late_resolve_crate ( krate) ) ;
15171526 self . session . time ( "resolve_main" , || self . resolve_main ( ) ) ;
@@ -1521,6 +1530,58 @@ impl<'a> Resolver<'a> {
15211530 } ) ;
15221531 }
15231532
1533+ /// Compute access levels for exports and intermediate use statements
1534+ fn resolve_export_privacy ( & mut self ) {
1535+ let root = self . graph_root ( ) ;
1536+ let exports = root. def_id ( ) . and_then ( |id| self . export_map . get ( & id. expect_local ( ) ) ) ;
1537+
1538+ if let Some ( exports) = exports. cloned ( ) {
1539+ let public_exports =
1540+ exports. iter ( ) . filter ( |ex| ex. vis == Visibility :: Public ) . collect :: < Vec < _ > > ( ) ;
1541+
1542+ for export in public_exports {
1543+ if let Some ( ns) = export. res . ns ( ) {
1544+ let key = self . new_key ( export. ident , ns) ;
1545+ let name_res = self . resolution ( root, key) ;
1546+ if let Some ( binding) = name_res. borrow ( ) . binding ( ) {
1547+ self . compute_binding_access_level ( binding) ;
1548+ }
1549+ }
1550+ }
1551+ }
1552+
1553+ tracing:: debug!( "nodes_access_level: {:?}" , self . nodes_access_level) ;
1554+ }
1555+
1556+ /// Set the given binding access level to `AccessLevel::Public` and
1557+ /// sets the rest of the `use` chain to `AccessLevel::Exported` until
1558+ /// we hit the actual exported item
1559+ fn compute_binding_access_level ( & mut self , mut binding : & NameBinding < ' a > ) {
1560+ let mut access_level = AccessLevel :: Public ;
1561+ while let NameBindingKind :: Import { binding : nested_binding, import, .. } = binding. kind {
1562+ self . mark_node_with_access_level ( import. id , access_level) ;
1563+
1564+ match import. kind {
1565+ ImportKind :: Single { additional_ids, .. } => {
1566+ self . mark_node_with_access_level ( additional_ids. 0 , access_level) ;
1567+ self . mark_node_with_access_level ( additional_ids. 1 , access_level) ;
1568+ }
1569+ _ => { }
1570+ } ;
1571+
1572+ access_level = AccessLevel :: Exported ;
1573+ binding = nested_binding;
1574+ }
1575+ }
1576+
1577+ fn mark_node_with_access_level ( & mut self , node_id : NodeId , access_level : AccessLevel ) -> bool {
1578+ if let Some ( def_id) = self . opt_local_def_id ( node_id) {
1579+ self . nodes_access_level . insert ( def_id, access_level) . is_none ( )
1580+ } else {
1581+ false
1582+ }
1583+ }
1584+
15241585 pub fn traits_in_scope (
15251586 & mut self ,
15261587 current_trait : Option < Module < ' a > > ,
0 commit comments