Skip to content

Commit c0a7612

Browse files
committed
Auto merge of #103690 - GuillaumeGomez:visibility-on-demand, r=notriddle
Make rustdoc Item::visibility computed on-demand This is a take-over of #91408. Helps with #90852 (needs to use `ty::Visibility` directly too). cc `@camelid` r? `@notriddle`
2 parents 822f8c2 + 5515e2c commit c0a7612

File tree

11 files changed

+144
-145
lines changed

11 files changed

+144
-145
lines changed

Diff for: src/librustdoc/clean/auto_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ where
118118
Some(Item {
119119
name: None,
120120
attrs: Default::default(),
121-
visibility: Inherited,
122121
item_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
123122
kind: Box::new(ImplItem(Box::new(Impl {
124123
unsafety: hir::Unsafety::Normal,
@@ -130,6 +129,7 @@ where
130129
kind: ImplKind::Auto,
131130
}))),
132131
cfg: None,
132+
inline_stmt_id: None,
133133
})
134134
}
135135

Diff for: src/librustdoc/clean/blanket_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
9797
impls.push(Item {
9898
name: None,
9999
attrs: Default::default(),
100-
visibility: Inherited,
101100
item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
102101
kind: Box::new(ImplItem(Box::new(Impl {
103102
unsafety: hir::Unsafety::Normal,
@@ -128,6 +127,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
128127
))),
129128
}))),
130129
cfg: None,
130+
inline_stmt_id: None,
131131
});
132132
}
133133
}

Diff for: src/librustdoc/clean/inline.rs

+7-22
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::clean::{
2020
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
2121
clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
2222
clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt,
23-
ImplKind, ItemId, Type, Visibility,
23+
ImplKind, ItemId, Type,
2424
};
2525
use crate::core::DocContext;
2626
use crate::formats::item_type::ItemType;
@@ -152,18 +152,10 @@ pub(crate) fn try_inline(
152152

153153
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs);
154154
cx.inlined.insert(did.into());
155-
let mut item = clean::Item::from_def_id_and_attrs_and_parts(
156-
did,
157-
Some(name),
158-
kind,
159-
Box::new(attrs),
160-
cx,
161-
cfg,
162-
);
163-
if let Some(import_def_id) = import_def_id {
164-
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
165-
item.visibility = clean_visibility(cx.tcx.visibility(import_def_id));
166-
}
155+
let mut item =
156+
clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, Box::new(attrs), cfg);
157+
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
158+
item.inline_stmt_id = import_def_id;
167159
ret.push(item);
168160
Some(ret)
169161
}
@@ -239,13 +231,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
239231
.tcx
240232
.associated_items(did)
241233
.in_definition_order()
242-
.map(|item| {
243-
// When building an external trait, the cleaned trait will have all items public,
244-
// which causes methods to have a `pub` prefix, which is invalid since items in traits
245-
// can not have a visibility prefix. Thus we override the visibility here manually.
246-
// See https://github.com/rust-lang/rust/issues/81274
247-
clean::Item { visibility: Visibility::Inherited, ..clean_middle_assoc_item(item, cx) }
248-
})
234+
.map(|item| clean_middle_assoc_item(item, cx))
249235
.collect();
250236

251237
let predicates = cx.tcx.predicates_of(did);
@@ -559,7 +545,6 @@ pub(crate) fn build_impl(
559545
},
560546
})),
561547
Box::new(merged_attrs),
562-
cx,
563548
cfg,
564549
));
565550
}
@@ -607,7 +592,6 @@ fn build_module_items(
607592
name: None,
608593
attrs: Box::new(clean::Attributes::default()),
609594
item_id: ItemId::Primitive(prim_ty, did.krate),
610-
visibility: clean::Public,
611595
kind: Box::new(clean::ImportItem(clean::Import::new_simple(
612596
item.ident.name,
613597
clean::ImportSource {
@@ -626,6 +610,7 @@ fn build_module_items(
626610
true,
627611
))),
628612
cfg: None,
613+
inline_stmt_id: None,
629614
});
630615
} else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
631616
items.extend(i)

Diff for: src/librustdoc/clean/mod.rs

+9-55
Original file line numberDiff line numberDiff line change
@@ -1083,10 +1083,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
10831083
TyAssocTypeItem(Box::new(generics), bounds)
10841084
}
10851085
};
1086-
let what_rustc_thinks =
1087-
Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx);
1088-
// Trait items always inherit the trait's visibility -- we don't want to show `pub`.
1089-
Item { visibility: Inherited, ..what_rustc_thinks }
1086+
Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
10901087
})
10911088
}
10921089

