Skip to content

Commit 0916e72

Browse files
committed
Auto merge of #17251 - roife:fix-issue-17057, r=Veykril
fix: resolve extern prelude for local mods in block modules fix rust-lang/rust-analyzer#17057, rust-lang/rust-analyzer#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`.
2 parents 56ce7e0 + 4e9b128 commit 0916e72

File tree

3 files changed

+71
-6
lines changed

3 files changed

+71
-6
lines changed

src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs

+62
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,65 @@ fn f() {$0
528528
"#]],
529529
)
530530
}
531+
532+
#[test]
533+
fn resolve_extern_prelude_in_block() {
534+
check_at(
535+
r#"
536+
//- /main.rs crate:main deps:core
537+
fn main() {
538+
mod f {
539+
use core::S;
540+
$0
541+
}
542+
}
543+
544+
//- /core.rs crate:core
545+
pub struct S;
546+
"#,
547+
expect![[r#"
548+
block scope
549+
f: t
550+
551+
block scope::f
552+
S: ti vi
553+
554+
crate
555+
main: v
556+
"#]],
557+
)
558+
}
559+
560+
#[test]
561+
fn shadow_extern_prelude_in_block() {
562+
check_at(
563+
r#"
564+
//- /main.rs crate:main deps:core
565+
fn main() {
566+
mod core { pub struct S; }
567+
{
568+
fn inner() {} // forces a block def map
569+
use core::S; // should resolve to the local one
570+
$0
571+
}
572+
}
573+
574+
//- /core.rs crate:core
575+
pub const S;
576+
"#,
577+
expect![[r#"
578+
block scope
579+
S: ti vi
580+
inner: v
581+
582+
block scope
583+
core: t
584+
585+
block scope::core
586+
S: t v
587+
588+
crate
589+
main: v
590+
"#]],
591+
)
592+
}

src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs

+2
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ impl DefCollector<'_> {
395395
.cfg()
396396
.map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
397397
if is_cfg_enabled {
398+
self.inject_prelude();
399+
398400
ModCollector {
399401
def_collector: self,
400402
macro_depth: 0,

src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ impl DefMap {
221221
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
222222
};
223223
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
224-
self.resolve_name_in_crate_root_or_extern_prelude(db, segment)
224+
self.resolve_name_in_crate_root_or_extern_prelude(db, original_module, segment)
225225
}
226226
PathKind::Plain => {
227227
let (_, segment) = match segments.next() {
@@ -470,9 +470,9 @@ impl DefMap {
470470
};
471471

472472
let extern_prelude = || {
473-
if self.block.is_some() {
474-
// Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so
475-
// that blocks can properly shadow them
473+
if self.block.is_some() && module == DefMap::ROOT {
474+
// Don't resolve extern prelude in pseudo-modules of blocks, because
475+
// they might been shadowed by local names.
476476
return PerNs::none();
477477
}
478478
self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
@@ -505,6 +505,7 @@ impl DefMap {
505505
fn resolve_name_in_crate_root_or_extern_prelude(
506506
&self,
507507
db: &dyn DefDatabase,
508+
module: LocalModuleId,
508509
name: &Name,
509510
) -> PerNs {
510511
let from_crate_root = match self.block {
@@ -515,8 +516,8 @@ impl DefMap {
515516
None => self[Self::ROOT].scope.get(name),
516517
};
517518
let from_extern_prelude = || {
518-
if self.block.is_some() {
519-
// Don't resolve extern prelude in block `DefMap`s.
519+
if self.block.is_some() && module == DefMap::ROOT {
520+
// Don't resolve extern prelude in pseudo-module of a block.
520521
return PerNs::none();
521522
}
522523
self.data.extern_prelude.get(name).copied().map_or(

0 commit comments

Comments
 (0)