diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2020-10-25 18:43:37 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-25 18:43:37 +0900 |
| commit | 569d29d55c240eea3ff35d0a16572c2b81dd40bf (patch) | |
| tree | f62e6c36ea47b873ea3028796bb96bf4e20d59dd /compiler/rustc_resolve | |
| parent | 3e0dd24a6c0812eedbb02182a75c352f8a7e184a (diff) | |
| parent | 283053a742277f9b949facdfc5f4996f503f3c4e (diff) | |
| download | rust-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.rs | 48 |
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) } } |
