Skip to content

fix: resolve extern prelude for local mods in block modules #17251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions 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
"#]],
)
}
2 changes: 2 additions & 0 deletions crates/hir-def/src/nameres/collector.rs
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
13 changes: 7 additions & 6 deletions crates/hir-def/src/nameres/path_resolution.rs
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