Skip to content

Commit 044e45c

Browse files
committed
rustdoc: Keep full ParentScope during early doc link resolution
1 parent 921f63f commit 044e45c

File tree

3 files changed

+36
-30
lines changed

3 files changed

+36
-30
lines changed

compiler/rustc_resolve/src/lib.rs

+6-11
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ enum ScopeSet<'a> {
143143
/// but not for late resolution yet.
144144
#[derive(Clone, Copy, Debug)]
145145
pub struct ParentScope<'a> {
146-
module: Module<'a>,
146+
pub module: Module<'a>,
147147
expansion: LocalExpnId,
148148
macro_rules: MacroRulesScopeRef<'a>,
149149
derives: &'a [ast::Path],
@@ -1874,25 +1874,25 @@ impl<'a> Resolver<'a> {
18741874
&mut self,
18751875
path_str: &str,
18761876
ns: Namespace,
1877-
mut module_id: DefId,
1877+
mut parent_scope: ParentScope<'a>,
18781878
) -> Option<Res> {
18791879
let mut segments =
18801880
Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident));
18811881
if let Some(segment) = segments.first_mut() {
18821882
if segment.ident.name == kw::Crate {
18831883
// FIXME: `resolve_path` always resolves `crate` to the current crate root, but
1884-
// rustdoc wants it to resolve to the `module_id`'s crate root. This trick of
1884+
// rustdoc wants it to resolve to the `parent_scope`'s crate root. This trick of
18851885
// replacing `crate` with `self` and changing the current module should achieve
18861886
// the same effect.
18871887
segment.ident.name = kw::SelfLower;
1888-
module_id = module_id.krate.as_def_id();
1888+
parent_scope.module =
1889+
self.expect_module(parent_scope.module.def_id().krate.as_def_id());
18891890
} else if segment.ident.name == kw::Empty {
18901891
segment.ident.name = kw::PathRoot;
18911892
}
18921893
}
18931894

1894-
let module = self.expect_module(module_id);
1895-
match self.maybe_resolve_path(&segments, Some(ns), &ParentScope::module(module, self)) {
1895+
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) {
18961896
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
18971897
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
18981898
Some(path_res.base_res())
@@ -1904,11 +1904,6 @@ impl<'a> Resolver<'a> {
19041904
}
19051905
}
19061906

