Handle extern crates better, so they work correctly in 2015 edition
(see the removed comment.)
This commit is contained in:
parent
70839b7ef8
commit
92c595a6a6
@ -287,12 +287,18 @@ where
|
||||
) -> ReachedFixedPoint {
|
||||
log::debug!("resolving import: {:?} ({:?})", import, self.result.edition);
|
||||
let original_module = Module { krate: self.krate, module_id };
|
||||
let (def, reached_fixedpoint) = self.result.resolve_path_fp(
|
||||
self.db,
|
||||
ResolveMode::Import,
|
||||
original_module,
|
||||
&import.path,
|
||||
);
|
||||
|
||||
let (def, reached_fixedpoint) = if import.is_extern_crate {
|
||||
let res = self.result.resolve_name_in_extern_prelude(
|
||||
&import
|
||||
.path
|
||||
.as_ident()
|
||||
.expect("extern crate should have been desugared to one-element path"),
|
||||
);
|
||||
(res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes })
|
||||
} else {
|
||||
self.result.resolve_path_fp(self.db, ResolveMode::Import, original_module, &import.path)
|
||||
};
|
||||
|
||||
if reached_fixedpoint != ReachedFixedPoint::Yes {
|
||||
return reached_fixedpoint;
|
||||
@ -502,6 +508,10 @@ impl ItemMap {
|
||||
from_scope.or(from_extern_prelude).or(from_prelude)
|
||||
}
|
||||
|
||||
fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
|
||||
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
|
||||
}
|
||||
|
||||
fn resolve_name_in_crate_root_or_extern_prelude(
|
||||
&self,
|
||||
db: &impl PersistentHirDatabase,
|
||||
@ -511,8 +521,7 @@ impl ItemMap {
|
||||
let crate_root = module.crate_root(db);
|
||||
let from_crate_root =
|
||||
self[crate_root.module_id].items.get(name).map_or(PerNs::none(), |it| it.def);
|
||||
let from_extern_prelude =
|
||||
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
|
||||
let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
|
||||
|
||||
from_crate_root.or(from_extern_prelude)
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::{
|
||||
SourceItemId, Path, PathKind, ModuleSource, Name,
|
||||
SourceItemId, Path, ModuleSource, Name,
|
||||
HirFileId, MacroCallLoc, AsName, PerNs, Function,
|
||||
ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type,
|
||||
ids::LocationCtx, PersistentHirDatabase,
|
||||
@ -180,13 +180,8 @@ impl LoweredModule {
|
||||
self.add_use_item(source_map, it);
|
||||
}
|
||||
ast::ModuleItemKind::ExternCrateItem(it) => {
|
||||
// Lower `extern crate x` to `use ::x`. This is kind of cheating
|
||||
// and only works if we always interpret absolute paths in the
|
||||
// 2018 style; otherwise `::x` could also refer to a module in
|
||||
// the crate root.
|
||||
if let Some(name_ref) = it.name_ref() {
|
||||
let mut path = Path::from_name_ref(name_ref);
|
||||
path.kind = PathKind::Abs;
|
||||
let path = Path::from_name_ref(name_ref);
|
||||
let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name);
|
||||
self.imports.alloc(ImportData {
|
||||
path,
|
||||
|
@ -542,6 +542,42 @@ fn extern_crate_rename() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extern_crate_rename_2015_edition() {
|
||||
let mut db = MockDatabase::with_files(
|
||||
"
|
||||
//- /main.rs
|
||||
extern crate alloc as alloc_crate;
|
||||
|
||||
mod alloc;
|
||||
mod sync;
|
||||
|
||||
//- /sync.rs
|
||||
use alloc_crate::Arc;
|
||||
|
||||
//- /lib.rs
|
||||
struct Arc;
|
||||
",
|
||||
);
|
||||
db.set_crate_graph_from_fixture(crate_graph! {
|
||||
"main": ("/main.rs", "2015", ["alloc"]),
|
||||
"alloc": ("/lib.rs", []),
|
||||
});
|
||||
let sync_id = db.file_id_of("/sync.rs");
|
||||
|
||||
let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap();
|
||||
let krate = module.krate(&db).unwrap();
|
||||
let item_map = db.item_map(krate);
|
||||
|
||||
check_module_item_map(
|
||||
&item_map,
|
||||
module.module_id,
|
||||
"
|
||||
Arc: t v
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import_across_source_roots() {
|
||||
let mut db = MockDatabase::with_files(
|
||||
|
Loading…
x
Reference in New Issue
Block a user