about summary refs log tree commit diff
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-10-25 18:43:37 +0900
committerGitHub <noreply@github.com>2020-10-25 18:43:37 +0900
commit569d29d55c240eea3ff35d0a16572c2b81dd40bf (patch)
treef62e6c36ea47b873ea3028796bb96bf4e20d59dd /compiler/rustc_resolve
parent3e0dd24a6c0812eedbb02182a75c352f8a7e184a (diff)
parent283053a742277f9b949facdfc5f4996f503f3c4e (diff)
downloadrust-569d29d55c240eea3ff35d0a16572c2b81dd40bf.tar.gz
rust-569d29d55c240eea3ff35d0a16572c2b81dd40bf.zip
Rollup merge of #77984 - Aaron1011:fix/macro-mod-weird-parent, r=petrochenkov
Compute proper module parent during resolution

Fixes #75982

The direct parent of a module may not be a module
(e.g. `const _: () =  { #[path = "foo.rs"] mod foo; };`).

To find the parent of a module for purposes of resolution, we need to
walk up the tree until we hit a module or a crate root.
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs48
1 files changed, 41 insertions, 7 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 02e31ade41f..feeea726f4c 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -95,6 +95,27 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    /// Walks up the tree of definitions starting at `def_id`,
+    /// stopping at the first `DefKind::Mod` encountered
+    fn nearest_mod_parent(&mut self, def_id: DefId) -> Module<'a> {
+        let def_key = self.cstore().def_key(def_id);
+
+        let mut parent_id = DefId {
+            krate: def_id.krate,
+            index: def_key.parent.expect("failed to get parent for module"),
+        };
+        // The immediate parent may not be a module
+        // (e.g. `const _: () =  { #[path = "foo.rs"] mod foo; };`)
+        // Walk up the tree until we hit a module or the crate root.
+        while parent_id.index != CRATE_DEF_INDEX
+            && self.cstore().def_kind(parent_id) != DefKind::Mod
+        {
+            let parent_def_key = self.cstore().def_key(parent_id);
+            parent_id.index = parent_def_key.parent.expect("failed to get parent for module");
+        }
+        self.get_module(parent_id)
+    }
+
     crate fn get_module(&mut self, def_id: DefId) -> Module<'a> {
         // If this is a local module, it will be in `module_map`, no need to recalculate it.
         if let Some(def_id) = def_id.as_local() {
@@ -116,11 +137,8 @@ impl<'a> Resolver<'a> {
                 .data
                 .get_opt_name()
                 .expect("given a DefId that wasn't a module");
-            // This unwrap is safe since we know this isn't the root
-            let parent = Some(self.get_module(DefId {
-                index: def_key.parent.expect("failed to get parent for module"),
-                ..def_id
-            }));
+
+            let parent = Some(self.nearest_mod_parent(def_id));
             (name, parent)
         };
 
@@ -145,8 +163,24 @@ impl<'a> Resolver<'a> {
         if let Some(id) = def_id.as_local() {
             self.local_macro_def_scopes[&id]
         } else {
-            let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
-            self.get_module(module_def_id)
+            // This is not entirely correct - a `macro_rules!` macro may occur
+            // inside a 'block' module:
+            //
+            // ```rust
+            // const _: () = {
+            // #[macro_export]
+            // macro_rules! my_macro {
+            //     () => {};
+            // }
+            // `
+            // We don't record this information for external crates, so
+            // the module we compute here will be the closest 'mod' item
+            // (not necesssarily the actual parent of the `macro_rules!`
+            // macro). `macro_rules!` macros can't use def-site hygiene,
+            // so this hopefully won't be a problem.
+            //
+            // See https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508
+            self.nearest_mod_parent(def_id)
         }
     }