1907-
// For rustdoc.
1908-
pub fn graph_root(&self) -> Module<'a> {
1909-
self.graph_root
1910-
}
1911-
19121907
// For rustdoc.
19131908
pub fn take_all_macro_rules(&mut self) -> FxHashMap<Symbol, Res> {
19141909
mem::take(&mut self.all_macro_rules)

src/librustdoc/passes/collect_intra_doc_links.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
1212
use rustc_hir::Mutability;
1313
use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
1414
use rustc_middle::{bug, span_bug, ty};
15+
use rustc_resolve::ParentScope;
1516
use rustc_session::lint::Lint;
1617
use rustc_span::hygiene::MacroKind;
1718
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -564,7 +565,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
564565
.copied()
565566
.unwrap_or_else(|| {
566567
self.cx.enter_resolver(|resolver| {
567-
resolver.resolve_rustdoc_path(path_str, ns, module_id)
568+
let parent_scope =
569+
ParentScope::module(resolver.expect_module(module_id), resolver);
570+
resolver.resolve_rustdoc_path(path_str, ns, parent_scope)
568571
})
569572
})
570573
.and_then(|res| res.try_into().ok())

src/librustdoc/passes/collect_intra_doc_links/early.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_ast_lowering::ResolverAstLowering;
99
use rustc_data_structures::fx::FxHashMap;
1010
use rustc_hir::def::Namespace::*;
1111
use rustc_hir::def::{DefKind, Namespace, Res};
12-
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, CRATE_DEF_ID};
12+
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, CRATE_DEF_ID};
1313
use rustc_hir::TraitCandidate;
1414
use rustc_middle::ty::{DefIdTree, Visibility};
1515
use rustc_resolve::{ParentScope, Resolver};
@@ -27,10 +27,12 @@ crate fn early_resolve_intra_doc_links(
2727
externs: Externs,
2828
document_private_items: bool,
2929
) -> ResolverCaches {
30+
let parent_scope =
31+
ParentScope::module(resolver.expect_module(CRATE_DEF_ID.to_def_id()), resolver);
3032
let mut link_resolver = EarlyDocLinkResolver {
3133
resolver,
3234
sess,
33-
current_mod: CRATE_DEF_ID,
35+
parent_scope,
3436
visited_mods: Default::default(),
3537
markdown_links: Default::default(),
3638
doc_link_resolutions: Default::default(),
@@ -52,7 +54,7 @@ crate fn early_resolve_intra_doc_links(
5254
// DO NOT REMOVE THIS without first testing on the reproducer in
5355
// https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb
5456
for (extern_name, _) in externs.iter().filter(|(_, entry)| entry.add_prelude) {
55-
link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, CRATE_DEF_ID.to_def_id());
57+
link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, parent_scope);
5658
}
5759

5860
ResolverCaches {
@@ -72,7 +74,7 @@ fn doc_attrs<'a>(attrs: impl Iterator<Item = &'a ast::Attribute>) -> Attributes
7274
struct EarlyDocLinkResolver<'r, 'ra> {
7375
resolver: &'r mut Resolver<'ra>,
7476
sess: &'r Session,
75-
current_mod: LocalDefId,
77+
parent_scope: ParentScope<'ra>,
7678
visited_mods: DefIdSet,
7779
markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
7880
doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
@@ -82,7 +84,7 @@ struct EarlyDocLinkResolver<'r, 'ra> {
8284
document_private_items: bool,
8385
}
8486

85-
impl EarlyDocLinkResolver<'_, '_> {
87+
impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
8688
fn add_traits_in_scope(&mut self, def_id: DefId) {
8789
// Calls to `traits_in_scope` are expensive, so try to avoid them if only possible.
8890
// Keys in the `traits_in_scope` cache are always module IDs.
@@ -205,20 +207,24 @@ impl EarlyDocLinkResolver<'_, '_> {
205207
if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
206208
return;
207209
}
208-
let module_id = self.current_mod.to_def_id();
209-
self.resolve_doc_links(doc_attrs(attrs.iter()), module_id);
210+
self.resolve_doc_links(doc_attrs(attrs.iter()), self.parent_scope);
210211
}
211212

212-
fn resolve_and_cache(&mut self, path_str: &str, ns: Namespace, module_id: DefId) -> bool {
213+
fn resolve_and_cache(
214+
&mut self,
215+
path_str: &str,
216+
ns: Namespace,
217+
parent_scope: &ParentScope<'ra>,
218+
) -> bool {
213219
self.doc_link_resolutions
214-
.entry((Symbol::intern(path_str), ns, module_id))
215-
.or_insert_with_key(|(path, ns, module_id)| {
216-
self.resolver.resolve_rustdoc_path(path.as_str(), *ns, *module_id)
220+
.entry((Symbol::intern(path_str), ns, parent_scope.module.def_id()))
221+
.or_insert_with_key(|(path, ns, _)| {
222+
self.resolver.resolve_rustdoc_path(path.as_str(), *ns, *parent_scope)
217223
})
218224
.is_some()
219225
}
220226

221-
fn resolve_doc_links(&mut self, attrs: Attributes, module_id: DefId) {
227+
fn resolve_doc_links(&mut self, attrs: Attributes, parent_scope: ParentScope<'ra>) {
222228
let mut need_traits_in_scope = false;
223229
for (doc_module, doc) in attrs.prepare_to_doc_link_resolution() {
224230
assert_eq!(doc_module, None);
@@ -230,7 +236,7 @@ impl EarlyDocLinkResolver<'_, '_> {
230236
// The logic here is a conservative approximation for path resolution in
231237
// `resolve_with_disambiguator`.
232238
if let Some(ns) = pinfo.disambiguator.map(Disambiguator::ns) {
233-
if self.resolve_and_cache(&pinfo.path_str, ns, module_id) {
239+
if self.resolve_and_cache(&pinfo.path_str, ns, &parent_scope) {
234240
continue;
235241
}
236242
}
@@ -239,7 +245,7 @@ impl EarlyDocLinkResolver<'_, '_> {
239245
let mut any_resolved = false;
240246
let mut need_assoc = false;
241247
for ns in [TypeNS, ValueNS, MacroNS] {
242-
if self.resolve_and_cache(&pinfo.path_str, ns, module_id) {
248+
if self.resolve_and_cache(&pinfo.path_str, ns, &parent_scope) {
243249
any_resolved = true;
244250
} else if ns != MacroNS {
245251
need_assoc = true;
@@ -256,7 +262,7 @@ impl EarlyDocLinkResolver<'_, '_> {
256262
}
257263

258264
if need_traits_in_scope {
259-
self.add_traits_in_scope(module_id);
265+
self.add_traits_in_scope(parent_scope.module.def_id());
260266
}
261267
}
262268

@@ -298,11 +304,13 @@ impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
298304
fn visit_item(&mut self, item: &ast::Item) {
299305
self.resolve_doc_links_local(&item.attrs); // Outer attribute scope
300306
if let ItemKind::Mod(..) = item.kind {
301-
let old_mod = mem::replace(&mut self.current_mod, self.resolver.local_def_id(item.id));
307+
let module_def_id = self.resolver.local_def_id(item.id).to_def_id();
308+
let module = self.resolver.expect_module(module_def_id);
309+
let old_module = mem::replace(&mut self.parent_scope.module, module);
302310
self.resolve_doc_links_local(&item.attrs); // Inner attribute scope
303-
self.process_module_children_or_reexports(self.current_mod.to_def_id());
311+
self.process_module_children_or_reexports(module_def_id);
304312
visit::walk_item(self, item);
305-
self.current_mod = old_mod;
313+
self.parent_scope.module = old_module;
306314
} else {
307315
match item.kind {
308316
ItemKind::Trait(..) => {

0 commit comments

Comments
 (0)