Skip to content

Commit 7d247c9

Browse files
authored
Rollup merge of #80368 - camelid:rustdoc-succinct-vis, r=jyn514
rustdoc: Render visibilities succinctly Fixes #79139. r? `@jyn514`
2 parents 55cfcd5 + 5604a18 commit 7d247c9

File tree

7 files changed

+136
-97
lines changed

7 files changed

+136
-97
lines changed

src/librustdoc/clean/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2325,18 +2325,19 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
23252325
)
23262326
} else {
23272327
let vis = item.vis.clean(cx);
2328+
let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
23282329

23292330
if matchers.len() <= 1 {
23302331
format!(
23312332
"{}macro {}{} {{\n ...\n}}",
2332-
vis.print_with_space(cx.tcx),
2333+
vis.print_with_space(cx.tcx, def_id),
23332334
name,
23342335
matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
23352336
)
23362337
} else {
23372338
format!(
23382339
"{}macro {} {{\n{}}}",
2339-
vis.print_with_space(cx.tcx),
2340+
vis.print_with_space(cx.tcx, def_id),
23402341
name,
23412342
matchers
23422343
.iter()

src/librustdoc/clean/utils.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Res};
1414
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
1515
use rustc_middle::mir::interpret::ConstValue;
1616
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
17-
use rustc_middle::ty::{self, DefIdTree, Ty};
17+
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
1818
use rustc_span::symbol::{kw, sym, Symbol};
1919
use std::mem;
2020

@@ -623,3 +623,24 @@ where
623623
*cx.impl_trait_bounds.borrow_mut() = old_bounds;
624624
r
625625
}
626+
627+
/// Find the nearest parent module of a [`DefId`].
628+
///
629+
/// **Panics if the item it belongs to [is fake][Item::is_fake].**
630+
crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
631+
if def_id.is_top_level_module() {
632+
// The crate root has no parent. Use it as the root instead.
633+
Some(def_id)
634+
} else {
635+
let mut current = def_id;
636+
// The immediate parent might not always be a module.
637+
// Find the first parent which is.
638+
while let Some(parent) = tcx.parent(current) {
639+
if tcx.def_kind(parent) == DefKind::Mod {
640+
return Some(parent);
641+
}
642+
current = parent;
643+
}
644+
None
645+
}
646+
}

src/librustdoc/html/format.rs

+42-20
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::ty::TyCtxt;
1515
use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
1616
use rustc_target::spec::abi::Abi;
1717

18-
use crate::clean::{self, PrimitiveType};
18+
use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType};
1919
use crate::formats::cache::cache;
2020
use crate::formats::item_type::ItemType;
2121
use crate::html::escape::Escape;
@@ -1085,32 +1085,54 @@ impl Function<'_> {
10851085
}
10861086

10871087
impl clean::Visibility {
1088-
crate fn print_with_space<'tcx>(self, tcx: TyCtxt<'tcx>) -> impl fmt::Display + 'tcx {
1088+
crate fn print_with_space<'tcx>(
1089+
self,
1090+
tcx: TyCtxt<'tcx>,
1091+
item_did: DefId,
1092+
) -> impl fmt::Display + 'tcx {
10891093
use rustc_span::symbol::kw;
10901094

10911095
display_fn(move |f| match self {
10921096
clean::Public => f.write_str("pub "),
10931097
clean::Inherited => Ok(()),
1094-
clean::Visibility::Restricted(did) if did.index == CRATE_DEF_INDEX => {
1095-
write!(f, "pub(crate) ")
1096-
}
1097-
clean::Visibility::Restricted(did) => {
1098-
f.write_str("pub(")?;
1099-
let path = tcx.def_path(did);
1100-
debug!("path={:?}", path);
1101-
let first_name =
1102-
path.data[0].data.get_opt_name().expect("modules are always named");
1103-
if path.data.len() != 1 || (first_name != kw::SelfLower && first_name != kw::Super)
1098+
1099+
clean::Visibility::Restricted(vis_did) => {
1100+
// FIXME(camelid): This may not work correctly if `item_did` is a module.
1101+
// However, rustdoc currently never displays a module's
1102+
// visibility, so it shouldn't matter.
1103+
let parent_module = find_nearest_parent_module(tcx, item_did);
1104+
1105+
if vis_did.index == CRATE_DEF_INDEX {
1106+
write!(f, "pub(crate) ")
1107+
} else if parent_module == Some(vis_did) {
1108+
// `pub(in foo)` where `foo` is the parent module
1109+
// is the same as no visibility modifier
1110+
Ok(())
1111+
} else if parent_module
1112+
.map(|parent| find_nearest_parent_module(tcx, parent))
1113+
.flatten()
1114+
== Some(vis_did)
11041115
{
1105-
f.write_str("in ")?;
1106-
}
1107-
// modified from `resolved_path()` to work with `DefPathData`
1108-
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
1109-
for seg in &path.data[..path.data.len() - 1] {
1110-
write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
1116+
write!(f, "pub(super) ")
1117+
} else {
1118+
f.write_str("pub(")?;
1119+
let path = tcx.def_path(vis_did);
1120+
debug!("path={:?}", path);
1121+
let first_name =
1122+
path.data[0].data.get_opt_name().expect("modules are always named");
1123+
if path.data.len() != 1
1124+
|| (first_name != kw::SelfLower && first_name != kw::Super)
1125+
{
1126+
f.write_str("in ")?;
1127+
}
1128+
// modified from `resolved_path()` to work with `DefPathData`
1129+
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
1130+
for seg in &path.data[..path.data.len() - 1] {
1131+
write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
1132+
}
1133+
let path = anchor(vis_did, &last_name.as_str()).to_string();
1134+
write!(f, "{}) ", path)
11111135
}
1112-
let path = anchor(did, &last_name.as_str()).to_string();
1113-
write!(f, "{}) ", path)
11141136
}
11151137
})
11161138
}

