From f135a8ea55c0a46c67713fb3b79b5f62ada430c1 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Thu, 12 Dec 2019 14:58:04 +0100
Subject: [PATCH] Move structs to new loc

---
 crates/ra_hir/src/code_model.rs            |  4 ++--
 crates/ra_hir/src/from_source.rs           |  6 ++++--
 crates/ra_hir/src/has_source.rs            |  2 +-
 crates/ra_hir_def/src/adt.rs               |  9 ++++----
 crates/ra_hir_def/src/attr.rs              |  2 +-
 crates/ra_hir_def/src/child_by_source.rs   | 12 +++++++++--
 crates/ra_hir_def/src/db.rs                |  6 +++---
 crates/ra_hir_def/src/docs.rs              |  2 +-
 crates/ra_hir_def/src/generics.rs          |  2 +-
 crates/ra_hir_def/src/keys.rs              |  5 +++--
 crates/ra_hir_def/src/lib.rs               | 24 ++++++++++++++++------
 crates/ra_hir_def/src/nameres/collector.rs |  7 ++++---
 crates/ra_hir_def/src/src.rs               | 13 +++++++++++-
 crates/ra_hir_ty/src/lower.rs              |  2 +-
 14 files changed, 66 insertions(+), 30 deletions(-)

diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 78c7792bf3e..8588aa5a3a7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -269,7 +269,7 @@ pub struct Struct {
 
 impl Struct {
     pub fn module(self, db: &impl DefDatabase) -> Module {
-        Module { id: self.id.module(db) }
+        Module { id: self.id.lookup(db).container }
     }
 
     pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -290,7 +290,7 @@ impl Struct {
     }
 
     pub fn ty(self, db: &impl HirDatabase) -> Type {
-        Type::from_def(db, self.id.module(db).krate, self.id)
+        Type::from_def(db, self.id.lookup(db).container.krate, self.id)
     }
 
     fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 091349d49db..978326c74ce 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -23,8 +23,10 @@ pub trait FromSource: Sized {
 impl FromSource for Struct {
     type Ast = ast::StructDef;
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Struct { id })
+        analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STRUCT]
+            .get(&src)
+            .copied()
+            .map(Struct::from)
     }
 }
 impl FromSource for Union {
diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs
index c4c6d66b756..8f35a3fbb4f 100644
--- a/crates/ra_hir/src/has_source.rs
+++ b/crates/ra_hir/src/has_source.rs
@@ -51,7 +51,7 @@ impl HasSource for StructField {
 impl HasSource for Struct {
     type Ast = ast::StructDef;
     fn source(self, db: &impl DefDatabase) -> InFile<ast::StructDef> {
-        self.id.source(db)
+        self.id.lookup(db).source(db)
     }
 }
 impl HasSource for Union {
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index db3e63ef828..ef2b20f1ec1 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -11,8 +11,9 @@ use ra_arena::{map::ArenaMap, Arena};
 use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
 
 use crate::{
-    db::DefDatabase, src::HasChildSource, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId,
-    LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId,
+    db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef,
+    AstItemDef, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId,
+    VariantId,
 };
 
 /// Note that we use `StructData` for unions as well!
@@ -50,7 +51,7 @@ pub struct StructFieldData {
 
 impl StructData {
     pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> {
-        let src = id.source(db);
+        let src = id.lookup(db).source(db);
         let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
         let variant_data = VariantData::new(src.value.kind());
         let variant_data = Arc::new(variant_data);
@@ -153,7 +154,7 @@ impl HasChildSource for VariantId {
                 let src = it.parent.child_source(db);
                 src.map(|map| map[it.local_id].kind())
             }
-            VariantId::StructId(it) => it.source(db).map(|it| it.kind()),
+            VariantId::StructId(it) => it.lookup(db).source(db).map(|it| it.kind()),
             VariantId::UnionId(it) => it.source(db).map(|it| {
                 it.record_field_def_list()
                     .map(ast::StructKind::Record)
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 3347d819c70..d2aa5ce8f16 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -56,7 +56,7 @@ impl Attrs {
                 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
             }
             AttrDefId::AdtId(it) => match it {
-                AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
+                AdtId::StructId(it) => attrs_from_loc(it.lookup(db), db),
                 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
                 AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
             },
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs
index 88c2d3f242d..eba361578b8 100644
--- a/crates/ra_hir_def/src/child_by_source.rs
+++ b/crates/ra_hir_def/src/child_by_source.rs
@@ -11,8 +11,8 @@ use crate::{
     dyn_map::DynMap,
     keys,
     src::{HasChildSource, HasSource},
-    AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, StructFieldId,
-    TraitId, VariantId,
+    AdtId, AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId,
+    StructFieldId, TraitId, VariantId,
 };
 
 pub trait ChildBySource {
@@ -98,6 +98,14 @@ impl ChildBySource for ModuleId {
                     let src = trait_.lookup(db).source(db);
                     res[keys::TRAIT].insert(src, trait_)
                 }
+                ModuleDefId::AdtId(adt) => match adt {
+                    AdtId::StructId(strukt) => {
+                        let src = strukt.lookup(db).source(db);
+                        res[keys::STRUCT].insert(src, strukt)
+                    }
+                    AdtId::UnionId(_) => (),
+                    AdtId::EnumId(_) => (),
+                },
                 _ => (),
             }
         }
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index f0c2ae559a5..e120c7768da 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -18,8 +18,8 @@ use crate::{
         CrateDefMap,
     },
     AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
-    ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TraitLoc,
-    TypeAliasId, TypeAliasLoc, UnionId,
+    ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId,
+    TraitLoc, TypeAliasId, TypeAliasLoc, UnionId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -27,7 +27,7 @@ pub trait InternDatabase: SourceDatabase {
     #[salsa::interned]
     fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
     #[salsa::interned]
-    fn intern_struct(&self, loc: ItemLoc<ast::StructDef>) -> StructId;
+    fn intern_struct(&self, loc: StructLoc) -> StructId;
     #[salsa::interned]
     fn intern_union(&self, loc: ItemLoc<ast::UnionDef>) -> UnionId;
     #[salsa::interned]
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 1921681fbd8..58143b894a5 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -51,7 +51,7 @@ impl Documentation {
                 }
             }
             AttrDefId::AdtId(it) => match it {
-                AdtId::StructId(it) => docs_from_ast(&it.source(db).value),
+                AdtId::StructId(it) => docs_from_ast(&it.lookup(db).source(db).value),
                 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
                 AdtId::UnionId(it) => docs_from_ast(&it.source(db).value),
             },
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index cbfc3ff0491..f1ce8d59a2c 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -71,7 +71,7 @@ impl GenericParams {
                 src.file_id
             }
             GenericDefId::AdtId(AdtId::StructId(it)) => {
-                let src = it.source(db);
+                let src = it.lookup(db).source(db);
                 generics.fill(&mut sm, &src.value);
                 src.file_id
             }
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs
index 6ec58f5f9a3..758cf80970b 100644
--- a/crates/ra_hir_def/src/keys.rs
+++ b/crates/ra_hir_def/src/keys.rs
@@ -8,8 +8,8 @@ use rustc_hash::FxHashMap;
 
 use crate::{
     dyn_map::{DynMap, Policy},
-    ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, TraitId, TypeAliasId,
-    TypeParamId,
+    ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId,
+    TypeAliasId, TypeParamId,
 };
 
 type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -20,6 +20,7 @@ pub const STATIC: Key<ast::StaticDef, StaticId> = Key::new();
 pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new();
 pub const IMPL: Key<ast::ImplBlock, ImplId> = Key::new();
 pub const TRAIT: Key<ast::TraitDef, TraitId> = Key::new();
+pub const STRUCT: Key<ast::StructDef, StructId> = Key::new();
 
 pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new();
 pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new();
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 0fcc2cde497..1a599706a7a 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -149,12 +149,24 @@ impl Lookup for FunctionId {
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct StructId(salsa::InternId);
 impl_intern_key!(StructId);
-impl AstItemDef<ast::StructDef> for StructId {
-    fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
-        db.intern_struct(loc)
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct StructLoc {
+    pub container: ModuleId,
+    pub ast_id: AstId<ast::StructDef>,
+}
+
+impl Intern for StructLoc {
+    type ID = StructId;
+    fn intern(self, db: &impl db::DefDatabase) -> StructId {
+        db.intern_struct(self)
     }
-    fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> {
-        db.lookup_intern_struct(self)
+}
+
+impl Lookup for StructId {
+    type Data = StructLoc;
+    fn lookup(&self, db: &impl db::DefDatabase) -> StructLoc {
+        db.lookup_intern_struct(*self)
     }
 }
 
@@ -532,7 +544,7 @@ impl HasModule for ConstLoc {
 impl HasModule for AdtId {
     fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
         match self {
-            AdtId::StructId(it) => it.module(db),
+            AdtId::StructId(it) => it.lookup(db).container,
             AdtId::UnionId(it) => it.module(db),
             AdtId::EnumId(it) => it.module(db),
         }
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index a7bdd620b42..602ec0911ca 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -25,7 +25,7 @@ use crate::{
     path::{Path, PathKind},
     per_ns::PerNs,
     AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplLoc,
-    Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
+    Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructLoc,
     TraitLoc, TypeAliasLoc, UnionId,
 };
 
@@ -773,8 +773,9 @@ where
                 PerNs::values(def.into())
             }
             raw::DefKind::Struct(ast_id) => {
-                let id = StructId::from_ast_id(ctx, ast_id).into();
-                PerNs::both(id, id)
+                let def = StructLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
+                    .intern(self.def_collector.db);
+                PerNs::both(def.into(), def.into())
             }
             raw::DefKind::Union(ast_id) => {
                 let id = UnionId::from_ast_id(ctx, ast_id).into();
diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs
index 858e4861eb6..7e212adb15c 100644
--- a/crates/ra_hir_def/src/src.rs
+++ b/crates/ra_hir_def/src/src.rs
@@ -4,7 +4,9 @@ use hir_expand::InFile;
 use ra_arena::map::ArenaMap;
 use ra_syntax::ast;
 
-use crate::{db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, TraitLoc, TypeAliasLoc};
+use crate::{
+    db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc,
+};
 
 pub trait HasSource {
     type Value;
@@ -65,6 +67,15 @@ impl HasSource for TraitLoc {
     }
 }
 
+impl HasSource for StructLoc {
+    type Value = ast::StructDef;
+
+    fn source(&self, db: &impl DefDatabase) -> InFile<ast::StructDef> {
+        let node = self.ast_id.to_node(db);
+        InFile::new(self.ast_id.file_id, node)
+    }
+}
+
 pub trait HasChildSource {
     type ChildId;
     type Value;
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index eab91229e3e..6af5bf50aa3 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -699,7 +699,7 @@ impl CallableDef {
     pub fn krate(self, db: &impl HirDatabase) -> CrateId {
         match self {
             CallableDef::FunctionId(f) => f.lookup(db).module(db).krate,
-            CallableDef::StructId(s) => s.module(db).krate,
+            CallableDef::StructId(s) => s.lookup(db).container.krate,
             CallableDef::EnumVariantId(e) => e.parent.module(db).krate,
         }
     }