@@ -1117,18 +1114,7 @@ pub(crate) fn clean_impl_item<'tcx>(
11171114
}
11181115
};
11191116

1120-
let mut what_rustc_thinks =
1121-
Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx);
1122-
1123-
let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.owner_id.def_id));
1124-
1125-
// Trait impl items always inherit the impl's visibility --
1126-
// we don't want to show `pub`.
1127-
if impl_ref.is_some() {
1128-
what_rustc_thinks.visibility = Inherited;
1129-
}
1130-
1131-
what_rustc_thinks
1117+
Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx)
11321118
})
11331119
}
11341120

@@ -1340,18 +1326,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
13401326
}
13411327
};
13421328

1343-
let mut what_rustc_thinks =
1344-
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx);
1345-
1346-
let impl_ref = tcx.impl_trait_ref(tcx.parent(assoc_item.def_id));
1347-
1348-
// Trait impl items always inherit the impl's visibility --
1349-
// we don't want to show `pub`.
1350-
if impl_ref.is_some() {
1351-
what_rustc_thinks.visibility = Visibility::Inherited;
1352-
}
1353-
1354-
what_rustc_thinks
1329+
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx)
13551330
}
13561331

13571332
fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
@@ -1821,23 +1796,7 @@ pub(crate) fn clean_field_with_def_id(
18211796
ty: Type,
18221797
cx: &mut DocContext<'_>,
18231798
) -> Item {
1824-
let what_rustc_thinks =
1825-
Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx);
1826-
if is_field_vis_inherited(cx.tcx, def_id) {
1827-
// Variant fields inherit their enum's visibility.
1828-
Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
1829-
} else {
1830-
what_rustc_thinks
1831-
}
1832-
}
1833-
1834-
fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
1835-
let parent = tcx.parent(def_id);
1836-
match tcx.def_kind(parent) {
1837-
DefKind::Struct | DefKind::Union => false,
1838-
DefKind::Variant => true,
1839-
parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
1840-
}
1799+
Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx)
18411800
}
18421801

18431802
pub(crate) fn clean_visibility(vis: ty::Visibility<DefId>) -> Visibility {
@@ -1861,10 +1820,7 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont
18611820
fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
18621821
}),
18631822
};
1864-
let what_rustc_thinks =
1865-
Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx);
1866-
// don't show `pub` for variants, which always inherit visibility
1867-
Item { visibility: Inherited, ..what_rustc_thinks }
1823+
Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx)
18681824
}
18691825

18701826
fn clean_variant_data<'tcx>(
@@ -2038,10 +1994,7 @@ fn clean_maybe_renamed_item<'tcx>(
20381994

20391995
fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
20401996
let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
2041-
let what_rustc_thinks =
2042-
Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
2043-
// don't show `pub` for variants, which are always public
2044-
Item { visibility: Inherited, ..what_rustc_thinks }
1997+
Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx)
20451998
}
20461999

20472000
fn clean_impl<'tcx>(
@@ -2114,6 +2067,7 @@ fn clean_extern_crate<'tcx>(
21142067
}
21152068
});
21162069

2070+
let krate_owner_def_id = krate.owner_id.to_def_id();
21172071
if please_inline {
21182072
let mut visited = FxHashSet::default();
21192073

@@ -2122,7 +2076,7 @@ fn clean_extern_crate<'tcx>(
21222076
if let Some(items) = inline::try_inline(
21232077
cx,
21242078
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
2125-
Some(krate.owner_id.to_def_id()),
2079+
Some(krate_owner_def_id),
21262080
res,
21272081
name,
21282082
Some(attrs),
@@ -2137,9 +2091,9 @@ fn clean_extern_crate<'tcx>(
21372091
name: Some(name),
21382092
attrs: Box::new(Attributes::from_ast(attrs)),
21392093
item_id: crate_def_id.into(),
2140-
visibility: clean_visibility(ty_vis),
21412094
kind: Box::new(ExternCrateItem { src: orig_name }),
21422095
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
2096+
inline_stmt_id: Some(krate_owner_def_id),
21432097
}]
21442098
}
21452099

Diff for: src/librustdoc/clean/types.rs

