Skip to content

Commit

Permalink
[BROKEN] fix the regression from rust-lang#77820
Browse files Browse the repository at this point in the history
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.
```
  • Loading branch information
jyn514 committed Nov 15, 2020
1 parent b9f7690 commit b997e4f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 42 deletions.
66 changes: 33 additions & 33 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,7 @@ impl Clean<Item> for hir::StructField<'_> {
cx,
);
// Don't show `pub` for fields on enum variants; they are always public
Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
Item { visibility: hir_visibility(&self.vis, self.hir_id, cx), ..what_rustc_thinks }
}
}

Expand All @@ -1744,34 +1744,34 @@ impl Clean<Item> for ty::FieldDef {
cx,
);
// Don't show `pub` for fields on enum variants; they are always public
Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
}
}

impl Clean<Visibility> for hir::Visibility<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Visibility {
match self.node {
hir::VisibilityKind::Public => Visibility::Public,
hir::VisibilityKind::Inherited => Visibility::Inherited,
hir::VisibilityKind::Crate(_) => {
let krate = DefId::local(CRATE_DEF_INDEX);
Visibility::Restricted(krate, cx.tcx.def_path(krate))
}
hir::VisibilityKind::Restricted { ref path, .. } => {
let path = path.clean(cx);
let did = register_res(cx, path.res);
Visibility::Restricted(did, cx.tcx.def_path(did))
}
}
}
}

impl Clean<Visibility> for ty::Visibility {
fn clean(&self, cx: &DocContext<'_>) -> Visibility {
match *self {
ty::Visibility::Public => Visibility::Public,
ty::Visibility::Invisible => Visibility::Inherited,
ty::Visibility::Restricted(module) => {
let hir_id = self.did.as_local().map(|local| cx.tcx.hir().local_def_id_to_hir_id(local));
Item { visibility: ty_visibility(self.vis, hir_id, cx), ..what_rustc_thinks }
}
}

fn hir_visibility(
vis: &hir::Visibility<'_>,
hir_id: hir::HirId,
cx: &DocContext<'_>,
) -> Visibility {
// FIXME: I think this handles `Inherited` wrong
ty_visibility(ty::Visibility::from_hir(vis, hir_id, cx.tcx), Some(hir_id), cx)
}

fn ty_visibility(
vis: ty::Visibility,
hir_id: Option<hir::HirId>,
cx: &DocContext<'_>,
) -> Visibility {
match vis {
ty::Visibility::Public => Visibility::Public,
ty::Visibility::Invisible => Visibility::Inherited,
ty::Visibility::Restricted(module) => {
let hir_id = hir_id.unwrap_or_else(|| panic!("only local items can have restricted visibility (while calculating vis of {:?})", module));
let parent = cx.tcx.parent_module(hir_id).to_def_id();
if parent == module {
Visibility::RestrictSelf
} else {
Visibility::Restricted(module, cx.tcx.def_path(module))
}
}
Expand Down Expand Up @@ -2093,7 +2093,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
def_id: def_id.to_def_id(),
visibility: self.vis.clean(cx),
visibility: hir_visibility(self.vis, self.id, cx),
stability: cx.stability(self.id),
deprecation: cx.deprecation(self.id).clean(cx),
inner: ImplItem(Impl {
Expand Down Expand Up @@ -2149,7 +2149,7 @@ impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
visibility: self.vis.clean(cx),
visibility: hir_visibility(self.vis, self.hir_id, cx),
stability: None,
deprecation: None,
inner: ExternCrateItem(self.name.clean(cx), self.path.clone()),
Expand Down Expand Up @@ -2220,7 +2220,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx),
visibility: hir_visibility(self.vis, self.id, cx),
stability: None,
deprecation: None,
inner: ImportItem(Import::new_simple(
Expand All @@ -2240,7 +2240,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
def_id: DefId::local(CRATE_DEF_INDEX),
visibility: self.vis.clean(cx),
visibility: hir_visibility(self.vis, self.id, cx),
stability: None,
deprecation: None,
inner: ImportItem(inner),
Expand Down
12 changes: 11 additions & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,15 @@ impl Item {
hir.span_with_body(hir.local_def_id_to_hir_id(local))
},
);
let hir_id = def_id.as_local().map(|local| cx.tcx.hir().local_def_id_to_hir_id(local));

Item {
def_id,
inner,
name: name.clean(cx),
source: source.clean(cx),
attrs: cx.tcx.get_attrs(def_id).clean(cx),
visibility: cx.tcx.visibility(def_id).clean(cx),
visibility: super::ty_visibility(cx.tcx.visibility(def_id), hir_id, cx),
stability: cx.tcx.lookup_stability(def_id).cloned(),
deprecation: cx.tcx.lookup_deprecation(def_id).clean(cx),
}
Expand Down Expand Up @@ -1527,8 +1528,17 @@ impl From<hir::PrimTy> for PrimitiveType {

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

Expand Down
10 changes: 2 additions & 8 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,24 +1089,18 @@ impl Function<'_> {

impl clean::Visibility {
crate fn print_with_space(&self) -> impl fmt::Display + '_ {
use rustc_span::symbol::kw;

display_fn(move |f| match *self {
clean::Public => f.write_str("pub "),
clean::Inherited => Ok(()),
clean::Visibility::RestrictSelf => f.write_str("pub(self) "),
// If this is `pub(crate)`, `path` will be empty.
clean::Visibility::Restricted(did, _) if did.index == CRATE_DEF_INDEX => {
write!(f, "pub(crate) ")
}
clean::Visibility::Restricted(did, ref path) => {
f.write_str("pub(")?;
debug!("path={:?}", path);
let first_name =
path.data[0].data.get_opt_name().expect("modules are always named");
if path.data.len() != 1 || (first_name != kw::SelfLower && first_name != kw::Super)
{
f.write_str("in ")?;
}

// modified from `resolved_path()` to work with `DefPathData`
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
for seg in &path.data[..path.data.len() - 1] {
Expand Down

0 comments on commit b997e4f

Please sign in to comment.