Repository: rust-analyzer/rust-analyzer
Pull request #2327 (2019-11-20 15:44:59)

Move constants to new ID


Patch:
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index c49190a0f0..920899dceb 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -12,7 +12,7 @@ use hir_def::{
     builtin_type::BuiltinType,
     traits::TraitData,
     type_ref::{Mutability, TypeRef},
-    AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId,
+    AssocItemId, ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId,
     LocalStructFieldId, Lookup, ModuleId, UnionId,
 };
 use hir_expand::{
@@ -697,9 +697,9 @@ impl Function {
 
     pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
         match self.id.lookup(db).container {
-            FunctionContainerId::TraitId(it) => Some(Container::Trait(it.into())),
-            FunctionContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
-            FunctionContainerId::ModuleId(_) => None,
+            ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
+            ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
+            ContainerId::ModuleId(_) => None,
         }
     }
 
@@ -729,7 +729,7 @@ pub struct Const {
 
 impl Const {
     pub fn module(self, db: &impl DefDatabase) -> Module {
-        Module { id: self.id.module(db) }
+        Module { id: self.id.lookup(db).module(db) }
     }
 
     pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -748,22 +748,27 @@ impl Const {
         db.infer(self.into())
     }
 
-    /// The containing impl block, if this is a method.
+    /// The containing impl block, if this is a type alias.
     pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
-        ImplBlock::containing(db, self.into())
+        match self.container(db) {
+            Some(Container::ImplBlock(it)) => Some(it),
+            _ => None,
+        }
     }
 
+    /// The containing trait, if this is a trait type alias definition.
     pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
-        db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from)
+        match self.container(db) {
+            Some(Container::Trait(it)) => Some(it),
+            _ => None,
+        }
     }
 
     pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
-        if let Some(impl_block) = self.impl_block(db) {
-            Some(impl_block.into())
-        } else if let Some(trait_) = self.parent_trait(db) {
-            Some(trait_.into())
-        } else {
-            None
+        match self.id.lookup(db).container {
+            ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
+            ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
+            ContainerId::ModuleId(_) => None,
         }
     }
 
@@ -954,30 +959,34 @@ pub struct TypeAlias {
 
 impl TypeAlias {
     pub fn module(self, db: &impl DefDatabase) -> Module {
-        Module { id: self.id.module(db) }
+        Module { id: self.id.lookup(db).module(db) }
     }
 
     pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
         Some(self.module(db).krate())
     }
 
-    /// The containing impl block, if this is a method.
+    /// The containing impl block, if this is a type alias.
     pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
-        ImplBlock::containing(db, self.into())
+        match self.container(db) {
+            Some(Container::ImplBlock(it)) => Some(it),
+            _ => None,
+        }
     }
 
-    /// The containing trait, if this is a trait method definition.
+    /// The containing trait, if this is a trait type alias definition.
     pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
-        db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from)
+        match self.container(db) {
+            Some(Container::Trait(it)) => Some(it),
+            _ => None,
+        }
     }
 
     pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
