Skip to content

Commit bc89ee9

Browse files
committed
Mak DefId to AccessLevel map in resolve for export
hir_id to accesslevel in resolve and applied in privacy using local def id removing tracing probes making function not recursive and adding comments
1 parent 49ca3d9 commit bc89ee9

File tree

6 files changed

+80
-59
lines changed

6 files changed

+80
-59
lines changed

compiler/rustc_middle/src/ty/context.rs

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
88
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
99
use crate::middle;
1010
use crate::middle::cstore::EncodedMetadata;
11+
use crate::middle::privacy::AccessLevel;
1112
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
1213
use crate::middle::stability;
1314
use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
@@ -1160,6 +1161,10 @@ impl<'tcx> TyCtxt<'tcx> {
11601161
)
11611162
}
11621163

1164+
pub fn get_resolver_access_level(self, local_def_id: LocalDefId) -> Option<AccessLevel> {
1165+
self.gcx.untracked_resolutions.access_levels.get(&local_def_id).copied()
1166+
}
1167+
11631168
pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
11641169
value.lift_to_tcx(self)
11651170
}

compiler/rustc_middle/src/ty/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub use vtable::*;
2323
use crate::hir::exports::ExportMap;
2424
use crate::ich::StableHashingContext;
2525
use crate::middle::cstore::CrateStoreDyn;
26+
use crate::middle::privacy::AccessLevel;
2627
use crate::mir::{Body, GeneratorLayout};
2728
use crate::traits::{self, Reveal};
2829
use crate::ty;
@@ -118,6 +119,7 @@ pub struct ResolverOutputs {
118119
pub definitions: rustc_hir::definitions::Definitions,
119120
pub cstore: Box<CrateStoreDyn>,
120121
pub visibilities: FxHashMap<LocalDefId, Visibility>,
122+
pub access_levels: FxHashMap<LocalDefId, AccessLevel>,
121123
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
122124
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
123125
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,

compiler/rustc_privacy/src/lib.rs

+5-54
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashSet;
1111
use rustc_errors::struct_span_err;
1212
use rustc_hir as hir;
1313
use rustc_hir::def::{DefKind, Res};
14-
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
14+
use rustc_hir::def_id::{DefId, LocalDefId};
1515
use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
1616
use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
1717
use rustc_middle::bug;
@@ -574,56 +574,6 @@ impl EmbargoVisitor<'tcx> {
574574
| DefKind::Generator => (),
575575
}
576576
}
577-
578-
/// Given the path segments of a `ItemKind::Use`, then we need
579-
/// to update the visibility of the intermediate use so that it isn't linted
580-
/// by `unreachable_pub`.
581-
///
582-
/// This isn't trivial as `path.res` has the `DefId` of the eventual target
583-
/// of the use statement not of the next intermediate use statement.
584-
///
585-
/// To do this, consider the last two segments of the path to our intermediate
586-
/// use statement. We expect the penultimate segment to be a module and the
587-
/// last segment to be the name of the item we are exporting. We can then
588-
/// look at the items contained in the module for the use statement with that
589-
/// name and update that item's visibility.
590-
///
591-
/// FIXME: This solution won't work with glob imports and doesn't respect
592-
/// namespaces. See <https://github.com/rust-lang/rust/pull/57922#discussion_r251234202>.
593-
fn update_visibility_of_intermediate_use_statements(
594-
&mut self,
595-
segments: &[hir::PathSegment<'_>],
596-
) {
597-
if let [.., module, segment] = segments {
598-
if let Some(item) = module
599-
.res
600-
.and_then(|res| res.mod_def_id())
601-
// If the module is `self`, i.e. the current crate,
602-
// there will be no corresponding item.
603-
.filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
604-
.and_then(|def_id| {
605-
def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
606-
})
607-
.map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
608-
{
609-
if let hir::ItemKind::Mod(m) = &item.kind {
610-
for &item_id in m.item_ids {
611-
let item = self.tcx.hir().item(item_id);
612-
if !self.tcx.hygienic_eq(
613-
segment.ident,
614-
item.ident,
615-
item_id.def_id.to_def_id(),
616-
) {
617-
continue;
618-
}
619-
if let hir::ItemKind::Use(..) = item.kind {
620-
self.update(item.def_id, Some(AccessLevel::Exported));
621-
}
622-
}
623-
}
624-
}
625-
}
626-
}
627577
}
628578

629579
impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
@@ -732,9 +682,10 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
732682
// Re-exports are handled in `visit_mod`. However, in order to avoid looping over
733683
// all of the items of a mod in `visit_mod` looking for use statements, we handle
734684
// making sure that intermediate use statements have their visibilities updated here.
735-
hir::ItemKind::Use(ref path, _) => {
736-
if item_level.is_some() {
737-
self.update_visibility_of_intermediate_use_statements(path.segments.as_ref());
685+
hir::ItemKind::Use(..) => {
686+
if item.vis.node.is_pub() {
687+
let access_level = self.tcx.get_resolver_access_level(item.def_id);
688+
self.update(item.hir_id(), access_level);
738689
}
739690
}
740691
// The interface is empty.

compiler/rustc_resolve/src/build_reduced_graph.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
397397
used: Cell::new(false),
398398
});
399399

400-
debug!("add_import({:?})", import);
401-
402400
self.r.indeterminate_imports.push(import);
403401
match import.kind {
404402
// Don't add unresolved underscore imports to modules
@@ -469,7 +467,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
469467
prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot
470468
};
471469
match use_tree.kind {
472-
ast::UseTreeKind::Simple(rename, ..) => {
470+
ast::UseTreeKind::Simple(rename, id1, id2) => {
473471
let mut ident = use_tree.ident();
474472
let mut module_path = prefix;
475473
let mut source = module_path.pop().unwrap();
@@ -579,7 +577,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
579577
},
580578
type_ns_only,
581579
nested,
580+
additional_ids: (id1, id2),
582581
};
582+
583583
self.add_import(
584584
module_path,
585585
kind,

compiler/rustc_resolve/src/imports.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ pub enum ImportKind<'a> {
5050
type_ns_only: bool,
5151
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
5252
nested: bool,
53+
/// Additional `NodeId`s allocated to a `ast::UseTree` for automatically generated `use` statement
54+
/// (eg. implicit struct constructors)
55+
additional_ids: (NodeId, NodeId),
5356
},
5457
Glob {
5558
is_prelude: bool,
@@ -836,7 +839,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
836839
import.span,
837840
);
838841
import.vis.set(orig_vis);
839-
840842
source_bindings[ns].set(binding);
841843
} else {
842844
return;

compiler/rustc_resolve/src/lib.rs

+62-1
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ use rustc_index::vec::IndexVec;
4646
use rustc_metadata::creader::{CStore, CrateLoader};
4747
use rustc_middle::hir::exports::ExportMap;
4848
use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn};
49+
use rustc_middle::middle::privacy::AccessLevel;
4950
use rustc_middle::span_bug;
5051
use rustc_middle::ty::query::Providers;
51-
use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs};
52+
use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs, Visibility};
5253
use rustc_session::lint;
5354
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
5455
use 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

Comments
 (0)