about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>2021-01-05 15:07:40 +0100
committerDaniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>2021-01-06 15:13:39 +0100
commit255f107cacb8927e72798313d69fa83d2e752a20 (patch)
tree3d8cb26f3dc355ca2666327a26781a4809ca2d07
parentce3ecd612f2ac52770293201848de733c86dcaaa (diff)
downloadrust-255f107cacb8927e72798313d69fa83d2e752a20.tar.gz
rust-255f107cacb8927e72798313d69fa83d2e752a20.zip
Fix ICE on `pub macro`s defined within a non-module type namespace.
-rw-r--r--src/librustdoc/visit_ast.rs18
-rw-r--r--src/test/rustdoc/macro_pub_in_module.rs8
2 files changed, 21 insertions, 5 deletions
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 1e78a014048..2dc9c7bc758 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -93,6 +93,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             });
             // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
             // lookup the module by its name, by looking at each path segment one at a time.
+            // Once #80415 is merged, this whole `for` loop research can be replaced by that.
             let mut cur_mod = &mut top_level_module;
             for path_segment in macro_parent_module.data {
                 let path_segment_ty_ns = match path_segment.data {
@@ -106,11 +107,18 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                         continue 'exported_macros;
                     }
                 };
-                cur_mod = cur_mod
-                    .mods
-                    .iter_mut()
-                    .find(|module| module.name == Some(path_segment_ty_ns))
-                    .unwrap();
+                // The obtained name in the type namespace may belong to something that is not
+                // a `mod`ule (_e.g._, it could be an `enum` with a `pub macro` defined within
+                // the block used for a discriminant.
+                if let Some(child_mod) =
+                    cur_mod.mods.iter_mut().find(|module| module.name == Some(path_segment_ty_ns))
+                {
+                    cur_mod = child_mod;
+                } else {
+                    // If the macro's parent def path is not exclusively made of module
+                    // components, then it is not accessible (c.f. previous `continue`).
+                    continue 'exported_macros;
+                }
             }
             cur_mod.macros.push((def, None));
         }
diff --git a/src/test/rustdoc/macro_pub_in_module.rs b/src/test/rustdoc/macro_pub_in_module.rs
index 59e69625455..4fd85d68994 100644
--- a/src/test/rustdoc/macro_pub_in_module.rs
+++ b/src/test/rustdoc/macro_pub_in_module.rs
@@ -72,3 +72,11 @@ const __: () = {
 pub mod __ {
     // @!has krate/__/macro.in_both_const_and_mod.html
 }
+
+enum Enum {
+    Crazy = {
+        // @!has krate/macro.this_is_getting_weird.html;
+        pub macro this_is_getting_weird() {}
+        42
+    },
+}