-        if let Some(impl_block) = self.impl_block(db) {
-            Some(impl_block.into())
-        } else if let Some(trait_) = self.parent_trait(db) {
-            Some(trait_.into())
-        } else {
-            None
+        match self.id.lookup(db).container {
+            ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
+            ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
+            ContainerId::ModuleId(_) => None,
         }
     }
 
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 91cab7414f..354d2c98f2 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -120,7 +120,7 @@ impl HasSource for Function {
 impl HasSource for Const {
     type Ast = ast::ConstDef;
     fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ConstDef> {
-        self.id.source(db)
+        self.id.lookup(db).source(db)
     }
 }
 impl HasSource for Static {
@@ -138,7 +138,7 @@ impl HasSource for Trait {
 impl HasSource for TypeAlias {
     type Ast = ast::TypeAliasDef;
     fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TypeAliasDef> {
-        self.id.source(db)
+        self.id.lookup(db).source(db)
     }
 }
 impl HasSource for MacroDef {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 73859e1e94..5bb7961b39 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -26,7 +26,6 @@ pub use hir_def::db::{
     BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
     EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
     RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, TraitDataQuery,
-    TraitItemsIndexQuery,
 };
 pub use hir_expand::db::{
     AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 303d5f1389..b86307c58a 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -4,7 +4,7 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId};
 use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
 use ra_syntax::{
     ast::{self, AstNode, NameOwner},
-    match_ast, AstPtr,
+    match_ast, AstPtr, SyntaxNode,
 };
 
 use crate::{
@@ -52,56 +52,54 @@ impl FromSource for Trait {
 impl FromSource for Function {
     type Ast = ast::FnDef;
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        // FIXME: this doesn't try to handle nested declarations
-        for container in src.value.syntax().ancestors() {
-            let res = match_ast! {
-                match container {
-                    ast::TraitDef(it) => {
-                        let c = Trait::from_source(db, src.with_value(it))?;
-                        c.items(db)
-                            .into_iter()
-                            .filter_map(|it| match it {
-                                AssocItem::Function(it) => Some(it),
-                                _ => None
-                            })
-                            .find(|it| same_source(&it.source(db), &src))?
-                    },
-                    ast::ImplBlock(it) => {
-                        let c = ImplBlock::from_source(db, src.with_value(it))?;
-                        c.items(db)
-                            .into_iter()
-                            .filter_map(|it| match it {
-                                AssocItem::Function(it) => Some(it),
-                                _ => None
-                            })
-                            .find(|it| same_source(&it.source(db), &src))?
-
-                     },
-                    _ => { continue },
-                }
-            };
-            return Some(res);
-        }
-
-        let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
-        let c = Module::from_definition(db, src.with_value(module_source))?;
-        let res = c
-            .declarations(db)
+        let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
+            Container::Trait(it) => it.items(db),
+            Container::ImplBlock(it) => it.items(db),
+            Container::Module(m) => {
+                return m
+                    .declarations(db)
+                    .into_iter()
+                    .filter_map(|it| match it {
+                        ModuleDef::Function(it) => Some(it),
+                        _ => None,
+                    })
+                    .find(|it| same_source(&it.source(db), &src))
+            }
+        };
+        items
             .into_iter()
             .filter_map(|it| match it {
-                ModuleDef::Function(it) => Some(it),
+                AssocItem::Function(it) => Some(it),
                 _ => None,
             })
-            .find(|it| same_source(&it.source(db), &src));
-        res
+            .find(|it| same_source(&it.source(db), &src))
     }
 }
 
 impl FromSource for Const {
     type Ast = ast::ConstDef;
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Const { id })
+        let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
+            Container::Trait(it) => it.items(db),
+            Container::ImplBlock(it) => it.items(db),
+            Container::Module(m) => {
+                return m
+                    .declarations(db)
+                    .into_iter()
+                    .filter_map(|it| match it {
+                        ModuleDef::Const(it) => Some(it),
+                        _ => None,
+                    })
+                    .find(|it| same_source(&it.source(db), &src))
+            }
+        };
+        items
+            .into_iter()
+            .filter_map(|it| match it {
+                AssocItem::Const(it) => Some(it),
+                _ => None,
+            })
+            .find(|it| same_source(&it.source(db), &src))
     }
 }
 impl FromSource for Static {
@@ -114,8 +112,27 @@ impl FromSource for Static {
 impl FromSource for TypeAlias {
     type Ast = ast::TypeAliasDef;
     fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(TypeAlias { id })
+        let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
+            Container::Trait(it) => it.items(db),
+            Container::ImplBlock(it) => it.items(db),
+            Container::Module(m) => {
+                return m
+                    .declarations(db)
+                    .into_iter()
+                    .filter_map(|it| match it {
+                        ModuleDef::TypeAlias(it) => Some(it),
+                        _ => None,
+                    })
+                    .find(|it| same_source(&it.source(db), &src))
+            }
+        };
+        items
+            .into_iter()
+            .filter_map(|it| match it {
+                AssocItem::TypeAlias(it) => Some(it),
+                _ => None,
+            })
+            .find(|it| same_source(&it.source(db), &src))
     }
 }
 
@@ -258,11 +275,43 @@ where
     Some(DEF::from_ast(ctx, &src.value))
 }
 