src/librustdoc/html/render/mod.rs

+23-18
Original file line numberDiff line numberDiff line change
@@ -2157,14 +2157,14 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
21572157
Some(ref src) => write!(
21582158
w,
21592159
"<tr><td><code>{}extern crate {} as {};",
2160-
myitem.visibility.print_with_space(cx.tcx()),
2160+
myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
21612161
anchor(myitem.def_id, &*src.as_str()),
21622162
name
21632163
),
21642164
None => write!(
21652165
w,
21662166
"<tr><td><code>{}extern crate {};",
2167-
myitem.visibility.print_with_space(cx.tcx()),
2167+
myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
21682168
anchor(myitem.def_id, &*name.as_str())
21692169
),
21702170
}
@@ -2175,7 +2175,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
21752175
write!(
21762176
w,
21772177
"<tr><td><code>{}{}</code></td></tr>",
2178-
myitem.visibility.print_with_space(cx.tcx()),
2178+
myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
21792179
import.print()
21802180
);
21812181
}
@@ -2392,7 +2392,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
23922392
write!(
23932393
w,
23942394
"{vis}const {name}: {typ}",
2395-
vis = it.visibility.print_with_space(cx.tcx()),
2395+
vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
23962396
name = it.name.as_ref().unwrap(),
23972397
typ = c.type_.print(),
23982398
);
@@ -2426,7 +2426,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
24262426
write!(
24272427
w,
24282428
"{vis}static {mutability}{name}: {typ}</pre>",
2429-
vis = it.visibility.print_with_space(cx.tcx()),
2429+
vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
24302430
mutability = s.mutability.print_with_space(),
24312431
name = it.name.as_ref().unwrap(),
24322432
typ = s.type_.print()
@@ -2437,7 +2437,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
24372437
fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
24382438
let header_len = format!(
24392439
"{}{}{}{}{:#}fn {}{:#}",
2440-
it.visibility.print_with_space(cx.tcx()),
2440+
it.visibility.print_with_space(cx.tcx(), it.def_id),
24412441
f.header.constness.print_with_space(),
24422442
f.header.asyncness.print_with_space(),
24432443
f.header.unsafety.print_with_space(),
@@ -2452,7 +2452,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
24522452
w,
24532453
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
24542454
{name}{generics}{decl}{spotlight}{where_clause}</pre>",
2455-
vis = it.visibility.print_with_space(cx.tcx()),
2455+
vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
24562456
constness = f.header.constness.print_with_space(),
24572457
asyncness = f.header.asyncness.print_with_space(),
24582458
unsafety = f.header.unsafety.print_with_space(),
@@ -2578,7 +2578,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
25782578
write!(
25792579
w,
25802580
"{}{}{}trait {}{}{}",
2581-
it.visibility.print_with_space(cx.tcx()),
2581+
it.visibility.print_with_space(cx.tcx(), it.def_id),
25822582
t.unsafety.print_with_space(),
25832583
if t.is_auto { "auto " } else { "" },
25842584
it.name.as_ref().unwrap(),
@@ -2896,7 +2896,7 @@ fn assoc_const(
28962896
w,
28972897
"{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}",
28982898
extra,
2899-
it.visibility.print_with_space(cx.tcx()),
2899+
it.visibility.print_with_space(cx.tcx(), it.def_id),
29002900
naive_assoc_href(it, link),
29012901
it.name.as_ref().unwrap(),
29022902
ty.print()
@@ -3015,7 +3015,7 @@ fn render_assoc_item(
30153015
};
30163016
let mut header_len = format!(
30173017
"{}{}{}{}{}{:#}fn {}{:#}",
3018-
meth.visibility.print_with_space(cx.tcx()),
3018+
meth.visibility.print_with_space(cx.tcx(), meth.def_id),
30193019
header.constness.print_with_space(),
30203020
header.asyncness.print_with_space(),
30213021
header.unsafety.print_with_space(),
@@ -3037,7 +3037,7 @@ fn render_assoc_item(
30373037
"{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
30383038
{generics}{decl}{spotlight}{where_clause}",
30393039
if parent == ItemType::Trait { " " } else { "" },
3040-
meth.visibility.print_with_space(cx.tcx()),
3040+
meth.visibility.print_with_space(cx.tcx(), meth.def_id),
30413041
header.constness.print_with_space(),
30423042
header.asyncness.print_with_space(),
30433043
header.unsafety.print_with_space(),
@@ -3189,7 +3189,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
31893189
write!(
31903190
w,
31913191
"{}enum {}{}{}",
3192-
it.visibility.print_with_space(cx.tcx()),
3192+
it.visibility.print_with_space(cx.tcx(), it.def_id),
31933193
it.name.as_ref().unwrap(),
31943194
e.generics.print(),
31953195
WhereClause { gens: &e.generics, indent: 0, end_newline: true }
@@ -3365,7 +3365,7 @@ fn render_struct(
33653365
write!(
33663366
w,
33673367
"{}{}{}",
3368-
it.visibility.print_with_space(cx.tcx()),
3368+
it.visibility.print_with_space(cx.tcx(), it.def_id),
33693369
if structhead { "struct " } else { "" },
33703370
it.name.as_ref().unwrap()
33713371
);
@@ -3385,7 +3385,7 @@ fn render_struct(
33853385
w,
33863386
"\n{} {}{}: {},",
33873387
tab,
3388-
field.visibility.print_with_space(cx.tcx()),
3388+
field.visibility.print_with_space(cx.tcx(), field.def_id),
33893389
field.name.as_ref().unwrap(),
33903390
ty.print()
33913391
);
@@ -3414,7 +3414,12 @@ fn render_struct(
34143414
match *field.kind {
34153415
clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"),
34163416
clean::StructFieldItem(ref ty) => {
3417-
write!(w, "{}{}", field.visibility.print_with_space(cx.tcx()), ty.print())
3417+
write!(
3418+
w,
3419+
"{}{}",
3420+
field.visibility.print_with_space(cx.tcx(), field.def_id),
3421+
ty.print()
3422+
)
34183423
}
34193424
_ => unreachable!(),
34203425
}
@@ -3447,7 +3452,7 @@ fn render_union(
34473452
write!(
34483453
w,
34493454
"{}{}{}",
3450-
it.visibility.print_with_space(cx.tcx()),
3455+
it.visibility.print_with_space(cx.tcx(), it.def_id),
34513456
if structhead { "union " } else { "" },
34523457
it.name.as_ref().unwrap()
34533458
);
@@ -3462,7 +3467,7 @@ fn render_union(
34623467
write!(
34633468
w,
34643469
" {}{}: {},\n{}",
3465-
field.visibility.print_with_space(cx.tcx()),
3470+
field.visibility.print_with_space(cx.tcx(), field.def_id),
34663471
field.name.as_ref().unwrap(),
34673472
ty.print(),
34683473
tab
@@ -4101,7 +4106,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache:
41014106
write!(
41024107
w,
41034108
" {}type {};\n}}</pre>",
4104-
it.visibility.print_with_space(cx.tcx()),
4109+
it.visibility.print_with_space(cx.tcx(), it.def_id),
41054110
it.name.as_ref().unwrap(),
41064111
);
41074112

src/librustdoc/passes/collect_intra_doc_links.rs

+2-24
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use std::convert::{TryFrom, TryInto};
3131
use std::mem;
3232
use std::ops::Range;
3333

34-
use crate::clean::{self, Crate, Item, ItemLink, PrimitiveType};
34+
use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
3535
use crate::core::DocContext;
3636
use crate::fold::DocFolder;
3737
use crate::html::markdown::markdown_links;
@@ -830,31 +830,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
830830
use rustc_middle::ty::DefIdTree;
831831

832832
let parent_node = if item.is_fake() {
833-
// FIXME: is this correct?
834833
None
835-
// If we're documenting the crate root itself, it has no parent. Use the root instead.
836-
} else if item.def_id.is_top_level_module() {
837-
Some(item.def_id)
838834
} else {
839-
let mut current = item.def_id;
840-
// The immediate parent might not always be a module.
841-
// Find the first parent which is.
842-
loop {
843-
if let Some(parent) = self.cx.tcx.parent(current) {
844-
if self.cx.tcx.def_kind(parent) == DefKind::Mod {
845-
break Some(parent);
846-
}
847-
current = parent;
848-
} else {
849-
debug!(
850-
"{:?} has no parent (kind={:?}, original was {:?})",
851-
current,
852-
self.cx.tcx.def_kind(current),
853-
item.def_id
854-
);
855-
break None;
856-
}
857-
}
835+
find_nearest_parent_module(self.cx.tcx, item.def_id)
858836
};
859837

860838
if parent_node.is_some() {

src/test/rustdoc/pub-restricted.rs

-32
This file was deleted.

0 commit comments

Comments
 (0)