Make rustdoc Item::visibility computed on-demand

This commit is contained in:
Guillaume Gomez 2022-10-28 16:15:37 +02:00
parent fab0432952
commit 5515e2c2a1
11 changed files with 144 additions and 145 deletions

View File

@ -118,7 +118,6 @@ where
Some(Item {
name: None,
attrs: Default::default(),
visibility: Inherited,
item_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
kind: Box::new(ImplItem(Box::new(Impl {
unsafety: hir::Unsafety::Normal,
@ -130,6 +129,7 @@ where
kind: ImplKind::Auto,
}))),
cfg: None,
inline_stmt_id: None,
})
}

View File

@ -97,7 +97,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
impls.push(Item {
name: None,
attrs: Default::default(),
visibility: Inherited,
item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
kind: Box::new(ImplItem(Box::new(Impl {
unsafety: hir::Unsafety::Normal,
@ -128,6 +127,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
))),
}))),
cfg: None,
inline_stmt_id: None,
});
}
}

View File

@ -20,7 +20,7 @@ use crate::clean::{
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt,
ImplKind, ItemId, Type, Visibility,
ImplKind, ItemId, Type,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
@ -152,18 +152,10 @@ pub(crate) fn try_inline(
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs);
cx.inlined.insert(did.into());
let mut item = clean::Item::from_def_id_and_attrs_and_parts(
did,
Some(name),
kind,
Box::new(attrs),
cx,
cfg,
);
if let Some(import_def_id) = import_def_id {
let mut item =
clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, Box::new(attrs), cfg);
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
item.visibility = clean_visibility(cx.tcx.visibility(import_def_id));
}
item.inline_stmt_id = import_def_id;
ret.push(item);
Some(ret)
}
@ -239,13 +231,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
.tcx
.associated_items(did)
.in_definition_order()
.map(|item| {
// When building an external trait, the cleaned trait will have all items public,
// which causes methods to have a `pub` prefix, which is invalid since items in traits
// can not have a visibility prefix. Thus we override the visibility here manually.
// See https://github.com/rust-lang/rust/issues/81274
clean::Item { visibility: Visibility::Inherited, ..clean_middle_assoc_item(item, cx) }
})
.map(|item| clean_middle_assoc_item(item, cx))
.collect();
let predicates = cx.tcx.predicates_of(did);
@ -544,7 +530,6 @@ pub(crate) fn build_impl(
},
})),
Box::new(merged_attrs),
cx,
cfg,
));
}
@ -592,7 +577,6 @@ fn build_module_items(
name: None,
attrs: Box::new(clean::Attributes::default()),
item_id: ItemId::Primitive(prim_ty, did.krate),
visibility: clean::Public,
kind: Box::new(clean::ImportItem(clean::Import::new_simple(
item.ident.name,
clean::ImportSource {
@ -611,6 +595,7 @@ fn build_module_items(
true,
))),
cfg: None,
inline_stmt_id: None,
});
} else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
items.extend(i)

View File

@ -1083,10 +1083,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
TyAssocTypeItem(Box::new(generics), bounds)
}
};
let what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx);
// Trait items always inherit the trait's visibility -- we don't want to show `pub`.
Item { visibility: Inherited, ..what_rustc_thinks }
Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
})
}
@ -1117,18 +1114,7 @@ pub(crate) fn clean_impl_item<'tcx>(
}
};
let mut what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx);
let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.owner_id.def_id));
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
if impl_ref.is_some() {
what_rustc_thinks.visibility = Inherited;
}
what_rustc_thinks
Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx)
})
}
@ -1340,18 +1326,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
}
};
let mut what_rustc_thinks =
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx);
let impl_ref = tcx.impl_trait_ref(tcx.parent(assoc_item.def_id));
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
if impl_ref.is_some() {
what_rustc_thinks.visibility = Visibility::Inherited;
}
what_rustc_thinks
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx)
}
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(
ty: Type,
cx: &mut DocContext<'_>,
) -> Item {
let what_rustc_thinks =
Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx);
if is_field_vis_inherited(cx.tcx, def_id) {
// Variant fields inherit their enum's visibility.
Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
} else {
what_rustc_thinks
}
}
fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let parent = tcx.parent(def_id);
match tcx.def_kind(parent) {
DefKind::Struct | DefKind::Union => false,
DefKind::Variant => true,
parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
}
Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx)
}
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
fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
}),
};
let what_rustc_thinks =
Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx);
// don't show `pub` for variants, which always inherit visibility
Item { visibility: Inherited, ..what_rustc_thinks }
Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx)
}
fn clean_variant_data<'tcx>(
@ -2038,10 +1994,7 @@ fn clean_maybe_renamed_item<'tcx>(
fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
let what_rustc_thinks =
Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
// don't show `pub` for variants, which are always public
Item { visibility: Inherited, ..what_rustc_thinks }
Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx)
}
fn clean_impl<'tcx>(
@ -2114,6 +2067,7 @@ fn clean_extern_crate<'tcx>(
}
});
let krate_owner_def_id = krate.owner_id.to_def_id();
if please_inline {
let mut visited = FxHashSet::default();
@ -2122,7 +2076,7 @@ fn clean_extern_crate<'tcx>(
if let Some(items) = inline::try_inline(
cx,
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
Some(krate.owner_id.to_def_id()),
Some(krate_owner_def_id),
res,
name,
Some(attrs),
@ -2137,9 +2091,9 @@ fn clean_extern_crate<'tcx>(
name: Some(name),
attrs: Box::new(Attributes::from_ast(attrs)),
item_id: crate_def_id.into(),
visibility: clean_visibility(ty_vis),
kind: Box::new(ExternCrateItem { src: orig_name }),
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
inline_stmt_id: Some(krate_owner_def_id),
}]
}