+enum Container {
+    Trait(Trait),
+    ImplBlock(ImplBlock),
+    Module(Module),
+}
+
+impl Container {
+    fn find(db: &impl DefDatabase, src: Source<&SyntaxNode>) -> Option<Container> {
+        // FIXME: this doesn't try to handle nested declarations
+        for container in src.value.ancestors() {
+            let res = match_ast! {
+                match container {
+                    ast::TraitDef(it) => {
+                        let c = Trait::from_source(db, src.with_value(it))?;
+                        Container::Trait(c)
+                    },
+                    ast::ImplBlock(it) => {
+                        let c = ImplBlock::from_source(db, src.with_value(it))?;
+                        Container::ImplBlock(c)
+                     },
+                    _ => { continue },
+                }
+            };
+            return Some(res);
+        }
+
+        let module_source = ModuleSource::from_child_node(db, src);
+        let c = Module::from_definition(db, src.with_value(module_source))?;
+        Some(Container::Module(c))
+    }
+}
+
 /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
 /// equal if they point to exactly the same object.
 ///
 /// In general, we do not guarantee that we have exactly one instance of a
-/// syntax tree for each file. We probably should add such guanratree, but, for
+/// syntax tree for each file. We probably should add such guarantee, but, for
 /// the time being, we will use identity-less AstPtr comparison.
 fn same_source<N: AstNode>(s1: &Source<N>, s2: &Source<N>) -> bool {
     s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new)
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 0c2bb8fee3..0513f28a96 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -19,14 +19,6 @@ impl HasSource for ImplBlock {
 }
 
 impl ImplBlock {
-    pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option<ImplBlock> {
-        let module = item.module(db);
-        let crate_def_map = db.crate_def_map(module.id.krate);
-        crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| {
-            db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item)
-        })
-    }
-
     pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
         db.impl_data(self.id).target_trait().cloned()
     }
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index caa8d0082f..fd9994098b 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -71,7 +71,7 @@ fn def_with_body_from_child_node(
         match_ast! {
             match node {
                 ast::FnDef(def)  => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); },
-                ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) },
+                ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); },
                 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) },
                 _ => { None },
             }
@@ -428,6 +428,11 @@ impl SourceAnalyzer {
     pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
         self.infer.clone().unwrap()
     }
