Skip to content

Commit b997e4f

Browse files
committed
[BROKEN] fix the regression from rust-lang#77820
This currently breaks, see rust-lang#77820 (comment). ``` DEBUG rustdoc::clean::inline build_impl: impl Some(DefId(1:7424 ~ std[7f8a]::os::linux::fs::MetadataExt)) for Some(DefId(1:7039 ~ std[7f8a]::fs::Metadata)) DEBUG rustdoc::clean::types name=None, def_id=DefId(1:7442 ~ std[7f8a]::os::linux::fs::{impl#0}) thread 'rustc' panicked at 'only local items can have restricted visibility (while calculating vis of DefId(1:7420 ~ std[7f8a]::os::linux::fs))', src/librustdoc/clean/mod.rs:1762:51 ``` ``` stack backtrace: 0: rust_begin_unwind 1: std::panicking::begin_panic_fmt 2: rustdoc::clean::ty_visibility::{{closure}} 3: rustdoc::clean::ty_visibility 4: rustdoc::clean::types::Item::from_def_id_and_parts 5: rustdoc::clean::inline::build_impl 6: rustc_session::utils::<impl rustc_session::session::Session>::time 7: rustdoc::passes::collect_trait_impls::collect_trait_impls 8: rustc_session::utils::<impl rustc_session::session::Session>::time 9: rustdoc::core::run_global_ctxt 10: rustc_interface::passes::QueryContext::enter 11: rustc_session::utils::<impl rustc_session::session::Session>::time 12: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter 13: rustc_span::with_source_map 14: rustc_interface::interface::create_compiler_and_run 15: rustdoc::core::run_core 16: rustdoc::main_options 17: scoped_tls::ScopedKey<T>::set 18: rustc_span::with_session_globals note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. ```
1 parent b9f7690 commit b997e4f

File tree

3 files changed

+46
-42
lines changed

3 files changed

+46
-42
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ impl Clean<Item> for hir::StructField<'_> {
17311731
cx,
17321732
);
17331733
// Don't show `pub` for fields on enum variants; they are always public
1734-
Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
1734+
Item { visibility: hir_visibility(&self.vis, self.hir_id, cx), ..what_rustc_thinks }
17351735
}
17361736
}
17371737