+66-18
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_hir::{BodyId, Mutability};
2424
use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
2525
use rustc_index::vec::IndexVec;
2626
use rustc_middle::ty::fast_reject::SimplifiedType;
27-
use rustc_middle::ty::{self, TyCtxt};
27+
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
2828
use rustc_session::Session;
2929
use rustc_span::hygiene::MacroKind;
3030
use rustc_span::source_map::DUMMY_SP;
@@ -348,12 +348,12 @@ pub(crate) struct Item {
348348
/// Optional because not every item has a name, e.g. impls.
349349
pub(crate) name: Option<Symbol>,
350350
pub(crate) attrs: Box<Attributes>,
351-
pub(crate) visibility: Visibility,
352351
/// Information about this item that is specific to what kind of item it is.
353352
/// E.g., struct vs enum vs function.
354353
pub(crate) kind: Box<ItemKind>,
355354
pub(crate) item_id: ItemId,
356-
355+
/// This is the `DefId` of the `use` statement if the item was inlined.
356+
pub(crate) inline_stmt_id: Option<DefId>,
357357
pub(crate) cfg: Option<Arc<Cfg>>,
358358
}
359359

@@ -364,9 +364,7 @@ impl fmt::Debug for Item {
364364
let alternate = f.alternate();
365365
// hand-picked fields that don't bloat the logs too much
366366
let mut fmt = f.debug_struct("Item");
367-
fmt.field("name", &self.name)
368-
.field("visibility", &self.visibility)
369-
.field("item_id", &self.item_id);
367+
fmt.field("name", &self.name).field("item_id", &self.item_id);
370368
// allow printing the full item if someone really wants to
371369
if alternate {
372370
fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
@@ -388,6 +386,15 @@ pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
388386
))
389387
}
390388

389+
fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
390+
let parent = tcx.parent(def_id);
391+
match tcx.def_kind(parent) {
392+
DefKind::Struct | DefKind::Union => false,
393+
DefKind::Variant => true,
394+
parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
395+
}
396+
}
397+
391398
impl Item {
392399
pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
393400
self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
@@ -462,7 +469,6 @@ impl Item {
462469
name,
463470
kind,
464471
Box::new(Attributes::from_ast(ast_attrs)),
465-
cx,
466472
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
467473
)
468474
}
@@ -472,21 +478,18 @@ impl Item {
472478
name: Option<Symbol>,
473479
kind: ItemKind,
474480
attrs: Box<Attributes>,
475-
cx: &mut DocContext<'_>,
476481
cfg: Option<Arc<Cfg>>,
477482
) -> Item {
478483
trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
479484

480-
// Primitives and Keywords are written in the source code as private modules.
481-
// The modules need to be private so that nobody actually uses them, but the
482-
// keywords and primitives that they are documenting are public.
483-
let visibility = if matches!(&kind, ItemKind::KeywordItem | ItemKind::PrimitiveItem(..)) {
484-
Visibility::Public
485-
} else {
486-
clean_visibility(cx.tcx.visibility(def_id))
487-
};
488-
489-
Item { item_id: def_id.into(), kind: Box::new(kind), name, attrs, visibility, cfg }
485+
Item {
486+
item_id: def_id.into(),
487+
kind: Box::new(kind),
488+
name,
489+
attrs,
490+
cfg,
491+
inline_stmt_id: None,
492+
}
490493
}
491494

492495
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
@@ -702,6 +705,51 @@ impl Item {
702705
};
703706
Some(header)
704707
}
708+
709+
pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility {
710+
let def_id = match self.item_id {
711+
// Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
712+
ItemId::Auto { .. } | ItemId::Blanket { .. } => return Visibility::Inherited,
713+
// Primitives and Keywords are written in the source code as private modules.
714+
// The modules need to be private so that nobody actually uses them, but the
715+
// keywords and primitives that they are documenting are public.
716+
ItemId::Primitive(..) => return Visibility::Public,
717+
ItemId::DefId(def_id) => def_id,
718+
};
719+
720+
match *self.kind {
721+
// Explication on `ItemId::Primitive` just above.
722+
ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Visibility::Public,
723+
// Variant fields inherit their enum's visibility.
724+
StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
725+
return Visibility::Inherited;
726+
}
727+
// Variants always inherit visibility
728+
VariantItem(..) => return Visibility::Inherited,
729+
// Trait items inherit the trait's visibility
730+
AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..)
731+
| TyMethodItem(..) | MethodItem(..) => {
732+
let assoc_item = tcx.associated_item(def_id);
733+
let is_trait_item = match assoc_item.container {
734+
ty::TraitContainer => true,
735+
ty::ImplContainer => {
736+
// Trait impl items always inherit the impl's visibility --
737+
// we don't want to show `pub`.
738+
tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
739+
}
740+
};
741+
if is_trait_item {
742+
return Visibility::Inherited;
743+
}
744+
}
745+
_ => {}
746+
}
747+
let def_id = match self.inline_stmt_id {
748+
Some(inlined) => inlined,
749+
None => def_id,
750+
};
751+
clean_visibility(tcx.visibility(def_id))
752+
}
705753
}
706754

707755
#[derive(Clone, Debug)]

0 commit comments

Comments
 (0)