diff options
author | Aleksey Kladov <[email protected]> | 2019-11-20 13:03:59 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-11-20 13:22:58 +0000 |
commit | cebeedc66fc40097eae20bf1767a285d00269966 (patch) | |
tree | e54c306ac0512e3610430574dc8bea39e4b50218 | |
parent | 06fa3d8389c833b01f482bf35b0f850e627612b9 (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
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model/src.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/from_source.rs | 65 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_def/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/impls.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 66 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_def/src/traits.rs | 25 | ||||
-rw-r--r-- | crates/ra_syntax/src/ptr.rs | 10 |
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 | }; |
17 | use hir_expand::{ | 18 | use hir_expand::{ |
18 | diagnostics::DiagnosticSink, | 19 | diagnostics::DiagnosticSink, |
@@ -647,7 +648,7 @@ impl FnData { | |||
647 | 648 | ||
648 | impl Function { | 649 | impl 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 | ||
3 | use hir_def::{HasSource as _, Lookup}; | ||
3 | use ra_syntax::ast::{self, AstNode}; | 4 | use ra_syntax::ast::{self, AstNode}; |
4 | 5 | ||
5 | use crate::{ | 6 | use crate::{ |
@@ -113,7 +114,7 @@ impl HasSource for EnumVariant { | |||
113 | impl HasSource for Function { | 114 | impl 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 | } |
119 | impl HasSource for Const { | 120 | impl 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}; | |||
4 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; | 4 | use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | ast::{self, AstNode, NameOwner}, | 6 | ast::{self, AstNode, NameOwner}, |
7 | match_ast, | 7 | match_ast, AstPtr, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 | ||
18 | pub trait FromSource: Sized { | 18 | pub trait FromSource: Sized { |
@@ -52,10 +52,51 @@ impl FromSource for Trait { | |||
52 | impl FromSource for Function { | 52 | impl 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 | |||
59 | impl FromSource for Const { | 100 | impl 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. | ||
267 | fn 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 | ||
23 | pub struct Expander { | 23 | pub 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)] |
21 | pub trait InternDatabase: SourceDatabase { | 21 | pub 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}; | |||
11 | use crate::{ | 11 | use 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 | ||
6 | use std::sync::Arc; | 6 | use std::sync::Arc; |
7 | 7 | ||
8 | use hir_expand::AstId; | ||
8 | use ra_syntax::ast; | 9 | use ra_syntax::ast; |
9 | 10 | ||
10 | use crate::{ | 11 | use 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 { | |||
199 | pub struct FunctionId(salsa::InternId); | 199 | pub struct FunctionId(salsa::InternId); |
200 | impl_intern_key!(FunctionId); | 200 | impl_intern_key!(FunctionId); |
201 | 201 | ||
202 | impl AstItemDef<ast::FnDef> for FunctionId { | 202 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
203 | fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::FnDef>) -> Self { | 203 | pub struct FunctionLoc { |
204 | db.intern_function(loc) | 204 | pub container: FunctionContainerId, |
205 | pub ast_id: AstId<ast::FnDef>, | ||
206 | } | ||
207 | |||
208 | impl 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 | |
215 | impl 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)] |
223 | pub enum FunctionContainerId { | ||
224 | ModuleId(ModuleId), | ||
225 | ImplId(ImplId), | ||
226 | TraitId(TraitId), | ||
227 | } | ||
228 | |||
229 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
212 | pub struct StructOrUnionId(salsa::InternId); | 230 | pub struct StructOrUnionId(salsa::InternId); |
213 | impl_intern_key!(StructOrUnionId); | 231 | impl_intern_key!(StructOrUnionId); |
214 | impl AstItemDef<ast::StructDef> for StructOrUnionId { | 232 | impl AstItemDef<ast::StructDef> for StructOrUnionId { |
@@ -433,3 +451,41 @@ impl_froms!( | |||
433 | EnumVariantId, | 451 | EnumVariantId, |
434 | ConstId | 452 | ConstId |
435 | ); | 453 | ); |
454 | |||
455 | trait Intern { | ||
456 | type ID; | ||
457 | fn intern(self, db: &impl db::DefDatabase2) -> Self::ID; | ||
458 | } | ||
459 | |||
460 | pub trait Lookup { | ||
461 | type Data; | ||
462 | fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data; | ||
463 | } | ||
464 | |||
465 | pub trait HasModule { | ||
466 | fn module(&self, db: &impl db::DefDatabase2) -> ModuleId; | ||
467 | } | ||
468 | |||
469 | impl 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 | |||
479 | pub trait HasSource { | ||
480 | type Value; | ||
481 | fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>; | ||
482 | } | ||
483 | |||
484 | impl 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 | ||
27 | pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { | 27 | pub(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 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_expand::name::{AsName, Name}; | 5 | use hir_expand::{ |
6 | name::{AsName, Name}, | ||
7 | AstId, | ||
8 | }; | ||
6 | 9 | ||
7 | use ra_syntax::ast::{self, NameOwner}; | 10 | use ra_syntax::ast::{self, NameOwner}; |
8 | use rustc_hash::FxHashMap; | 11 | use rustc_hash::FxHashMap; |
9 | 12 | ||
10 | use crate::{ | 13 | use 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)] |
47 | pub struct AstPtr<N: AstNode> { | 47 | pub 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 | ||
59 | impl<N: AstNode> Eq for AstPtr<N> {} | ||
60 | |||
61 | impl<N: AstNode> PartialEq for AstPtr<N> { | ||
62 | fn eq(&self, other: &AstPtr<N>) -> bool { | ||
63 | self.raw == other.raw | ||
64 | } | ||
65 | } | ||
66 | |||
59 | impl<N: AstNode> AstPtr<N> { | 67 | impl<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 } |