@@ -1744,34 +1744,34 @@ impl Clean<Item> for ty::FieldDef {
17441744
cx,
17451745
);
17461746
// Don't show `pub` for fields on enum variants; they are always public
1747-
Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
1748-
}
1749-
}
1750-
1751-
impl Clean<Visibility> for hir::Visibility<'_> {
1752-
fn clean(&self, cx: &DocContext<'_>) -> Visibility {
1753-
match self.node {
1754-
hir::VisibilityKind::Public => Visibility::Public,
1755-
hir::VisibilityKind::Inherited => Visibility::Inherited,
1756-
hir::VisibilityKind::Crate(_) => {
1757-
let krate = DefId::local(CRATE_DEF_INDEX);
1758-
Visibility::Restricted(krate, cx.tcx.def_path(krate))
1759-
}
1760-
hir::VisibilityKind::Restricted { ref path, .. } => {
1761-
let path = path.clean(cx);
1762-
let did = register_res(cx, path.res);
1763-
Visibility::Restricted(did, cx.tcx.def_path(did))
1764-
}
1765-
}
1766-
}
1767-
}
1768-
1769-
impl Clean<Visibility> for ty::Visibility {
1770-
fn clean(&self, cx: &DocContext<'_>) -> Visibility {
1771-
match *self {
1772-
ty::Visibility::Public => Visibility::Public,
1773-
ty::Visibility::Invisible => Visibility::Inherited,
1774-
ty::Visibility::Restricted(module) => {
1747+
let hir_id = self.did.as_local().map(|local| cx.tcx.hir().local_def_id_to_hir_id(local));
1748+
Item { visibility: ty_visibility(self.vis, hir_id, cx), ..what_rustc_thinks }
1749+
}
1750+
}
1751+
1752+
fn hir_visibility(
1753+
vis: &hir::Visibility<'_>,
1754+
hir_id: hir::HirId,
1755+
cx: &DocContext<'_>,
1756+
) -> Visibility {
1757+
// FIXME: I think this handles `Inherited` wrong
1758+
ty_visibility(ty::Visibility::from_hir(vis, hir_id, cx.tcx), Some(hir_id), cx)
1759+
}
1760+
1761+
fn ty_visibility(
1762+
vis: ty::Visibility,
1763+
hir_id: Option<hir::HirId>,
1764+
cx: &DocContext<'_>,
1765+
) -> Visibility {
1766+
match vis {
1767+
ty::Visibility::Public => Visibility::Public,
1768+
ty::Visibility::Invisible => Visibility::Inherited,
1769+
ty::Visibility::Restricted(module) => {
1770+
let hir_id = hir_id.unwrap_or_else(|| panic!("only local items can have restricted visibility (while calculating vis of {:?})", module));
1771+
let parent = cx.tcx.parent_module(hir_id).to_def_id();
1772+
if parent == module {
1773+
Visibility::RestrictSelf
1774+
} else {
17751775
Visibility::Restricted(module, cx.tcx.def_path(module))
17761776
}
17771777
}
@@ -2093,7 +2093,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
20932093
attrs: self.attrs.clean(cx),
20942094
source: self.span.clean(cx),
20952095
def_id: def_id.to_def_id(),
2096-
visibility: self.vis.clean(cx),
2096+
visibility: hir_visibility(self.vis, self.id, cx),
20972097
stability: cx.stability(self.id),
20982098
deprecation: cx.deprecation(self.id).clean(cx),
20992099
inner: ImplItem(Impl {
@@ -2149,7 +2149,7 @@ impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
21492149
attrs: self.attrs.clean(cx),
21502150
source: self.span.clean(cx),
21512151
def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
2152-
visibility: self.vis.clean(cx),
2152+
visibility: hir_visibility(self.vis, self.hir_id, cx),
21532153
stability: None,
21542154
deprecation: None,
21552155
inner: ExternCrateItem(self.name.clean(cx), self.path.clone()),
@@ -2220,7 +2220,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
22202220
attrs: self.attrs.clean(cx),
22212221
source: self.span.clean(cx),
22222222
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
2223-
visibility: self.vis.clean(cx),
2223+
visibility: hir_visibility(self.vis, self.id, cx),
22242224
stability: None,
22252225
deprecation: None,
22262226
inner: ImportItem(Import::new_simple(
@@ -2240,7 +2240,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
22402240
attrs: self.attrs.clean(cx),
22412241
source: self.span.clean(cx),
22422242
def_id: DefId::local(CRATE_DEF_INDEX),
2243-
visibility: self.vis.clean(cx),
2243+
visibility: hir_visibility(self.vis, self.id, cx),
22442244
stability: None,
22452245
deprecation: None,
22462246
inner: ImportItem(inner),

src/librustdoc/clean/types.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,15 @@ impl Item {
142142
hir.span_with_body(hir.local_def_id_to_hir_id(local))
143143
},
144144
);
145+
let hir_id = def_id.as_local().map(|local| cx.tcx.hir().local_def_id_to_hir_id(local));
145146

146147
Item {
147148
def_id,
148149
inner,
149150
name: name.clean(cx),
150151
source: source.clean(cx),
151152
attrs: cx.tcx.get_attrs(def_id).clean(cx),
152-
visibility: cx.tcx.visibility(def_id).clean(cx),
153+
visibility: super::ty_visibility(cx.tcx.visibility(def_id), hir_id, cx),
153154
stability: cx.tcx.lookup_stability(def_id).cloned(),
154155
deprecation: cx.tcx.lookup_deprecation(def_id).clean(cx),
155156
}
@@ -1527,8 +1528,17 @@ impl From<hir::PrimTy> for PrimitiveType {
15271528

15281529
#[derive(Clone, Debug)]
15291530
pub enum Visibility {
1531+
/// `pub`
15301532
Public,
1533+
/// Usually means private, but for enum variants it instead means 'always public'.
15311534
Inherited,
1535+
/// `pub(self)`
1536+
///
1537+
/// This has to be calculated ahead of time because `html` doesn't have access to a `tcx`.
1538+
/// Even if it did, `print_with_space` doesn't know the original item this was attached to
1539+
/// and so can't calculate whether the `DefPath` is `self` or not.
1540+
RestrictSelf,
1541+
/// `pub(in path)`
15321542
Restricted(DefId, rustc_hir::definitions::DefPath),
15331543
}
15341544

src/librustdoc/html/format.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,24 +1089,18 @@ impl Function<'_> {
10891089

10901090
impl clean::Visibility {
10911091
crate fn print_with_space(&self) -> impl fmt::Display + '_ {
1092-
use rustc_span::symbol::kw;
1093-
10941092
display_fn(move |f| match *self {
10951093
clean::Public => f.write_str("pub "),
10961094
clean::Inherited => Ok(()),
1095+
clean::Visibility::RestrictSelf => f.write_str("pub(self) "),
10971096
// If this is `pub(crate)`, `path` will be empty.
10981097
clean::Visibility::Restricted(did, _) if did.index == CRATE_DEF_INDEX => {
10991098
write!(f, "pub(crate) ")
11001099
}
11011100
clean::Visibility::Restricted(did, ref path) => {
11021101
f.write_str("pub(")?;
11031102
debug!("path={:?}", path);
1104-
let first_name =
1105-
path.data[0].data.get_opt_name().expect("modules are always named");
1106-
if path.data.len() != 1 || (first_name != kw::SelfLower && first_name != kw::Super)
1107-
{
1108-
f.write_str("in ")?;
1109-
}
1103+
11101104
// modified from `resolved_path()` to work with `DefPathData`
11111105
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
11121106
for seg in &path.data[..path.data.len() - 1] {

0 commit comments

Comments
 (0)