Skip to content

Commit

Permalink
Rustdoc: Fix macros 2.0 and built-in derives being shown at the wrong…
Browse files Browse the repository at this point in the history
… path.

Fixes rust-lang#74355

The issue with the built-in derives may be related to:
rust-lang#55482 (comment)
  • Loading branch information
danielhenrymantilla committed Jan 6, 2021
1 parent 8fec6c7 commit 0bee802
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 5 deletions.
56 changes: 51 additions & 5 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,66 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}

crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
let mut module = self.visit_mod_contents(
let mut top_level_module = self.visit_mod_contents(
krate.item.span,
&Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
hir::CRATE_HIR_ID,
&krate.item.module,
None,
);
// Attach the crate's exported macros to the top-level module:
module.macros.extend(krate.exported_macros.iter().map(|def| (def, None)));
module.is_crate = true;
top_level_module.is_crate = true;
// Attach the crate's exported macros to the top-level module.
// In the case of macros 2.0 (`pub macro`), and for built-in `derive`s as well
// (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
// moving them back to their correct locations.
krate.exported_macros.iter().for_each(|def| {
macro_rules! try_some {($($body:tt)*) => ({
fn fn_once<R, F: FnOnce() -> R> (f: F) -> F { f }
fn_once(|| Some({ $($body)* }))()
})}
// In the case of dummy items, some of the following operations may fail. We propagate
// that within a `?`-capturing block, so as to fallback to the basic behavior.
let containing_module_of_def = try_some! {
// The `def` of a macro in `exported_macros` should correspond to either:
// - a `#[macro-export] macro_rules!` macro,
// - a built-in `derive` macro such as the ones in `::core`,
// - a `pub macro`.
// Only the last two need to be fixed, thus:
if def.ast.macro_rules {
return None;
}
let macro_parent_module = self.cx.tcx.def_path({
use rustc_middle::ty::DefIdTree;
self.cx
.tcx
/* Because of #77828 we cannot do the simpler:
.parent_module(def.hir_id).to_def_id()
// and instead have to do: */
.parent(self.cx.tcx.hir().local_def_id(def.hir_id).to_def_id())?
});
let mut cur_mod = &mut top_level_module;
for path_segment in macro_parent_module.data {
let path_segment = path_segment.to_string();
cur_mod = cur_mod.mods.iter_mut().find(|module| {
matches!(
module.name, Some(symbol)
if symbol.with(|mod_name| mod_name == path_segment)
)
})?;
}
cur_mod
};
if let Some(module) = containing_module_of_def {
&mut module.macros
} else {
&mut top_level_module.macros
}
.push(self.visit_local_macro(def, None));
});

self.cx.renderinfo.get_mut().exact_paths = self.exact_paths;

module
top_level_module
}

fn visit_mod_contents(
Expand Down
9 changes: 9 additions & 0 deletions src/test/rustdoc/macro_pub_in_module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! See issue #74355
#![crate_name = "krate"]
#![feature(decl_macro)]

// @has krate/some_module/macro.my_macro.html
pub mod some_module {
//
pub macro my_macro() {}
}

0 comments on commit 0bee802

Please sign in to comment.