1
Fork 0

Auto merge of #96521 - petrochenkov:docrules, r=notriddle,GuillaumeGomez

rustdoc: Resolve doc links referring to `macro_rules` items

cc https://github.com/rust-lang/rust/issues/81633

UPD: the fallback to considering *all* `macro_rules` in the crate for unresolved names is not removed in this PR, it will be removed separately and will be run through crater.
This commit is contained in:
bors 2022-05-01 20:28:10 +00:00
commit 4dd8b420c0
11 changed files with 175 additions and 41 deletions

View file

@ -1267,13 +1267,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
self.insert_unused_macro(ident, def_id, item.id);
}
self.r.visibilities.insert(def_id, vis);
self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding(
let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding(
self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
parent_macro_rules_scope: parent_scope.macro_rules,
binding,
ident,
}),
))
));
self.r.macro_rules_scopes.insert(def_id, scope);
scope
} else {
let module = parent_scope.module;
let vis = match item.kind {

View file

@ -143,9 +143,9 @@ enum ScopeSet<'a> {
/// but not for late resolution yet.
#[derive(Clone, Copy, Debug)]
pub struct ParentScope<'a> {
module: Module<'a>,
pub module: Module<'a>,
expansion: LocalExpnId,
macro_rules: MacroRulesScopeRef<'a>,
pub macro_rules: MacroRulesScopeRef<'a>,
derives: &'a [ast::Path],
}
@ -990,6 +990,8 @@ pub struct Resolver<'a> {
/// `macro_rules` scopes *produced* by expanding the macro invocations,
/// include all the `macro_rules` items and other invocations generated by them.
output_macro_rules_scopes: FxHashMap<LocalExpnId, MacroRulesScopeRef<'a>>,
/// `macro_rules` scopes produced by `macro_rules` item definitions.
macro_rules_scopes: FxHashMap<LocalDefId, MacroRulesScopeRef<'a>>,
/// Helper attributes that are in scope for the given expansion.
helper_attrs: FxHashMap<LocalExpnId, Vec<Ident>>,
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
@ -1361,6 +1363,7 @@ impl<'a> Resolver<'a> {
non_macro_attr: Lrc::new(SyntaxExtension::non_macro_attr(session.edition())),
invocation_parent_scopes: Default::default(),
output_macro_rules_scopes: Default::default(),
macro_rules_scopes: Default::default(),
helper_attrs: Default::default(),
derive_data: Default::default(),
local_macro_def_scopes: FxHashMap::default(),
@ -1874,25 +1877,25 @@ impl<'a> Resolver<'a> {
&mut self,
path_str: &str,
ns: Namespace,
mut module_id: DefId,
mut parent_scope: ParentScope<'a>,
) -> Option<Res> {
let mut segments =
Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident));
if let Some(segment) = segments.first_mut() {
if segment.ident.name == kw::Crate {
// FIXME: `resolve_path` always resolves `crate` to the current crate root, but
// rustdoc wants it to resolve to the `module_id`'s crate root. This trick of
// rustdoc wants it to resolve to the `parent_scope`'s crate root. This trick of
// replacing `crate` with `self` and changing the current module should achieve
// the same effect.
segment.ident.name = kw::SelfLower;
module_id = module_id.krate.as_def_id();
parent_scope.module =
self.expect_module(parent_scope.module.def_id().krate.as_def_id());
} else if segment.ident.name == kw::Empty {
segment.ident.name = kw::PathRoot;
}
}
let module = self.expect_module(module_id);
match self.maybe_resolve_path(&segments, Some(ns), &ParentScope::module(module, self)) {
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
Some(path_res.base_res())
@ -1904,11 +1907,6 @@ impl<'a> Resolver<'a> {
}
}
// For rustdoc.
pub fn graph_root(&self) -> Module<'a> {
self.graph_root
}
// For rustdoc.
pub fn take_all_macro_rules(&mut self) -> FxHashMap<Symbol, Res> {
mem::take(&mut self.all_macro_rules)
@ -1924,6 +1922,11 @@ impl<'a> Resolver<'a> {
}
}
/// For rustdoc.
pub fn macro_rules_scope(&self, def_id: LocalDefId) -> MacroRulesScopeRef<'a> {
*self.macro_rules_scopes.get(&def_id).expect("not a `macro_rules` item")
}
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
#[inline]
pub fn opt_span(&self, def_id: DefId) -> Option<Span> {