Skip to content

Commit 92c595a

Browse files
committed
Handle extern crates better, so they work correctly in 2015 edition
(see the removed comment.)
1 parent 70839b7 commit 92c595a

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

crates/ra_hir/src/nameres.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,18 @@ where
287287
) -> ReachedFixedPoint {
288288
log::debug!("resolving import: {:?} ({:?})", import, self.result.edition);
289289
let original_module = Module { krate: self.krate, module_id };
290-
let (def, reached_fixedpoint) = self.result.resolve_path_fp(
291-
self.db,
292-
ResolveMode::Import,
293-
original_module,
294-
&import.path,
295-
);
290+
291+
let (def, reached_fixedpoint) = if import.is_extern_crate {
292+
let res = self.result.resolve_name_in_extern_prelude(
293+
&import
294+
.path
295+
.as_ident()
296+
.expect("extern crate should have been desugared to one-element path"),
297+
);
298+
(res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes })
299+
} else {
300+
self.result.resolve_path_fp(self.db, ResolveMode::Import, original_module, &import.path)
301+
};
296302

297303
if reached_fixedpoint != ReachedFixedPoint::Yes {
298304
return reached_fixedpoint;
@@ -502,6 +508,10 @@ impl ItemMap {
502508
from_scope.or(from_extern_prelude).or(from_prelude)
503509
}
504510

511+
fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
512+
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
513+
}
514+
505515
fn resolve_name_in_crate_root_or_extern_prelude(
506516
&self,
507517
db: &impl PersistentHirDatabase,
@@ -511,8 +521,7 @@ impl ItemMap {
511521
let crate_root = module.crate_root(db);
512522
let from_crate_root =
513523
self[crate_root.module_id].items.get(name).map_or(PerNs::none(), |it| it.def);
514-
let from_extern_prelude =
515-
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
524+
let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
516525

517526
from_crate_root.or(from_extern_prelude)
518527
}

crates/ra_hir/src/nameres/lower.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
88
use rustc_hash::FxHashMap;
99

1010
use crate::{
11-
SourceItemId, Path, PathKind, ModuleSource, Name,
11+
SourceItemId, Path, ModuleSource, Name,
1212
HirFileId, MacroCallLoc, AsName, PerNs, Function,
1313
ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type,
1414
ids::LocationCtx, PersistentHirDatabase,
@@ -180,13 +180,8 @@ impl LoweredModule {
180180
self.add_use_item(source_map, it);
181181
}
182182
ast::ModuleItemKind::ExternCrateItem(it) => {
183-
// Lower `extern crate x` to `use ::x`. This is kind of cheating
184-
// and only works if we always interpret absolute paths in the
185-
// 2018 style; otherwise `::x` could also refer to a module in
186-
// the crate root.
187183
if let Some(name_ref) = it.name_ref() {
188-
let mut path = Path::from_name_ref(name_ref);
189-
path.kind = PathKind::Abs;
184+
let path = Path::from_name_ref(name_ref);
190185
let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name);
191186
self.imports.alloc(ImportData {
192187
path,

crates/ra_hir/src/nameres/tests.rs

+36
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,42 @@ fn extern_crate_rename() {
542542
);
543543
}
544544

545+
#[test]
546+
fn extern_crate_rename_2015_edition() {
547+
let mut db = MockDatabase::with_files(
548+
"
549+
//- /main.rs
550+
extern crate alloc as alloc_crate;
551+
552+
mod alloc;
553+
mod sync;
554+
555+
//- /sync.rs
556+
use alloc_crate::Arc;
557+
558+
//- /lib.rs
559+
struct Arc;
560+
",
561+
);
562+
db.set_crate_graph_from_fixture(crate_graph! {
563+
"main": ("/main.rs", "2015", ["alloc"]),
564+
"alloc": ("/lib.rs", []),
565+
});
566+
let sync_id = db.file_id_of("/sync.rs");
567+
568+
let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap();
569+
let krate = module.krate(&db).unwrap();
570+
let item_map = db.item_map(krate);
571+
572+
check_module_item_map(
573+
&item_map,
574+
module.module_id,
575+
"
576+
Arc: t v
577+
",
578+
);
579+
}
580+
545581
#[test]
546582
fn import_across_source_roots() {
547583
let mut db = MockDatabase::with_files(

0 commit comments

Comments
 (0)