Repository: rust-analyzer/rust-analyzer
Pull request #6024 (2020-09-17 13:27:26)

Give `ExternCrate` a `Name`, not a `ModPath`
Simplifies things

jonas-schievink: bors r+ :robot: 

Patch:
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index db3b4a985c..0fd91b9d01 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -491,7 +491,7 @@ pub struct Import {
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct ExternCrate {
-    pub path: ModPath,
+    pub name: Name,
     pub alias: Option<ImportAlias>,
     pub visibility: RawVisibilityId,
     /// Whether this is a `#[macro_use] extern crate ...`.
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index da62e1297c..54814f1414 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -503,7 +503,7 @@ impl Ctx {
         &mut self,
         extern_crate: &ast::ExternCrate,
     ) -> Option<FileItemTreeId<ExternCrate>> {
-        let path = ModPath::from_name_ref(&extern_crate.name_ref()?);
+        let name = extern_crate.name_ref()?.as_name();
         let alias = extern_crate.rename().map(|a| {
             a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
         });
@@ -512,7 +512,7 @@ impl Ctx {
         // FIXME: cfg_attr
         let is_macro_use = extern_crate.has_atom_attr("macro_use");
 
-        let res = ExternCrate { path, alias, visibility, is_macro_use, ast_id };
+        let res = ExternCrate { name, alias, visibility, is_macro_use, ast_id };
         Some(id(self.data().extern_crates.alloc(res)))
     }
 
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 8180081696..c1e1d53f67 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -3,6 +3,8 @@
 //! `DefCollector::collect` contains the fixed-point iteration loop which
 //! resolves imports and expands macros.
 
+use std::iter;
+
 use base_db::{CrateId, FileId, ProcMacroId};
 use cfg::CfgOptions;
 use hir_expand::InFile;
@@ -149,7 +151,7 @@ impl Import {
         let it = &tree[id.value];
         let visibility = &tree[it.visibility];
         Self {
-            path: it.path.clone(),
+            path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
             alias: it.alias.clone(),
             visibility: visibility.clone(),
             is_glob: false,
@@ -356,20 +358,15 @@ impl DefCollector<'_> {
     fn import_macros_from_extern_crate(
         &mut self,
         current_module_id: LocalModuleId,
-        import: &item_tree::ExternCrate,
+        extern_crate: &item_tree::ExternCrate,
     ) {
         log::debug!(
             "importing macros from extern crate: {:?} ({:?})",
-            import,
+            extern_crate,
             self.def_map.edition,
         );
 
-        let res = self.def_map.resolve_name_in_extern_prelude(
-            &import
-                .path
-                .as_ident()
-                .expect("extern crate should have been desugared to one-element path"),
-        );
+        let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name);
 
         if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
             mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@@ -802,7 +799,7 @@ impl DefCollector<'_> {
                 let item_tree = self.db.item_tree(krate.file_id);
                 let extern_crate = &item_tree[krate.value];
 
-                diagnosed_extern_crates.insert(extern_crate.path.segments[0].clone());
+                diagnosed_extern_crates.insert(extern_crate.name.clone());
 
                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
                     directive.module_id,
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 99395667de..734310458f 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -56,10 +56,6 @@ impl ModPath {
         ModPath { kind, segments }
     }
 
-    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
-        name_ref.as_name().into()
-    }
-
     /// Converts an `tt::Ident` into a single-identifier `Path`.
     pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
         ident.as_name().into()


Test patch:
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index 4d0a3b7e6c..1a806cda52 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -232,7 +232,7 @@ fn smoke() {
             #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }]
             Import { path: ModPath { kind: Plain, segments: [Name(Text("b"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: true, is_prelude: false, ast_id: FileAstId::<syntax::ast::generated::nodes::Use>(0), index: 1 }
             #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("ext_crate"))] }, input: None }]) }]
-            ExternCrate { path: ModPath { kind: Plain, segments: [Name(Text("krate"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<syntax::ast::generated::nodes::ExternCrate>(1) }
+            ExternCrate { name: Name(Text("krate")), alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<syntax::ast::generated::nodes::ExternCrate>(1) }
             #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }]
             Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<syntax::ast::generated::nodes::Trait>(2) }
             > #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }]