Unnamed repository; edit this file 'description' to name the repository.
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`.
bors 2024-05-23
parent 870ad35 · parent d9cc159 · commit d4da3f9
-rw-r--r--crates/hir-def/src/body/tests/block.rs62
-rw-r--r--crates/hir-def/src/nameres/collector.rs2
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs13
3 files changed, 71 insertions, 6 deletions
diff --git a/crates/hir-def/src/body/tests/block.rs b/crates/hir-def/src/body/tests/block.rs
index 985c6387ba..f483efa851 100644
--- a/crates/hir-def/src/body/tests/block.rs
+++ b/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/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 262bc538b9..587997c473 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/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/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index ee29b89f3d..d621f3a360 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/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(