mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
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`.
This commit is contained in:
commit
d4da3f925c
3 changed files with 71 additions and 6 deletions
|
@ -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
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue