8447: Resolve prelude and crate root names in the root DefMap r=jonas-schievink a=jonas-schievink

Should fix https://github.com/rust-analyzer/rust-analyzer/issues/8418

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-04-09 13:30:12 +00:00 committed by GitHub
commit c08e690c93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 7 deletions

View File

@ -478,7 +478,7 @@ impl DefCollector<'_> {
self.def_map.edition, self.def_map.edition,
); );
let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@ -534,6 +534,7 @@ impl DefCollector<'_> {
log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
if import.is_extern_crate { if import.is_extern_crate {
let res = self.def_map.resolve_name_in_extern_prelude( let res = self.def_map.resolve_name_in_extern_prelude(
self.db,
&import &import
.path .path
.as_ident() .as_ident()

View File

@ -60,12 +60,26 @@ impl ResolvePathResult {
} }
impl DefMap { impl DefMap {
pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { pub(super) fn resolve_name_in_extern_prelude(
&self,
db: &dyn DefDatabase,
name: &Name,
) -> PerNs {
if name == &name!(self) { if name == &name!(self) {
cov_mark::hit!(extern_crate_self_as); cov_mark::hit!(extern_crate_self_as);
return PerNs::types(self.module_id(self.root).into(), Visibility::Public); return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
} }
self.extern_prelude
let arc;
let root = match self.block {
Some(_) => {
arc = self.crate_root(db).def_map(db);
&*arc
}
None => self,
};
root.extern_prelude
.get(name) .get(name)
.map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
} }
@ -191,7 +205,7 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
}; };
log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
self.resolve_name_in_crate_root_or_extern_prelude(&segment) self.resolve_name_in_crate_root_or_extern_prelude(db, &segment)
} }
PathKind::Plain => { PathKind::Plain => {
let (_, segment) = match segments.next() { let (_, segment) = match segments.next() {
@ -394,9 +408,21 @@ impl DefMap {
from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude)
} }
fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { fn resolve_name_in_crate_root_or_extern_prelude(
let from_crate_root = self[self.root].scope.get(name); &self,
let from_extern_prelude = self.resolve_name_in_extern_prelude(name); db: &dyn DefDatabase,
name: &Name,
) -> PerNs {
let arc;
let crate_def_map = match self.block {
Some(_) => {
arc = self.crate_root(db).def_map(db);
&arc
}
None => self,
};
let from_crate_root = crate_def_map[crate_def_map.root].scope.get(name);
let from_extern_prelude = self.resolve_name_in_extern_prelude(db, name);
from_crate_root.or(from_extern_prelude) from_crate_root.or(from_extern_prelude)
} }

View File

@ -3413,3 +3413,33 @@ fn foo() {
"#]], "#]],
); );
} }
#[test]
fn renamed_extern_crate_in_block() {
check_types(
r#"
//- /lib.rs crate:lib deps:serde
use serde::Deserialize;
struct Foo {}
const _ : () = {
extern crate serde as _serde;
impl _serde::Deserialize for Foo {
fn deserialize() -> u8 { 0 }
}
};
fn foo() {
Foo::deserialize();
//^^^^^^^^^^^^^^^^^^ u8
}
//- /serde.rs crate:serde
pub trait Deserialize {
fn deserialize() -> u8;
}
"#,
);
}