diff options
| author | bors <bors@rust-lang.org> | 2024-05-22 20:11:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-05-22 20:11:24 +0000 |
| commit | 0916e72a347f3bb0fb8de70b94a057e3e6f389fc (patch) | |
| tree | efff7bb5d617749cb7c582df6d991121d7a98e13 | |
| parent | 56ce7e0e06cf2888e7b3d9d1f03ab353d9a3721b (diff) | |
| parent | 4e9b12870c705e72c0e85ae286f1b5738fc2a1d9 (diff) | |
| download | rust-0916e72a347f3bb0fb8de70b94a057e3e6f389fc.tar.gz rust-0916e72a347f3bb0fb8de70b94a057e3e6f389fc.zip | |
Auto merge of #17251 - roife:fix-issue-17057, r=Veykril
fix: resolve extern prelude for local mods in block modules fix https://github.com/rust-lang/rust-analyzer/issues/17057, https://github.com/rust-lang/rust-analyzer/issues/17032. We should use `ModuleOrigin` to check if the current module is a pseudo-module introduced by blocks (where names might be shadowed), rather than checking `block_def_map`.
3 files changed, 71 insertions, 6 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs index 985c6387ba0..f483efa8517 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs @@ -528,3 +528,65 @@ fn f() {$0 "#]], ) } + +#[test] +fn resolve_extern_prelude_in_block() { + check_at( + r#" +//- /main.rs crate:main deps:core +fn main() { + mod f { + use core::S; + $0 + } +} + +//- /core.rs crate:core +pub struct S; + "#, + expect![[r#" + block scope + f: t + + block scope::f + S: ti vi + + crate + main: v + "#]], + ) +} + +#[test] +fn shadow_extern_prelude_in_block() { + check_at( + r#" +//- /main.rs crate:main deps:core +fn main() { + mod core { pub struct S; } + { + fn inner() {} // forces a block def map + use core::S; // should resolve to the local one + $0 + } +} + +//- /core.rs crate:core +pub const S; + "#, + expect![[r#" + block scope + S: ti vi + inner: v + + block scope + core: t + + block scope::core + S: t v + + crate + main: v + "#]], + ) +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 262bc538b94..587997c4736 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -395,6 +395,8 @@ impl DefCollector<'_> { .cfg() .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)); if is_cfg_enabled { + self.inject_prelude(); + ModCollector { def_collector: self, macro_depth: 0, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index ee29b89f3d3..d621f3a360a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -221,7 +221,7 @@ impl DefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_crate_root_or_extern_prelude(db, segment) + self.resolve_name_in_crate_root_or_extern_prelude(db, original_module, segment) } PathKind::Plain => { let (_, segment) = match segments.next() { @@ -470,9 +470,9 @@ impl DefMap { }; let extern_prelude = || { - if self.block.is_some() { - // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so - // that blocks can properly shadow them + if self.block.is_some() && module == DefMap::ROOT { + // Don't resolve extern prelude in pseudo-modules of blocks, because + // they might been shadowed by local names. return PerNs::none(); } self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| { @@ -505,6 +505,7 @@ impl DefMap { fn resolve_name_in_crate_root_or_extern_prelude( &self, db: &dyn DefDatabase, + module: LocalModuleId, name: &Name, ) -> PerNs { let from_crate_root = match self.block { @@ -515,8 +516,8 @@ impl DefMap { None => self[Self::ROOT].scope.get(name), }; let from_extern_prelude = || { - if self.block.is_some() { - // Don't resolve extern prelude in block `DefMap`s. + if self.block.is_some() && module == DefMap::ROOT { + // Don't resolve extern prelude in pseudo-module of a block. return PerNs::none(); } self.data.extern_prelude.get(name).copied().map_or( |
