Skip to content

Commit fab0432

Browse files
committed
Auto merge of #103010 - petrochenkov:effvisdoc, r=GuillaumeGomez
rustdoc: Simplify modifications of effective visibility table It is now obvious that rustdoc only calls `set_access_level` with foreign def ids and `AccessLevel::Public`. The second commit makes one more step and separates effective visibilities coming from rustc from similar data collected by rustdoc for extern `DefId`s. The original table is no longer modified and now only contains local def ids as populated by rustc. cc #102026 `@Bryanskiy`
2 parents e96c330 + f1850d4 commit fab0432

File tree

14 files changed

+108
-144
lines changed

14 files changed

+108
-144
lines changed

compiler/rustc_middle/src/middle/privacy.rs

+16-32
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
66
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
77
use rustc_macros::HashStable;
88
use rustc_query_system::ich::StableHashingContext;
9-
use rustc_span::def_id::{DefId, LocalDefId};
10-
use std::hash::Hash;
9+
use rustc_span::def_id::LocalDefId;
1110

1211
/// Represents the levels of effective visibility an item can have.
1312
///
@@ -75,33 +74,33 @@ impl EffectiveVisibility {
7574
}
7675

7776
/// Holds a map of effective visibilities for reachable HIR nodes.
78-
#[derive(Debug, Clone)]
79-
pub struct EffectiveVisibilities<Id = LocalDefId> {
80-
map: FxHashMap<Id, EffectiveVisibility>,
77+
#[derive(Default, Clone, Debug)]
78+
pub struct EffectiveVisibilities {
79+
map: FxHashMap<LocalDefId, EffectiveVisibility>,
8180
}
8281

83-
impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> {
84-
pub fn is_public_at_level(&self, id: Id, level: Level) -> bool {
82+
impl EffectiveVisibilities {
83+
pub fn is_public_at_level(&self, id: LocalDefId, level: Level) -> bool {
8584
self.effective_vis(id)
8685
.map_or(false, |effective_vis| effective_vis.is_public_at_level(level))
8786
}
8887

8988
/// See `Level::Reachable`.
90-
pub fn is_reachable(&self, id: Id) -> bool {
89+
pub fn is_reachable(&self, id: LocalDefId) -> bool {
9190
self.is_public_at_level(id, Level::Reachable)
9291
}
9392

9493
/// See `Level::Reexported`.
95-
pub fn is_exported(&self, id: Id) -> bool {
94+
pub fn is_exported(&self, id: LocalDefId) -> bool {
9695
self.is_public_at_level(id, Level::Reexported)
9796
}
9897

9998
/// See `Level::Direct`.
100-
pub fn is_directly_public(&self, id: Id) -> bool {
99+
pub fn is_directly_public(&self, id: LocalDefId) -> bool {
101100
self.is_public_at_level(id, Level::Direct)
102101
}
103102

104-
pub fn public_at_level(&self, id: Id) -> Option<Level> {
103+
pub fn public_at_level(&self, id: LocalDefId) -> Option<Level> {
105104
self.effective_vis(id).and_then(|effective_vis| {
106105
for level in Level::all_levels() {
107106
if effective_vis.is_public_at_level(level) {
@@ -112,24 +111,17 @@ impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> {
112111
})
113112
}
114113

115-
pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
114+
pub fn effective_vis(&self, id: LocalDefId) -> Option<&EffectiveVisibility> {
116115
self.map.get(&id)
117116
}
118117

119-
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
118+
pub fn iter(&self) -> impl Iterator<Item = (&LocalDefId, &EffectiveVisibility)> {
120119
self.map.iter()
121120
}
122121

123-
pub fn map_id<OutId: Hash + Eq + Copy>(
124-
&self,
125-
f: impl Fn(Id) -> OutId,
126-
) -> EffectiveVisibilities<OutId> {
127-
EffectiveVisibilities { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() }
128-
}
129-
130122
pub fn set_public_at_level(
131123
&mut self,
132-
id: Id,
124+
id: LocalDefId,
133125
default_vis: impl FnOnce() -> Visibility,
134126
level: Level,
135127
) {
@@ -144,23 +136,21 @@ impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> {
144136
}
145137
self.map.insert(id, effective_vis);
146138
}
147-
}
148139

149-
impl<Id: Hash + Eq + Copy + Into<DefId>> EffectiveVisibilities<Id> {
150140
// `parent_id` is not necessarily a parent in source code tree,
151141
// it is the node from which the maximum effective visibility is inherited.
152142
pub fn update(
153143
&mut self,
154-
id: Id,
144+
id: LocalDefId,
155145
nominal_vis: Visibility,
156146
default_vis: impl FnOnce() -> Visibility,
157-
parent_id: Id,
147+
parent_id: LocalDefId,
158148
level: Level,
159149
tree: impl DefIdTree,
160150
) -> bool {
161151
let mut changed = false;
162152
let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| {
163-
if id.into().is_crate_root() {
153+
if id.is_top_level_module() {
164154
EffectiveVisibility::from_vis(Visibility::Public)
165155
} else {
166156
EffectiveVisibility::from_vis(default_vis())
@@ -204,12 +194,6 @@ impl<Id: Hash + Eq + Copy + Into<DefId>> EffectiveVisibilities<Id> {
204194
}
205195
}
206196

207-
impl<Id> Default for EffectiveVisibilities<Id> {
208-
fn default() -> Self {
209-
EffectiveVisibilities { map: Default::default() }
210-
}
211-
}
212-
213197
impl<'a> HashStable<StableHashingContext<'a>> for EffectiveVisibilities {
214198
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
215199
let EffectiveVisibilities { ref map } = *self;

src/librustdoc/clean/blanket_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
2020
trace!("get_blanket_impls({:?})", ty);
2121
let mut impls = Vec::new();
2222
for trait_def_id in cx.tcx.all_traits() {
23-
if !cx.cache.effective_visibilities.is_directly_public(trait_def_id)
23+
if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, trait_def_id)
2424
|| cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
2525
{
2626
continue;

src/librustdoc/clean/inline.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ pub(crate) fn build_impl(
374374
if !did.is_local() {
375375
if let Some(traitref) = associated_trait {
376376
let did = traitref.def_id;
377-
if !cx.cache.effective_visibilities.is_directly_public(did) {
377+
if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
378378
return;
379379
}
380380

@@ -403,7 +403,7 @@ pub(crate) fn build_impl(
403403
// reachable in rustdoc generated documentation
404404
if !did.is_local() {
405405
if let Some(did) = for_.def_id(&cx.cache) {
406-
if !cx.cache.effective_visibilities.is_directly_public(did) {
406+
if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
407407
return;
408408
}
409409

src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ fn maybe_expand_private_type_alias<'tcx>(
14311431
let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
14321432
// Substitute private type aliases
14331433
let def_id = def_id.as_local()?;
1434-
let alias = if !cx.cache.effective_visibilities.is_exported(def_id.to_def_id()) {
1434+
let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id()) {
14351435
&cx.tcx.hir().expect_item(def_id).kind
14361436
} else {
14371437
return None;

src/librustdoc/clean/utils.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::clean::{
88
};
99
use crate::core::DocContext;
1010
use crate::formats::item_type::ItemType;
11-
use crate::visit_lib::LibEmbargoVisitor;
1211

1312
use rustc_ast as ast;
1413
use rustc_ast::tokenstream::TokenTree;
@@ -32,7 +31,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
3231

3332
for &cnum in cx.tcx.crates(()) {
3433
// Analyze doc-reachability for extern items
35-
LibEmbargoVisitor::new(cx).visit_lib(cnum);
34+
crate::visit_lib::lib_embargo_visit_item(cx, cnum.as_def_id());
3635
}
3736

3837
// Clean the crate, translating the entire librustc_ast AST to one that is

src/librustdoc/core.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ pub(crate) fn run_global_ctxt(
348348

349349
let auto_traits =
350350
tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect();
351-
let effective_visibilities = tcx.effective_visibilities(()).map_id(Into::into);
352351

353352
let mut ctxt = DocContext {
354353
tcx,
@@ -361,7 +360,7 @@ pub(crate) fn run_global_ctxt(
361360
impl_trait_bounds: Default::default(),
362361
generated_synthetics: Default::default(),
363362
auto_traits,
364-
cache: Cache::new(effective_visibilities, render_options.document_private),
363+
cache: Cache::new(render_options.document_private),
365364
inlined: FxHashSet::default(),
366365
output_format,
367366
render_options,

src/librustdoc/formats/cache.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::mem;
22

33
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_hir::def_id::{CrateNum, DefId};
5-
use rustc_middle::middle::privacy::EffectiveVisibilities;
65
use rustc_middle::ty::{self, TyCtxt};
76
use rustc_span::Symbol;
87

@@ -15,6 +14,7 @@ use crate::html::format::join_with_double_colon;
1514
use crate::html::markdown::short_markdown_summary;
1615
use crate::html::render::search_index::get_function_type_for_search;
1716
use crate::html::render::IndexItem;
17+
use crate::visit_lib::RustdocEffectiveVisibilities;
1818

1919
/// This cache is used to store information about the [`clean::Crate`] being
2020
/// rendered in order to provide more useful documentation. This contains
@@ -78,7 +78,7 @@ pub(crate) struct Cache {
7878
// Note that external items for which `doc(hidden)` applies to are shown as
7979
// non-reachable while local items aren't. This is because we're reusing
8080
// the effective visibilities from the privacy check pass.
81-
pub(crate) effective_visibilities: EffectiveVisibilities<DefId>,
81+
pub(crate) effective_visibilities: RustdocEffectiveVisibilities,
8282

8383
/// The version of the crate being documented, if given from the `--crate-version` flag.
8484
pub(crate) crate_version: Option<String>,
@@ -132,11 +132,8 @@ struct CacheBuilder<'a, 'tcx> {
132132
}
133133

134134
impl Cache {
135-
pub(crate) fn new(
136-
effective_visibilities: EffectiveVisibilities<DefId>,
137-
document_private: bool,
138-
) -> Self {
139-
Cache { effective_visibilities, document_private, ..Cache::default() }
135+
pub(crate) fn new(document_private: bool) -> Self {
136+
Cache { document_private, ..Cache::default() }
140137
}
141138

142139
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
@@ -387,7 +384,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
387384
|| self
388385
.cache
389386
.effective_visibilities
390-
.is_directly_public(item.item_id.expect_def_id())
387+
.is_directly_public(self.tcx, item.item_id.expect_def_id())
391388
{
392389
self.cache.paths.insert(
393390
item.item_id.expect_def_id(),

src/librustdoc/html/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ pub(crate) fn href_with_root_path(
659659
}
660660

661661
if !did.is_local()
662-
&& !cache.effective_visibilities.is_directly_public(did)
662+
&& !cache.effective_visibilities.is_directly_public(tcx, did)
663663
&& !cache.document_private
664664
&& !cache.primitive_locations.values().any(|&id| id == did)
665665
{

src/librustdoc/passes/check_doc_test_visibility.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl crate::doctest::Tester for Tests {
5656
}
5757

5858
pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
59-
if !cx.cache.effective_visibilities.is_directly_public(item.item_id.expect_def_id())
59+
if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item.item_id.expect_def_id())
6060
|| matches!(
6161
*item.kind,
6262
clean::StructFieldItem(_)
@@ -130,7 +130,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
130130
);
131131
}
132132
} else if tests.found_tests > 0
133-
&& !cx.cache.effective_visibilities.is_exported(item.item_id.expect_def_id())
133+
&& !cx.cache.effective_visibilities.is_exported(cx.tcx, item.item_id.expect_def_id())
134134
{
135135
cx.tcx.struct_span_lint_hir(
136136
crate::lint::PRIVATE_DOC_TESTS,

src/librustdoc/passes/strip_hidden.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
2727

2828
// strip all impls referencing stripped items
2929
let mut stripper = ImplStripper {
30+
tcx: cx.tcx,
3031
retained: &retained,
3132
cache: &cx.cache,
3233
is_json_output,

src/librustdoc/passes/strip_private.rs

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) ->
2222
// strip all private items
2323
{
2424
let mut stripper = Stripper {
25+
tcx: cx.tcx,
2526
retained: &mut retained,
2627
effective_visibilities: &cx.cache.effective_visibilities,
2728
update_retained: true,
@@ -32,6 +33,7 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) ->
3233

3334
// strip all impls referencing private items
3435
let mut stripper = ImplStripper {
36+
tcx: cx.tcx,
3537
retained: &retained,
3638
cache: &cx.cache,
3739
is_json_output,

src/librustdoc/passes/stripper.rs

+22-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
//! A collection of utility functions for the `strip_*` passes.
22
use rustc_hir::def_id::DefId;
3-
use rustc_middle::middle::privacy::EffectiveVisibilities;
3+
use rustc_middle::ty::TyCtxt;
44
use rustc_span::symbol::sym;
55

66
use std::mem;
77

88
use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt};
99
use crate::fold::{strip_item, DocFolder};
1010
use crate::formats::cache::Cache;
11+
use crate::visit_lib::RustdocEffectiveVisibilities;
1112

12-
pub(crate) struct Stripper<'a> {
13+
pub(crate) struct Stripper<'a, 'tcx> {
14+
pub(crate) tcx: TyCtxt<'tcx>,
1315
pub(crate) retained: &'a mut ItemIdSet,
14-
pub(crate) effective_visibilities: &'a EffectiveVisibilities<DefId>,
16+
pub(crate) effective_visibilities: &'a RustdocEffectiveVisibilities,
1517
pub(crate) update_retained: bool,
1618
pub(crate) is_json_output: bool,
1719
}
@@ -21,18 +23,19 @@ pub(crate) struct Stripper<'a> {
2123
// are in the public API, which is not enough.
2224
#[inline]
2325
fn is_item_reachable(
26+
tcx: TyCtxt<'_>,
2427
is_json_output: bool,
25-
effective_visibilities: &EffectiveVisibilities<DefId>,
28+
effective_visibilities: &RustdocEffectiveVisibilities,
2629
item_id: ItemId,
2730
) -> bool {
2831
if is_json_output {
29-
effective_visibilities.is_reachable(item_id.expect_def_id())
32+
effective_visibilities.is_reachable(tcx, item_id.expect_def_id())
3033
} else {
31-
effective_visibilities.is_exported(item_id.expect_def_id())
34+
effective_visibilities.is_exported(tcx, item_id.expect_def_id())
3235
}
3336
}
3437

35-
impl<'a> DocFolder for Stripper<'a> {
38+
impl<'a> DocFolder for Stripper<'a, '_> {
3639
fn fold_item(&mut self, i: Item) -> Option<Item> {
3740
match *i.kind {
3841
clean::StrippedItem(..) => {
@@ -66,7 +69,12 @@ impl<'a> DocFolder for Stripper<'a> {
6669
| clean::ForeignTypeItem => {
6770
let item_id = i.item_id;
6871
if item_id.is_local()
69-
&& !is_item_reachable(self.is_json_output, self.effective_visibilities, item_id)
72+
&& !is_item_reachable(
73+
self.tcx,
74+
self.is_json_output,
75+
self.effective_visibilities,
76+
item_id,
77+
)
7078
{
7179
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
7280
return None;
@@ -146,30 +154,31 @@ impl<'a> DocFolder for Stripper<'a> {
146154
}
147155

148156
/// This stripper discards all impls which reference stripped items
149-
pub(crate) struct ImplStripper<'a> {
157+
pub(crate) struct ImplStripper<'a, 'tcx> {
158+
pub(crate) tcx: TyCtxt<'tcx>,
150159
pub(crate) retained: &'a ItemIdSet,
151160
pub(crate) cache: &'a Cache,
152161
pub(crate) is_json_output: bool,
153162
pub(crate) document_private: bool,
154163
}
155164

156-
impl<'a> ImplStripper<'a> {
165+
impl<'a> ImplStripper<'a, '_> {
157166
#[inline]
158167
fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool {
159168
if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) {
160169
true
161170
} else if self.is_json_output {
162171
// If the "for" item is exported and the impl block isn't `#[doc(hidden)]`, then we
163172
// need to keep it.
164-
self.cache.effective_visibilities.is_exported(for_def_id)
173+
self.cache.effective_visibilities.is_exported(self.tcx, for_def_id)
165174
&& !item.attrs.lists(sym::doc).has_word(sym::hidden)
166175
} else {
167176
false
168177
}
169178
}
170179
}
171180

172-
impl<'a> DocFolder for ImplStripper<'a> {
181+
impl<'a> DocFolder for ImplStripper<'a, '_> {
173182
fn fold_item(&mut self, i: Item) -> Option<Item> {
174183
if let clean::ImplItem(ref imp) = *i.kind {
175184
// Impl blocks can be skipped if they are: empty; not a trait impl; and have no
@@ -185,6 +194,7 @@ impl<'a> DocFolder for ImplStripper<'a> {
185194
let item_id = i.item_id;
186195
item_id.is_local()
187196
&& !is_item_reachable(
197+
self.tcx,
188198
self.is_json_output,
189199
&self.cache.effective_visibilities,
190200
item_id,

0 commit comments

Comments
 (0)