aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-11-20 13:03:59 +0000
committerAleksey Kladov <[email protected]>2019-11-20 13:22:58 +0000
commitcebeedc66fc40097eae20bf1767a285d00269966 (patch)
treee54c306ac0512e3610430574dc8bea39e4b50218 /crates
parent06fa3d8389c833b01f482bf35b0f850e627612b9 (diff)
Next gen IDs for functions
The current system with AstIds has two primaraly drawbacks: * It is possible to manufacture IDs out of thin air. For example, it's possible to create IDs for items which are not considered in CrateDefMap due to cfg. Or it is possible to mixup structs and unions, because they share ID space. * Getting the ID of a parent requires a secondary index. Instead, the plan is to pursue the more traditional approach, where each items stores the id of the parent declaration. This makes `FromSource` more awkward, but also more correct: now, to get from an AST to HIR, we first do this recursively for the parent item, and the just search the children of the parent for the matching def
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs25
-rw-r--r--crates/ra_hir/src/code_model/src.rs3
-rw-r--r--crates/ra_hir/src/from_source.rs65
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir_def/src/body.rs3
-rw-r--r--crates/ra_hir_def/src/db.rs4
-rw-r--r--crates/ra_hir_def/src/generics.rs4
-rw-r--r--crates/ra_hir_def/src/impls.rs12
-rw-r--r--crates/ra_hir_def/src/lib.rs66
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs13
-rw-r--r--crates/ra_hir_def/src/traits.rs25
-rw-r--r--crates/ra_syntax/src/ptr.rs10
12 files changed, 190 insertions, 42 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index f436d5d5e..c49190a0f 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -12,7 +12,8 @@ use hir_def::{
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 traits::TraitData, 13 traits::TraitData,
14 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
15 AssocItemId, CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, 15 AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId,
16 LocalStructFieldId, Lookup, ModuleId, UnionId,
16}; 17};
17use hir_expand::{ 18use hir_expand::{
18 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -647,7 +648,7 @@ impl FnData {
647 648
648impl Function { 649impl Function {
649 pub fn module(self, db: &impl DefDatabase) -> Module { 650 pub fn module(self, db: &impl DefDatabase) -> Module {
650 Module { id: self.id.module(db) } 651 self.id.lookup(db).module(db).into()
651 } 652 }
652 653
653 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 654 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -680,21 +681,25 @@ impl Function {
680 681
681 /// The containing impl block, if this is a method. 682 /// The containing impl block, if this is a method.
682 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 683 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
683 ImplBlock::containing(db, self.into()) 684 match self.container(db) {
685 Some(Container::ImplBlock(it)) => Some(it),
686 _ => None,
687 }
684 } 688 }
685 689
686 /// The containing trait, if this is a trait method definition. 690 /// The containing trait, if this is a trait method definition.
687 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 691 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
688 db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) 692 match self.container(db) {
693 Some(Container::Trait(it)) => Some(it),
694 _ => None,
695 }
689 } 696 }
690 697
691 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 698 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
692 if let Some(impl_block) = self.impl_block(db) { 699 match self.id.lookup(db).container {
693 Some(impl_block.into()) 700 FunctionContainerId::TraitId(it) => Some(Container::Trait(it.into())),
694 } else if let Some(trait_) = self.parent_trait(db) { 701 FunctionContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
695 Some(trait_.into()) 702 FunctionContainerId::ModuleId(_) => None,
696 } else {
697 None
698 } 703 }
699 } 704 }
700 705
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 556417b0f..91cab7414 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,5 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{HasSource as _, Lookup};
3use ra_syntax::ast::{self, AstNode}; 4use ra_syntax::ast::{self, AstNode};
4 5
5use crate::{ 6use crate::{
@@ -113,7 +114,7 @@ impl HasSource for EnumVariant {
113impl HasSource for Function { 114impl HasSource for Function {
114 type Ast = ast::FnDef; 115 type Ast = ast::FnDef;
115 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::FnDef> { 116 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::FnDef> {
116 self.id.source(db) 117 self.id.lookup(db).source(db)
117 } 118 }
118} 119}
119impl HasSource for Const { 120impl HasSource for Const {
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index f4dca25cb..303d5f138 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -4,15 +4,15 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 6 ast::{self, AstNode, NameOwner},
7 match_ast, 7 match_ast, AstPtr,
8}; 8};
9 9
10use crate::{ 10use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx}, 12 ids::{AstItemDef, LocationCtx},
13 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, 13 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource,
14 Local, MacroDef, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, 14 ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct,
15 Union, VariantDef, 15 StructField, Trait, TypeAlias, Union, VariantDef,
16}; 16};
17 17
18pub trait FromSource: Sized { 18pub trait FromSource: Sized {
@@ -52,10 +52,51 @@ impl FromSource for Trait {
52impl FromSource for Function { 52impl FromSource for Function {
53 type Ast = ast::FnDef; 53 type Ast = ast::FnDef;
54 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 54 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
55 let id = from_source(db, src)?; 55 // FIXME: this doesn't try to handle nested declarations
56 Some(Function { id }) 56 for container in src.value.syntax().ancestors() {
57 let res = match_ast! {
58 match container {
59 ast::TraitDef(it) => {
60 let c = Trait::from_source(db, src.with_value(it))?;
61 c.items(db)
62 .into_iter()
63 .filter_map(|it| match it {
64 AssocItem::Function(it) => Some(it),
65 _ => None
66 })
67 .find(|it| same_source(&it.source(db), &src))?
68 },
69 ast::ImplBlock(it) => {
70 let c = ImplBlock::from_source(db, src.with_value(it))?;
71 c.items(db)
72 .into_iter()
73 .filter_map(|it| match it {
74 AssocItem::Function(it) => Some(it),
75 _ => None
76 })
77 .find(|it| same_source(&it.source(db), &src))?
78
79 },
80 _ => { continue },
81 }
82 };
83 return Some(res);
84 }
85
86 let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
87 let c = Module::from_definition(db, src.with_value(module_source))?;
88 let res = c
89 .declarations(db)
90 .into_iter()
91 .filter_map(|it| match it {
92 ModuleDef::Function(it) => Some(it),
93 _ => None,
94 })
95 .find(|it| same_source(&it.source(db), &src));
96 res
57 } 97 }
58} 98}
99
59impl FromSource for Const { 100impl FromSource for Const {
60 type Ast = ast::ConstDef; 101 type Ast = ast::ConstDef;
61 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 102 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
@@ -108,7 +149,7 @@ impl FromSource for EnumVariant {
108 let parent_enum = src.value.parent_enum(); 149 let parent_enum = src.value.parent_enum();
109 let src_enum = Source { file_id: src.file_id, value: parent_enum }; 150 let src_enum = Source { file_id: src.file_id, value: parent_enum };
110 let variants = Enum::from_source(db, src_enum)?.variants(db); 151 let variants = Enum::from_source(db, src_enum)?.variants(db);
111 variants.into_iter().find(|v| v.source(db) == src) 152 variants.into_iter().find(|v| same_source(&v.source(db), &src))
112 } 153 }
113} 154}
114 155
@@ -216,3 +257,13 @@ where
216 let ctx = LocationCtx::new(db, module.id, src.file_id); 257 let ctx = LocationCtx::new(db, module.id, src.file_id);
217 Some(DEF::from_ast(ctx, &src.value)) 258 Some(DEF::from_ast(ctx, &src.value))
218} 259}
260
261/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
262/// equal if they point to exactly the same object.
263///
264/// In general, we do not guarantee that we have exactly one instance of a
265/// syntax tree for each file. We probably should add such guanratree, but, for
266/// the time being, we will use identity-less AstPtr comparison.
267fn same_source<N: AstNode>(s1: &Source<N>, s2: &Source<N>) -> bool {
268 s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new)
269}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index a1c1daacd..5d9e22ee2 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -70,7 +70,7 @@ fn def_with_body_from_child_node(
70 child.value.ancestors().find_map(|node| { 70 child.value.ancestors().find_map(|node| {
71 match_ast! { 71 match_ast! {
72 match node { 72 match node {
73 ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, 73 ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); },
74 ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) }, 74 ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) },
75 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, 75 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) },
76 _ => { None }, 76 _ => { None },
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 3804b65c7..b69d4dea6 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -17,7 +17,7 @@ use crate::{
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
20 AstItemDef, DefWithBodyId, ModuleId, 20 AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 21};
22 22
23pub struct Expander { 23pub struct Expander {
@@ -149,6 +149,7 @@ impl Body {
149 149
150 let (file_id, module, body) = match def { 150 let (file_id, module, body) = match def {
151 DefWithBodyId::FunctionId(f) => { 151 DefWithBodyId::FunctionId(f) => {
152 let f = f.lookup(db);
152 let src = f.source(db); 153 let src = f.source(db);
153 params = src.value.param_list(); 154 params = src.value.param_list();
154 (src.file_id, f.module(db), src.value.body().map(ast::Expr::from)) 155 (src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index fb4402463..e4ffdebe9 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -14,13 +14,13 @@ use crate::{
14 CrateDefMap, 14 CrateDefMap,
15 }, 15 },
16 traits::{TraitData, TraitItemsIndex}, 16 traits::{TraitData, TraitItemsIndex},
17 DefWithBodyId, EnumId, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, 17 DefWithBodyId, EnumId, FunctionLoc, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId,
18}; 18};
19 19
20#[salsa::query_group(InternDatabaseStorage)] 20#[salsa::query_group(InternDatabaseStorage)]
21pub trait InternDatabase: SourceDatabase { 21pub trait InternDatabase: SourceDatabase {
22 #[salsa::interned] 22 #[salsa::interned]
23 fn intern_function(&self, loc: ItemLoc<ast::FnDef>) -> crate::FunctionId; 23 fn intern_function(&self, loc: FunctionLoc) -> crate::FunctionId;
24 #[salsa::interned] 24 #[salsa::interned]
25 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId; 25 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId;
26 #[salsa::interned] 26 #[salsa::interned]
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 4adfc16bb..11dd2a948 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -11,7 +11,7 @@ use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
11use crate::{ 11use crate::{
12 db::DefDatabase2, 12 db::DefDatabase2,
13 type_ref::{TypeBound, TypeRef}, 13 type_ref::{TypeBound, TypeRef},
14 AdtId, AstItemDef, GenericDefId, 14 AdtId, AstItemDef, GenericDefId, HasSource, Lookup,
15}; 15};
16 16
17/// Data about a generic parameter (to a function, struct, impl, ...). 17/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -53,7 +53,7 @@ impl GenericParams {
53 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; 53 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
54 // FIXME: add `: Sized` bound for everything except for `Self` in traits 54 // FIXME: add `: Sized` bound for everything except for `Self` in traits
55 match def { 55 match def {
56 GenericDefId::FunctionId(it) => generics.fill(&it.source(db).value, start), 56 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
57 GenericDefId::AdtId(AdtId::StructId(it)) => { 57 GenericDefId::AdtId(AdtId::StructId(it)) => {
58 generics.fill(&it.0.source(db).value, start) 58 generics.fill(&it.0.source(db).value, start)
59 } 59 }
diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs
index 4323dfcb6..9be38c5e1 100644
--- a/crates/ra_hir_def/src/impls.rs
+++ b/crates/ra_hir_def/src/impls.rs
@@ -5,11 +5,12 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_expand::AstId;
8use ra_syntax::ast; 9use ra_syntax::ast;
9 10
10use crate::{ 11use crate::{
11 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId, 12 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionContainerId,
12 LocationCtx, TypeAliasId, 13 FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasId,
13}; 14};
14 15
15#[derive(Debug, Clone, PartialEq, Eq)] 16#[derive(Debug, Clone, PartialEq, Eq)]
@@ -35,7 +36,12 @@ impl ImplData {
35 .impl_items() 36 .impl_items()
36 .map(|item_node| match item_node { 37 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => { 38 ast::ImplItem::FnDef(it) => {
38 FunctionId::from_ast_id(ctx, items.ast_id(&it)).into() 39 let func_id = FunctionLoc {
40 container: FunctionContainerId::ImplId(id),
41 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
42 }
43 .intern(db);
44 func_id.into()
39 } 45 }
40 ast::ImplItem::ConstDef(it) => { 46 ast::ImplItem::ConstDef(it) => {
41 ConstId::from_ast_id(ctx, items.ast_id(&it)).into() 47 ConstId::from_ast_id(ctx, items.ast_id(&it)).into()
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 38c110570..b9a13776f 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -199,16 +199,34 @@ pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
199pub struct FunctionId(salsa::InternId); 199pub struct FunctionId(salsa::InternId);
200impl_intern_key!(FunctionId); 200impl_intern_key!(FunctionId);
201 201
202impl AstItemDef<ast::FnDef> for FunctionId { 202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
203 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::FnDef>) -> Self { 203pub struct FunctionLoc {
204 db.intern_function(loc) 204 pub container: FunctionContainerId,
205 pub ast_id: AstId<ast::FnDef>,
206}
207
208impl Intern for FunctionLoc {
209 type ID = FunctionId;
210 fn intern(self, db: &impl db::DefDatabase2) -> FunctionId {
211 db.intern_function(self)
205 } 212 }
206 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::FnDef> { 213}
207 db.lookup_intern_function(self) 214
215impl Lookup for FunctionId {
216 type Data = FunctionLoc;
217 fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc {
218 db.lookup_intern_function(*self)
208 } 219 }
209} 220}
210 221
211#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 222#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
223pub enum FunctionContainerId {
224 ModuleId(ModuleId),
225 ImplId(ImplId),
226 TraitId(TraitId),
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
212pub struct StructOrUnionId(salsa::InternId); 230pub struct StructOrUnionId(salsa::InternId);
213impl_intern_key!(StructOrUnionId); 231impl_intern_key!(StructOrUnionId);
214impl AstItemDef<ast::StructDef> for StructOrUnionId { 232impl AstItemDef<ast::StructDef> for StructOrUnionId {
@@ -433,3 +451,41 @@ impl_froms!(
433 EnumVariantId, 451 EnumVariantId,
434 ConstId 452 ConstId
435); 453);
454
455trait Intern {
456 type ID;
457 fn intern(self, db: &impl db::DefDatabase2) -> Self::ID;
458}
459
460pub trait Lookup {
461 type Data;
462 fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data;
463}
464
465pub trait HasModule {
466 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId;
467}
468
469impl HasModule for FunctionLoc {
470 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
471 match self.container {
472 FunctionContainerId::ModuleId(it) => it,
473 FunctionContainerId::ImplId(it) => it.module(db),
474 FunctionContainerId::TraitId(it) => it.module(db),
475 }
476 }
477}
478
479pub trait HasSource {
480 type Value;
481 fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>;
482}
483
484impl HasSource for FunctionLoc {
485 type Value = ast::FnDef;
486
487 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::FnDef> {
488 let node = self.ast_id.to_node(db);
489 Source::new(self.ast_id.file_id(), node)
490 }
491}
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8f426b097..d2ed94a87 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::{
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 20 },
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, ImplId, 22 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionContainerId,
23 LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId, 23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
24 UnionId, 24 StructOrUnionId, TraitId, TypeAliasId, UnionId,
25}; 25};
26 26
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -673,7 +673,12 @@ where
673 let name = def.name.clone(); 673 let name = def.name.clone();
674 let def: PerNs = match def.kind { 674 let def: PerNs = match def.kind {
675 raw::DefKind::Function(ast_id) => { 675 raw::DefKind::Function(ast_id) => {
676 let f = FunctionId::from_ast_id(ctx, ast_id); 676 let f = FunctionLoc {
677 container: FunctionContainerId::ModuleId(module),
678 ast_id: AstId::new(self.file_id, ast_id),
679 }
680 .intern(self.def_collector.db);
681
677 PerNs::values(f.into()) 682 PerNs::values(f.into())
678 } 683 }
679 raw::DefKind::Struct(ast_id) => { 684 raw::DefKind::Struct(ast_id) => {
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
index a8ba31594..6e36bc0d0 100644
--- a/crates/ra_hir_def/src/traits.rs
+++ b/crates/ra_hir_def/src/traits.rs
@@ -2,14 +2,17 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::name::{AsName, Name}; 5use hir_expand::{
6 name::{AsName, Name},
7 AstId,
8};
6 9
7use ra_syntax::ast::{self, NameOwner}; 10use ra_syntax::ast::{self, NameOwner};
8use rustc_hash::FxHashMap; 11use rustc_hash::FxHashMap;
9 12
10use crate::{ 13use crate::{
11 db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionId, LocationCtx, ModuleDefId, 14 db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern,
12 ModuleId, TraitId, TypeAliasId, 15 LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasId,
13}; 16};
14 17
15#[derive(Debug, Clone, PartialEq, Eq)] 18#[derive(Debug, Clone, PartialEq, Eq)]
@@ -26,11 +29,17 @@ impl TraitData {
26 let module = tr.module(db); 29 let module = tr.module(db);
27 let ctx = LocationCtx::new(db, module, src.file_id); 30 let ctx = LocationCtx::new(db, module, src.file_id);
28 let auto = src.value.is_auto(); 31 let auto = src.value.is_auto();
32 let ast_id_map = db.ast_id_map(src.file_id);
29 let items = if let Some(item_list) = src.value.item_list() { 33 let items = if let Some(item_list) = src.value.item_list() {
30 item_list 34 item_list
31 .impl_items() 35 .impl_items()
32 .map(|item_node| match item_node { 36 .map(|item_node| match item_node {
33 ast::ImplItem::FnDef(it) => FunctionId::from_ast(ctx, &it).into(), 37 ast::ImplItem::FnDef(it) => FunctionLoc {
38 container: FunctionContainerId::TraitId(tr),
39 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
40 }
41 .intern(db)
42 .into(),
34 ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(), 43 ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(),
35 ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(), 44 ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(),
36 }) 45 })
@@ -54,7 +63,13 @@ impl TraitItemsIndex {
54 for decl in crate_def_map[module.module_id].scope.declarations() { 63 for decl in crate_def_map[module.module_id].scope.declarations() {
55 if let ModuleDefId::TraitId(tr) = decl { 64 if let ModuleDefId::TraitId(tr) = decl {
56 for item in db.trait_data(tr).items.iter() { 65 for item in db.trait_data(tr).items.iter() {
57 index.traits_by_def.insert(*item, tr); 66 match item {
67 AssocItemId::FunctionId(_) => (),
68 _ => {
69 let prev = index.traits_by_def.insert(*item, tr);
70 assert!(prev.is_none());
71 }
72 }
58 } 73 }
59 } 74 }
60 } 75 }
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 31167cada..e049fce61 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -43,7 +43,7 @@ impl SyntaxNodePtr {
43} 43}
44 44
45/// Like `SyntaxNodePtr`, but remembers the type of node 45/// Like `SyntaxNodePtr`, but remembers the type of node
46#[derive(Debug, PartialEq, Eq, Hash)] 46#[derive(Debug, Hash)]
47pub struct AstPtr<N: AstNode> { 47pub struct AstPtr<N: AstNode> {
48 raw: SyntaxNodePtr, 48 raw: SyntaxNodePtr,
49 _ty: PhantomData<fn() -> N>, 49 _ty: PhantomData<fn() -> N>,
@@ -56,6 +56,14 @@ impl<N: AstNode> Clone for AstPtr<N> {
56 } 56 }
57} 57}
58 58
59impl<N: AstNode> Eq for AstPtr<N> {}
60
61impl<N: AstNode> PartialEq for AstPtr<N> {
62 fn eq(&self, other: &AstPtr<N>) -> bool {
63 self.raw == other.raw
64 }
65}
66
59impl<N: AstNode> AstPtr<N> { 67impl<N: AstNode> AstPtr<N> {
60 pub fn new(node: &N) -> AstPtr<N> { 68 pub fn new(node: &N) -> AstPtr<N> {
61 AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData } 69 AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }