diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b2db09cbc8065..7abbaf97339c7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1285,6 +1285,33 @@ impl<'tcx> TyCtxt<'tcx> { ) } + /// Find the nearest parent module of a [`DefId`]. + /// This is different from [`TyCtxt::parent()`] because this returns + /// the nearest parent `mod`, whereas [`TyCtxt::parent()`] returns + /// the nearest module-like item (e.g., the enum that a variant belongs to). + /// + /// Returns `def_id` if it's the crate root. + /// + /// Note for users in rustdoc: **panics if the item it belongs to is fake** + /// (see `rustdoc::clean::types::Item::is_fake()`). + pub fn find_nearest_parent_module(self, def_id: DefId) -> Option { + if def_id.is_top_level_module() { + // The crate root has no parent. Use it as the root instead. + Some(def_id) + } else { + let mut current = def_id; + // The immediate parent might not always be a module. + // Find the first parent which is. + while let Some(parent) = self.parent(current) { + if self.def_kind(parent) == DefKind::Mod { + return Some(parent); + } + current = parent; + } + None + } + } + pub fn metadata_encoding_version(self) -> Vec { self.cstore.metadata_encoding_version().to_vec() } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 3b2f50db8c7c2..af3b31c3c0f37 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, Ty}; use rustc_span::symbol::{kw, sym, Symbol}; use std::mem; @@ -623,24 +623,3 @@ where *cx.impl_trait_bounds.borrow_mut() = old_bounds; r } - -/// Find the nearest parent module of a [`DefId`]. -/// -/// **Panics if the item it belongs to [is fake][Item::is_fake].** -crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if def_id.is_top_level_module() { - // The crate root has no parent. Use it as the root instead. - Some(def_id) - } else { - let mut current = def_id; - // The immediate parent might not always be a module. - // Find the first parent which is. - while let Some(parent) = tcx.parent(current) { - if tcx.def_kind(parent) == DefKind::Mod { - return Some(parent); - } - current = parent; - } - None - } -} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6eeb7ad82c0ac..d7d01b7faa031 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_target::spec::abi::Abi; -use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType}; +use crate::clean::{self, PrimitiveType}; use crate::formats::cache::cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; @@ -1100,7 +1100,7 @@ impl clean::Visibility { // FIXME(camelid): This may not work correctly if `item_did` is a module. // However, rustdoc currently never displays a module's // visibility, so it shouldn't matter. - let parent_module = find_nearest_parent_module(tcx, item_did); + let parent_module = tcx.find_nearest_parent_module(item_did); if vis_did.index == CRATE_DEF_INDEX { write!(f, "pub(crate) ") @@ -1109,7 +1109,7 @@ impl clean::Visibility { // is the same as no visibility modifier Ok(()) } else if parent_module - .map(|parent| find_nearest_parent_module(tcx, parent)) + .map(|parent| tcx.find_nearest_parent_module(parent)) .flatten() == Some(vis_did) { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0cefbb34791b2..ff777eb2a22d7 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -33,7 +33,7 @@ use std::convert::{TryFrom, TryInto}; use std::mem; use std::ops::Range; -use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType}; +use crate::clean::{self, Crate, Item, ItemLink, PrimitiveType}; use crate::core::DocContext; use crate::fold::DocFolder; use crate::html::markdown::{markdown_links, MarkdownLink}; @@ -832,11 +832,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { fn fold_item(&mut self, mut item: Item) -> Option { use rustc_middle::ty::DefIdTree; - let parent_node = if item.is_fake() { - None - } else { - find_nearest_parent_module(self.cx.tcx, item.def_id) - }; + let parent_node = + if item.is_fake() { None } else { self.cx.tcx.find_nearest_parent_module(item.def_id) }; if parent_node.is_some() { trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);