+
+    #[cfg(test)]
+    pub(crate) fn analyzed_declaration(&self) -> Option<DefWithBody> {
+        self.body_owner
+    }
 }
 
 fn scope_for(
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 776613c7ce..36ece723f2 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -3,8 +3,6 @@
 
 mod autoderef;
 pub(crate) mod primitive;
-#[cfg(test)]
-mod tests;
 pub(crate) mod traits;
 pub(crate) mod method_resolution;
 mod op;
@@ -12,6 +10,9 @@ mod lower;
 mod infer;
 pub(crate) mod display;
 
+#[cfg(test)]
+mod tests;
+
 use std::ops::Deref;
 use std::sync::Arc;
 use std::{fmt, iter, mem};
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index b69d4dea65..dfb79a30ac 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -155,6 +155,7 @@ impl Body {
                 (src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
             }
             DefWithBodyId::ConstId(c) => {
+                let c = c.lookup(db);
                 let src = c.source(db);
                 (src.file_id, c.module(db), src.value.body())
             }
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index e4ffdebe97..c6cd4369b2 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -13,26 +13,26 @@ use crate::{
         raw::{ImportSourceMap, RawItems},
         CrateDefMap,
     },
-    traits::{TraitData, TraitItemsIndex},
-    DefWithBodyId, EnumId, FunctionLoc, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId,
+    traits::TraitData,
+    DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, TraitId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
 pub trait InternDatabase: SourceDatabase {
     #[salsa::interned]
-    fn intern_function(&self, loc: FunctionLoc) -> crate::FunctionId;
+    fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId;
     #[salsa::interned]
     fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId;
     #[salsa::interned]
     fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId;
     #[salsa::interned]
-    fn intern_const(&self, loc: ItemLoc<ast::ConstDef>) -> crate::ConstId;
+    fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId;
     #[salsa::interned]
     fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId;
     #[salsa::interned]
     fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId;
     #[salsa::interned]
-    fn intern_type_alias(&self, loc: ItemLoc<ast::TypeAliasDef>) -> crate::TypeAliasId;
+    fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId;
     #[salsa::interned]
     fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId;
 }
@@ -63,9 +63,6 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
     #[salsa::invoke(TraitData::trait_data_query)]
     fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
 
-    #[salsa::invoke(TraitItemsIndex::trait_items_index)]
-    fn trait_items_index(&self, module: ModuleId) -> TraitItemsIndex;
-
     #[salsa::invoke(Body::body_with_source_map_query)]
     fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
 
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 11dd2a9487..17a5d5f436 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -72,7 +72,7 @@ impl GenericParams {
                 let self_param = TypeRef::Path(name::SELF_TYPE.into());
                 generics.fill_bounds(&it.source(db).value, self_param);
             }
-            GenericDefId::TypeAliasId(it) => generics.fill(&it.source(db).value, start),
+            GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
             // Note that we don't add `Self` here: in `impl`s, `Self` is not a
             // type-parameter, but rather is a type-alias for impl's target
             // type, so this is handled by the resolver.
diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs
index 9be38c5e18..750a869f25 100644
--- a/crates/ra_hir_def/src/impls.rs
+++ b/crates/ra_hir_def/src/impls.rs
@@ -9,8 +9,8 @@ use hir_expand::AstId;
 use ra_syntax::ast;
 
 use crate::{
-    db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionContainerId,
-    FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasId,
+    db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
+    FunctionLoc, ImplId, Intern, TypeAliasLoc,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -31,23 +31,32 @@ impl ImplData {
         let negative = src.value.is_negative();
 
         let items = if let Some(item_list) = src.value.item_list() {
-            let ctx = LocationCtx::new(db, id.module(db), src.file_id);
             item_list
                 .impl_items()
                 .map(|item_node| match item_node {
                     ast::ImplItem::FnDef(it) => {
-                        let func_id = FunctionLoc {
-                            container: FunctionContainerId::ImplId(id),
+                        let def = FunctionLoc {
+                            container: ContainerId::ImplId(id),
                             ast_id: AstId::new(src.file_id, items.ast_id(&it)),
                         }
                         .intern(db);
-                        func_id.into()
+                        def.into()
                     }
                     ast::ImplItem::ConstDef(it) => {
-                        ConstId::from_ast_id(ctx, items.ast_id(&it)).into()
+                        let def = ConstLoc {
+                            container: ContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
                     }
                     ast::ImplItem::TypeAliasDef(it) => {
-                        TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into()
+                        let def = TypeAliasLoc {
+                            container: ContainerId::ImplId(id),
+                            ast_id: AstId::new(src.file_id, items.ast_id(&it)),
+                        }
+                        .intern(db);
+                        def.into()
                     }
                 })
                 .collect()
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index b9a13776ff..0af41de879 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -201,7 +201,7 @@ impl_intern_key!(FunctionId);
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct FunctionLoc {
-    pub container: FunctionContainerId,
+    pub container: ContainerId,
     pub ast_id: AstId<ast::FnDef>,
 }
 
@@ -219,13 +219,6 @@ impl Lookup for FunctionId {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum FunctionContainerId {
-    ModuleId(ModuleId),
-    ImplId(ImplId),
-    TraitId(TraitId),
-}
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct StructOrUnionId(salsa::InternId);
 impl_intern_key!(StructOrUnionId);
@@ -296,12 +289,23 @@ impl_arena_id!(LocalStructFieldId);
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct ConstId(salsa::InternId);
 impl_intern_key!(ConstId);
-impl AstItemDef<ast::ConstDef> for ConstId {
-    fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::ConstDef>) -> Self {
-        db.intern_const(loc)
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ConstLoc {
+    pub container: ContainerId,
+    pub ast_id: AstId<ast::ConstDef>,
+}
+
+impl Intern for ConstLoc {
+    type ID = ConstId;
+    fn intern(self, db: &impl db::DefDatabase2) -> ConstId {
+        db.intern_const(self)
     }
-    fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::ConstDef> {
-        db.lookup_intern_const(self)
+}
+
+impl Lookup for ConstId {
+    type Data = ConstLoc;
+    fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc {
+        db.lookup_intern_const(*self)
     }
 }
 
@@ -332,12 +336,24 @@ impl AstItemDef<ast::TraitDef> for TraitId {
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct TypeAliasId(salsa::InternId);
 impl_intern_key!(TypeAliasId);
-impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
-    fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self {
-        db.intern_type_alias(loc)
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TypeAliasLoc {
+    pub container: ContainerId,
+    pub ast_id: AstId<ast::TypeAliasDef>,
+}
+
+impl Intern for TypeAliasLoc {
+    type ID = TypeAliasId;
+    fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId {
+        db.intern_type_alias(self)
     }
-    fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::TypeAliasDef> {
-        db.lookup_intern_type_alias(self)
+}
+
+impl Lookup for TypeAliasId {
+    type Data = TypeAliasLoc;
+    fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc {
+        db.lookup_intern_type_alias(*self)
     }
 }
 
@@ -372,6 +388,13 @@ macro_rules! impl_froms {
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ContainerId {
+    ModuleId(ModuleId),
+    ImplId(ImplId),
+    TraitId(TraitId),
+}
+
 /// A Data Type
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub enum AdtId {
@@ -469,9 +492,29 @@ pub trait HasModule {
 impl HasModule for FunctionLoc {
     fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
         match self.container {
-            FunctionContainerId::ModuleId(it) => it,
-            FunctionContainerId::ImplId(it) => it.module(db),
-            FunctionContainerId::TraitId(it) => it.module(db),
+            ContainerId::ModuleId(it) => it,
+            ContainerId::ImplId(it) => it.module(db),
+            ContainerId::TraitId(it) => it.module(db),
+        }
+    }
+}
+
+impl HasModule for TypeAliasLoc {
+    fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
+        match self.container {
+            ContainerId::ModuleId(it) => it,
+            ContainerId::ImplId(it) => it.module(db),
+            ContainerId::TraitId(it) => it.module(db),
+        }
+    }
+}
+
+impl HasModule for ConstLoc {
+    fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
+        match self.container {
+            ContainerId::ModuleId(it) => it,
+            ContainerId::ImplId(it) => it.module(db),
+            ContainerId::TraitId(it) => it.module(db),
         }
     }
 }
@@ -489,3 +532,21 @@ impl HasSource for FunctionLoc {
         Source::new(self.ast_id.file_id(), node)
     }
 }
+
+impl HasSource for TypeAliasLoc {
+    type Value = ast::TypeAliasDef;
+
+    fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> {
+        let node = self.ast_id.to_node(db);
+        Source::new(self.ast_id.file_id(), node)
+    }
+}
+
+impl HasSource for ConstLoc {
+    type Value = ast::ConstDef;
+
+    fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::ConstDef> {
+        let node = self.ast_id.to_node(db);
+        Source::new(self.ast_id.file_id(), node)
+    }
+}
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index d2ed94a876..aae3dcadf7 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -19,9 +19,9 @@ use crate::{
         per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
     },
     path::{Path, PathKind},
-    AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionContainerId,
+    AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId,
     FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
-    StructOrUnionId, TraitId, TypeAliasId, UnionId,
+    StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
 };
 
 pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -673,13 +673,13 @@ where
         let name = def.name.clone();
         let def: PerNs = match def.kind {
             raw::DefKind::Function(ast_id) => {
-                let f = FunctionLoc {
-                    container: FunctionContainerId::ModuleId(module),
+                let def = FunctionLoc {
+                    container: ContainerId::ModuleId(module),
                     ast_id: AstId::new(self.file_id, ast_id),
                 }
                 .intern(self.def_collector.db);
 
-                PerNs::values(f.into())
+                PerNs::values(def.into())
             }
             raw::DefKind::Struct(ast_id) => {
                 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into();
@@ -692,13 +692,27 @@ where
                 PerNs::both(u, u)
             }
             raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
-            raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()),
+            raw::DefKind::Const(ast_id) => {
+                let def = ConstLoc {
+                    container: ContainerId::ModuleId(module),
+                    ast_id: AstId::new(self.file_id, ast_id),
+                }
+                .intern(self.def_collector.db);
+
+                PerNs::values(def.into())
+            }
             raw::DefKind::Static(ast_id) => {
                 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into())
             }
             raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
             raw::DefKind::TypeAlias(ast_id) => {
-                PerNs::types(TypeAliasId::from_ast_id(ctx, ast_id).into())
+                let def = TypeAliasLoc {
+                    container: ContainerId::ModuleId(module),
+                    ast_id: AstId::new(self.file_id, ast_id),
+                }
+                .intern(self.def_collector.db);
+
+                PerNs::types(def.into())
             }
         };
         let resolution = Resolution { def, import: None };
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
index 6e36bc0d0c..877d73d666 100644
--- a/crates/ra_hir_def/src/traits.rs
+++ b/crates/ra_hir_def/src/traits.rs
@@ -8,11 +8,10 @@ use hir_expand::{
 };
 
 use ra_syntax::ast::{self, NameOwner};
-use rustc_hash::FxHashMap;
 
 use crate::{
-    db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern,
-    LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasId,
+    db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
+    TypeAliasLoc,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -26,8 +25,6 @@ impl TraitData {
     pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
         let src = tr.source(db);
         let name = src.value.name().map(|n| n.as_name());
-        let module = tr.module(db);
-        let ctx = LocationCtx::new(db, module, src.file_id);
         let auto = src.value.is_auto();
         let ast_id_map = db.ast_id_map(src.file_id);
         let items = if let Some(item_list) = src.value.item_list() {
@@ -35,13 +32,23 @@ impl TraitData {
                 .impl_items()
                 .map(|item_node| match item_node {
                     ast::ImplItem::FnDef(it) => FunctionLoc {
-                        container: FunctionContainerId::TraitId(tr),
+                        container: ContainerId::TraitId(tr),
+                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
+                    }
+                    .intern(db)
+                    .into(),
+                    ast::ImplItem::ConstDef(it) => ConstLoc {
+                        container: ContainerId::TraitId(tr),
+                        ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
+                    }
+                    .intern(db)
+                    .into(),
+                    ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
+                        container: ContainerId::TraitId(tr),
                         ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
                     }
                     .intern(db)
                     .into(),
-                    ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(),
-                    ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(),
                 })
                 .collect()
         } else {
@@ -50,33 +57,3 @@ impl TraitData {
         Arc::new(TraitData { name, items, auto })
     }
 }
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct TraitItemsIndex {
-    traits_by_def: FxHashMap<AssocItemId, TraitId>,
-}
-
-impl TraitItemsIndex {
-    pub fn trait_items_index(db: &impl DefDatabase2, module: ModuleId) -> TraitItemsIndex {
-        let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
-        let crate_def_map = db.crate_def_map(module.krate);
-        for decl in crate_def_map[module.module_id].scope.declarations() {
-            if let ModuleDefId::TraitId(tr) = decl {
-                for item in db.trait_data(tr).items.iter() {
-                    match item {
-                        AssocItemId::FunctionId(_) => (),
-                        _ => {
-                            let prev = index.traits_by_def.insert(*item, tr);
-                            assert!(prev.is_none());
-                        }
-                    }
-                }
-            }
-        }
-        index
-    }
-
-    pub fn get_parent_trait(&self, item: AssocItemId) -> Option<TraitId> {
-        self.traits_by_def.get(&item).cloned()
-    }
-}
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 5c9dec13ef..3c607d5b53 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -309,7 +309,6 @@ impl RootDatabase {
             hir::db::StructDataQuery
             hir::db::EnumDataQuery
             hir::db::TraitDataQuery
-            hir::db::TraitItemsIndexQuery
             hir::db::RawItemsWithSourceMapQuery
             hir::db::RawItemsQuery
             hir::db::CrateDefMapQuery
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index ae87ab9f91..9839be985f 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -404,9 +404,7 @@ mod tests {
         check_hover_result(
             r#"
             //- /main.rs
-            fn main() {
-                const foo<|>: u32 = 0;
-            }
+            const foo<|>: u32 = 0;
         "#,
             &["const foo: u32"],
         );
@@ -414,9 +412,7 @@ mod tests {
         check_hover_result(
             r#"
             //- /main.rs
-            fn main() {
-                static foo<|>: u32 = 0;
-            }
+            static foo<|>: u32 = 0;
         "#,
             &["static foo: u32"],
         );


Test patch:
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index abfaffb5e2..74c12a0a2d 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -11,6 +11,7 @@ use ra_syntax::{
     ast::{self, AstNode},
     SyntaxKind::*,
 };
+use rustc_hash::FxHashSet;
 use test_utils::covers;
 
 use crate::{
@@ -2518,7 +2519,6 @@ fn test() {
     [167; 179) 'GLOBAL_CONST': u32
     [189; 191) 'id': u32
     [194; 210) 'Foo::A..._CONST': u32
-    [126; 128) '99': u32
     "###
     );
 }
@@ -4742,10 +4742,13 @@ fn infer(content: &str) -> String {
         }
     };
 
+    let mut analyzed = FxHashSet::default();
     for node in source_file.syntax().descendants() {
         if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
             let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None);
-            infer_def(analyzer.inference_result(), analyzer.body_source_map());
+            if analyzed.insert(analyzer.analyzed_declaration()) {
+                infer_def(analyzer.inference_result(), analyzer.body_source_map());
+            }
         }
     }