View File

@ -24,7 +24,7 @@ use rustc_hir::{BodyId, Mutability};
use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DUMMY_SP;
@ -348,12 +348,12 @@ pub(crate) struct Item {
/// Optional because not every item has a name, e.g. impls.
pub(crate) name: Option<Symbol>,
pub(crate) attrs: Box<Attributes>,
pub(crate) visibility: Visibility,
/// Information about this item that is specific to what kind of item it is.
/// E.g., struct vs enum vs function.
pub(crate) kind: Box<ItemKind>,
pub(crate) item_id: ItemId,
/// This is the `DefId` of the `use` statement if the item was inlined.
pub(crate) inline_stmt_id: Option<DefId>,
pub(crate) cfg: Option<Arc<Cfg>>,
}
@ -364,9 +364,7 @@ impl fmt::Debug for Item {
let alternate = f.alternate();
// hand-picked fields that don't bloat the logs too much
let mut fmt = f.debug_struct("Item");
fmt.field("name", &self.name)
.field("visibility", &self.visibility)
.field("item_id", &self.item_id);
fmt.field("name", &self.name).field("item_id", &self.item_id);
// allow printing the full item if someone really wants to
if alternate {
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 {
))
}
fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let parent = tcx.parent(def_id);
match tcx.def_kind(parent) {
DefKind::Struct | DefKind::Union => false,
DefKind::Variant => true,
parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
}
}
impl Item {
pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
@ -462,7 +469,6 @@ impl Item {
name,
kind,
Box::new(Attributes::from_ast(ast_attrs)),
cx,
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
)
}
@ -472,21 +478,18 @@ impl Item {
name: Option<Symbol>,
kind: ItemKind,
attrs: Box<Attributes>,
cx: &mut DocContext<'_>,
cfg: Option<Arc<Cfg>>,
) -> Item {
trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
// Primitives and Keywords are written in the source code as private modules.
// The modules need to be private so that nobody actually uses them, but the
// keywords and primitives that they are documenting are public.
let visibility = if matches!(&kind, ItemKind::KeywordItem | ItemKind::PrimitiveItem(..)) {
Visibility::Public
} else {
clean_visibility(cx.tcx.visibility(def_id))
};
Item { item_id: def_id.into(), kind: Box::new(kind), name, attrs, visibility, cfg }
Item {
item_id: def_id.into(),
kind: Box::new(kind),
name,
attrs,
cfg,
inline_stmt_id: None,
}
}
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
@ -702,6 +705,51 @@ impl Item {
};
Some(header)
}
pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Visibility {
let def_id = match self.item_id {
// Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
ItemId::Auto { .. } | ItemId::Blanket { .. } => return Visibility::Inherited,
// Primitives and Keywords are written in the source code as private modules.
// The modules need to be private so that nobody actually uses them, but the
// keywords and primitives that they are documenting are public.
ItemId::Primitive(..) => return Visibility::Public,
ItemId::DefId(def_id) => def_id,
};
match *self.kind {
// Explication on `ItemId::Primitive` just above.
ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Visibility::Public,
// Variant fields inherit their enum's visibility.
StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
return Visibility::Inherited;
}
// Variants always inherit visibility
VariantItem(..) => return Visibility::Inherited,
// Trait items inherit the trait's visibility
AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..)
| TyMethodItem(..) | MethodItem(..) => {
let assoc_item = tcx.associated_item(def_id);
let is_trait_item = match assoc_item.container {
ty::TraitContainer => true,
ty::ImplContainer => {
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
}
};
if is_trait_item {
return Visibility::Inherited;
}
}
_ => {}
}
let def_id = match self.inline_stmt_id {
Some(inlined) => inlined,
None => def_id,
};
clean_visibility(tcx.visibility(def_id))
}
}
#[derive(Clone, Debug)]

