Skip to content

Commit

Permalink
Auto merge of #17251 - roife:fix-issue-17057, r=Veykril
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
bors committed May 22, 2024
2 parents 56ce7e0 + 4e9b128 commit 0916e72
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 6 deletions.
62 changes: 62 additions & 0 deletions src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
"#]],
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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)| {
Expand Down Expand Up @@ -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 {
Expand All @@ -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(
Expand Down

0 comments on commit 0916e72

Please sign in to comment.