View File

@ -747,11 +747,12 @@ fn assoc_const(
extra: &str,
cx: &Context<'_>,
) {
let tcx = cx.tcx();
write!(
w,
"{extra}{vis}const <a{href} class=\"constant\">{name}</a>: {ty}",
extra = extra,
vis = it.visibility.print_with_space(it.item_id, cx),
vis = it.visibility(tcx).print_with_space(it.item_id, cx),
href = assoc_href_attr(it, link, cx),
name = it.name.as_ref().unwrap(),
ty = ty.print(cx),
@ -764,7 +765,7 @@ fn assoc_const(
// This hurts readability in this context especially when more complex expressions
// are involved and it doesn't add much of value.
// Find a way to print constants here without all that jazz.
write!(w, "{}", Escape(&default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx()))));
write!(w, "{}", Escape(&default.value(tcx).unwrap_or_else(|| default.expr(tcx))));
}
}
@ -805,14 +806,15 @@ fn assoc_method(
cx: &Context<'_>,
render_mode: RenderMode,
) {
let header = meth.fn_header(cx.tcx()).expect("Trying to get header from a non-function item");
let tcx = cx.tcx();
let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item");
let name = meth.name.as_ref().unwrap();
let vis = meth.visibility.print_with_space(meth.item_id, cx).to_string();
let vis = meth.visibility(tcx).print_with_space(meth.item_id, cx).to_string();
// FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
// this condition.
let constness = match render_mode {
RenderMode::Normal => {
print_constness_with_space(&header.constness, meth.const_stability(cx.tcx()))
print_constness_with_space(&header.constness, meth.const_stability(tcx))
}
RenderMode::ForDeref { .. } => "",
};

View File

@ -318,6 +318,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
);
}
let tcx = cx.tcx();
match *myitem.kind {
clean::ExternCrateItem { ref src } => {
use crate::html::format::anchor;
@ -327,14 +328,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
Some(src) => write!(
w,
"<div class=\"item-left\"><code>{}extern crate {} as {};",
myitem.visibility.print_with_space(myitem.item_id, cx),
myitem.visibility(tcx).print_with_space(myitem.item_id, cx),
anchor(myitem.item_id.expect_def_id(), src, cx),
myitem.name.unwrap(),
),
None => write!(
w,
"<div class=\"item-left\"><code>{}extern crate {};",
myitem.visibility.print_with_space(myitem.item_id, cx),
myitem.visibility(tcx).print_with_space(myitem.item_id, cx),
anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
),
}
@ -384,7 +385,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
</div>\
{stab_tags_before}{stab_tags}{stab_tags_after}",
stab = stab.unwrap_or_default(),
vis = myitem.visibility.print_with_space(myitem.item_id, cx),
vis = myitem.visibility(tcx).print_with_space(myitem.item_id, cx),
imp = import.print(cx),
);
w.write_str(ITEM_TABLE_ROW_CLOSE);
@ -408,7 +409,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
let stab = myitem.stability_class(cx.tcx());
let add = if stab.is_some() { " " } else { "" };
let visibility_emoji = match myitem.visibility {
let visibility_emoji = match myitem.visibility(tcx) {
clean::Visibility::Restricted(_) => {
"<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
}
@ -496,12 +497,13 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
}
fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
let header = it.fn_header(cx.tcx()).expect("printing a function which isn't a function");
let constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx()));
let tcx = cx.tcx();
let header = it.fn_header(tcx).expect("printing a function which isn't a function");
let constness = print_constness_with_space(&header.constness, it.const_stability(tcx));
let unsafety = header.unsafety.print_with_space();
let abi = print_abi_with_space(header.abi).to_string();
let asyncness = header.asyncness.print_with_space();
let visibility = it.visibility.print_with_space(it.item_id, cx).to_string();
let visibility = it.visibility(tcx).print_with_space(it.item_id, cx).to_string();
let name = it.name.unwrap();
let generics_len = format!("{:#}", f.generics.print(cx)).len();
@ -539,6 +541,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
}
fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
let tcx = cx.tcx();
let bounds = bounds(&t.bounds, false, cx);
let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
@ -549,8 +552,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
let count_types = required_types.len() + provided_types.len();
let count_consts = required_consts.len() + provided_consts.len();
let count_methods = required_methods.len() + provided_methods.len();
let must_implement_one_of_functions =
cx.tcx().trait_def(t.def_id).must_implement_one_of.clone();
let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
// Output the trait definition
wrap_into_item_decl(w, |w| {
@ -559,9 +561,9 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
write!(
w,
"{}{}{}trait {}{}{}",
it.visibility.print_with_space(it.item_id, cx),
t.unsafety(cx.tcx()).print_with_space(),
if t.is_auto(cx.tcx()) { "auto " } else { "" },
it.visibility(tcx).print_with_space(it.item_id, cx),
t.unsafety(tcx).print_with_space(),
if t.is_auto(tcx) { "auto " } else { "" },
it.name.unwrap(),
t.generics.print(cx),
bounds
@ -1020,7 +1022,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
}
let extern_crates = extern_crates
.into_iter()
.map(|cnum| cx.shared.tcx.crate_name(cnum).to_string())
.map(|cnum| tcx.crate_name(cnum).to_string())
.collect::<Vec<_>>()
.join(",");
let (extern_before, extern_after) =
@ -1084,7 +1086,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
wrap_item(w, "typedef", |w| {
render_attributes_in_pre(w, it, "");
write!(w, "{}", it.visibility.print_with_space(it.item_id, cx));
write!(w, "{}", it.visibility(cx.tcx()).print_with_space(it.item_id, cx));
write!(
w,
"type {}{}{where_clause} = {type_};",
@ -1173,6 +1175,7 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]
}
fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
let tcx = cx.tcx();
let count_variants = e.variants().count();
wrap_into_item_decl(w, |w| {
wrap_item(w, "enum", |w| {
@ -1180,7 +1183,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
write!(
w,
"{}enum {}{}",
it.visibility.print_with_space(it.item_id, cx),
it.visibility(tcx).print_with_space(it.item_id, cx),
it.name.unwrap(),
e.generics.print(cx),
);
@ -1268,10 +1271,10 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
w.write_str("</code>");
render_stability_since_raw(
w,
variant.stable_since(cx.tcx()),
variant.const_stability(cx.tcx()),
it.stable_since(cx.tcx()),
it.const_stable_since(cx.tcx()),
variant.stable_since(tcx),
variant.const_stability(tcx),
it.stable_since(tcx),
it.const_stable_since(tcx),
);
w.write_str("</h3>");
@ -1389,12 +1392,13 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
wrap_into_item_decl(w, |w| {
wrap_item(w, "const", |w| {
let tcx = cx.tcx();
render_attributes_in_code(w, it);
write!(
w,
"{vis}const {name}: {typ}",
vis = it.visibility.print_with_space(it.item_id, cx),
vis = it.visibility(tcx).print_with_space(it.item_id, cx),
name = it.name.unwrap(),
typ = c.type_.print(cx),
);
@ -1408,9 +1412,9 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
// ` = 100i32;`
// instead?
let value = c.value(cx.tcx());
let is_literal = c.is_literal(cx.tcx());
let expr = c.expr(cx.tcx());
let value = c.value(tcx);
let is_literal = c.is_literal(tcx);
let expr = c.expr(tcx);
if value.is_some() || is_literal {
write!(w, " = {expr};", expr = Escape(&expr));
} else {
@ -1495,7 +1499,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
write!(
w,
"{vis}static {mutability}{name}: {typ}",
vis = it.visibility.print_with_space(it.item_id, cx),
vis = it.visibility(cx.tcx()).print_with_space(it.item_id, cx),
mutability = s.mutability.print_with_space(),
name = it.name.unwrap(),
typ = s.type_.print(cx)
@ -1513,7 +1517,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
write!(
w,
" {}type {};\n}}",
it.visibility.print_with_space(it.item_id, cx),
it.visibility(cx.tcx()).print_with_space(it.item_id, cx),
it.name.unwrap(),
);
});
@ -1666,7 +1670,8 @@ fn render_union(
tab: &str,
cx: &Context<'_>,
) {
write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap(),);
let tcx = cx.tcx();
write!(w, "{}union {}", it.visibility(tcx).print_with_space(it.item_id, cx), it.name.unwrap(),);
let where_displayed = g
.map(|g| {
@ -1693,7 +1698,7 @@ fn render_union(
write!(
w,
" {}{}: {},\n{}",
field.visibility.print_with_space(field.item_id, cx),
field.visibility(tcx).print_with_space(field.item_id, cx),
field.name.unwrap(),
ty.print(cx),
tab
@ -1720,10 +1725,11 @@ fn render_struct(
structhead: bool,
cx: &Context<'_>,
) {
let tcx = cx.tcx();
write!(
w,
"{}{}{}",
it.visibility.print_with_space(it.item_id, cx),
it.visibility(tcx).print_with_space(it.item_id, cx),
if structhead { "struct " } else { "" },
it.name.unwrap()
);
@ -1753,7 +1759,7 @@ fn render_struct(
w,
"\n{} {}{}: {},",
tab,
field.visibility.print_with_space(field.item_id, cx),
field.visibility(tcx).print_with_space(field.item_id, cx),
field.name.unwrap(),
ty.print(cx),
);
@ -1785,7 +1791,7 @@ fn render_struct(
write!(
w,
"{}{}",
field.visibility.print_with_space(field.item_id, cx),
field.visibility(tcx).print_with_space(field.item_id, cx),
ty.print(cx),
)
}

View File

@ -48,7 +48,8 @@ impl JsonRenderer<'_> {
.map(rustc_ast_pretty::pprust::attribute_to_string)
.collect();
let span = item.span(self.tcx);
let clean::Item { name, attrs: _, kind: _, visibility, item_id, cfg: _ } = item;
let visibility = item.visibility(self.tcx);
let clean::Item { name, attrs: _, kind: _, item_id, cfg: _, .. } = item;
let inner = match *item.kind {
clean::KeywordItem => return None,
clean::StrippedItem(ref inner) => {

View File

@ -11,6 +11,6 @@ pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass {
description: "strips all private import statements (`use`, `extern crate`) from a crate",
};
pub(crate) fn strip_priv_imports(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate {
ImportStripper.fold_crate(krate)
pub(crate) fn strip_priv_imports(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
ImportStripper { tcx: cx.tcx }.fold_crate(krate)
}

View File

@ -22,13 +22,13 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) ->
// strip all private items
{
let mut stripper = Stripper {
tcx: cx.tcx,
retained: &mut retained,
effective_visibilities: &cx.cache.effective_visibilities,
update_retained: true,
is_json_output,
tcx: cx.tcx,
};
krate = ImportStripper.fold_crate(stripper.fold_crate(krate));
krate = ImportStripper { tcx: cx.tcx }.fold_crate(stripper.fold_crate(krate));
}
// strip all impls referencing private items

View File

@ -2,7 +2,6 @@
use rustc_hir::def_id::DefId;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
use std::mem;
use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt};
@ -11,11 +10,11 @@ use crate::formats::cache::Cache;
use crate::visit_lib::RustdocEffectiveVisibilities;
pub(crate) struct Stripper<'a, 'tcx> {
pub(crate) tcx: TyCtxt<'tcx>,
pub(crate) retained: &'a mut ItemIdSet,
pub(crate) effective_visibilities: &'a RustdocEffectiveVisibilities,
pub(crate) update_retained: bool,
pub(crate) is_json_output: bool,
pub(crate) tcx: TyCtxt<'tcx>,
}
// We need to handle this differently for the JSON output because some non exported items could
@ -35,7 +34,7 @@ fn is_item_reachable(
}
}
impl<'a> DocFolder for Stripper<'a, '_> {
impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
match *i.kind {
clean::StrippedItem(..) => {
@ -82,13 +81,13 @@ impl<'a> DocFolder for Stripper<'a, '_> {
}
clean::StructFieldItem(..) => {
if !i.visibility.is_public() {
if !i.visibility(self.tcx).is_public() {
return Some(strip_item(i));
}
}
clean::ModuleItem(..) => {
if i.item_id.is_local() && !i.visibility.is_public() {
if i.item_id.is_local() && !i.visibility(self.tcx).is_public() {
debug!("Stripper: stripping module {:?}", i.name);
let old = mem::replace(&mut self.update_retained, false);
let ret = strip_item(self.fold_item_recur(i));
@ -239,12 +238,16 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
}
/// This stripper discards all private import statements (`use`, `extern crate`)
pub(crate) struct ImportStripper;
pub(crate) struct ImportStripper<'tcx> {
pub(crate) tcx: TyCtxt<'tcx>,
}
impl DocFolder for ImportStripper {
impl<'tcx> DocFolder for ImportStripper<'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
match *i.kind {
clean::ExternCrateItem { .. } | clean::ImportItem(..) if !i.visibility.is_public() => {
clean::ExternCrateItem { .. } | clean::ImportItem(..)
if !i.visibility(self.tcx).is_public() =>
{
None
}
_ => Some(self.fold_item_recur(i)),