aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model.rs53
-rw-r--r--crates/ra_hir/src/code_model/src.rs3
-rw-r--r--crates/ra_hir/src/db.rs10
-rw-r--r--crates/ra_hir/src/from_source.rs65
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/source_binder.rs15
-rw-r--r--crates/ra_hir/src/traits.rs82
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs6
-rw-r--r--crates/ra_hir_def/src/body.rs3
-rw-r--r--crates/ra_hir_def/src/db.rs13
-rw-r--r--crates/ra_hir_def/src/generics.rs4
-rw-r--r--crates/ra_hir_def/src/impls.rs (renamed from crates/ra_hir_def/src/imp.rs)12
-rw-r--r--crates/ra_hir_def/src/lib.rs69
-rw-r--r--crates/ra_hir_def/src/nameres.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs13
-rw-r--r--crates/ra_hir_def/src/traits.rs82
-rw-r--r--crates/ra_ide_api/src/expand.rs2
-rw-r--r--crates/ra_ide_api/src/expand_macro.rs10
-rw-r--r--crates/ra_syntax/src/ptr.rs10
19 files changed, 301 insertions, 160 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index cb990f4e2..c49190a0f 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -10,8 +10,10 @@ use hir_def::{
10 adt::VariantData, 10 adt::VariantData,
11 body::scope::ExprScopes, 11 body::scope::ExprScopes,
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 traits::TraitData,
13 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
14 CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, 15 AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId,
16 LocalStructFieldId, Lookup, ModuleId, UnionId,
15}; 17};
16use hir_expand::{ 18use hir_expand::{
17 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -30,7 +32,6 @@ use crate::{
30 TypeAliasId, 32 TypeAliasId,
31 }, 33 },
32 resolve::{Resolver, Scope, TypeNs}, 34 resolve::{Resolver, Scope, TypeNs},
33 traits::TraitData,
34 ty::{InferenceResult, Namespace, TraitRef}, 35 ty::{InferenceResult, Namespace, TraitRef},
35 Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, 36 Either, HasSource, ImportId, Name, ScopeDef, Source, Ty,
36}; 37};
@@ -230,15 +231,7 @@ impl Module {
230 231
231 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> { 232 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
232 let def_map = db.crate_def_map(self.id.krate); 233 let def_map = db.crate_def_map(self.id.krate);
233 def_map[self.id.module_id] 234 def_map[self.id.module_id].scope.declarations().map(ModuleDef::from).collect()
234 .scope
235 .entries()
236 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
237 .flat_map(|per_ns| {
238 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
239 })
240 .map(ModuleDef::from)
241 .collect()
242 } 235 }
243 236
244 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { 237 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
@@ -655,7 +648,7 @@ impl FnData {
655 648
656impl Function { 649impl Function {
657 pub fn module(self, db: &impl DefDatabase) -> Module { 650 pub fn module(self, db: &impl DefDatabase) -> Module {
658 Module { id: self.id.module(db) } 651 self.id.lookup(db).module(db).into()
659 } 652 }
660 653
661 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 654 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -688,21 +681,25 @@ impl Function {
688 681
689 /// The containing impl block, if this is a method. 682 /// The containing impl block, if this is a method.
690 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 683 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
691 ImplBlock::containing(db, self.into()) 684 match self.container(db) {
685 Some(Container::ImplBlock(it)) => Some(it),
686 _ => None,
687 }
692 } 688 }
693 689
694 /// The containing trait, if this is a trait method definition. 690 /// The containing trait, if this is a trait method definition.
695 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 691 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
696 db.trait_items_index(self.module(db)).get_parent_trait(self.into()) 692 match self.container(db) {
693 Some(Container::Trait(it)) => Some(it),
694 _ => None,
695 }
697 } 696 }
698 697
699 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 698 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
700 if let Some(impl_block) = self.impl_block(db) { 699 match self.id.lookup(db).container {
701 Some(impl_block.into()) 700 FunctionContainerId::TraitId(it) => Some(Container::Trait(it.into())),
702 } else if let Some(trait_) = self.parent_trait(db) { 701 FunctionContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
703 Some(trait_.into()) 702 FunctionContainerId::ModuleId(_) => None,
704 } else {
705 None
706 } 703 }
707 } 704 }
708 705
@@ -757,7 +754,7 @@ impl Const {
757 } 754 }
758 755
759 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 756 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
760 db.trait_items_index(self.module(db)).get_parent_trait(self.into()) 757 db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from)
761 } 758 }
762 759
763 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 760 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
@@ -861,11 +858,11 @@ impl Trait {
861 } 858 }
862 859
863 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 860 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
864 self.trait_data(db).name().clone() 861 self.trait_data(db).name.clone()
865 } 862 }
866 863
867 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 864 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
868 self.trait_data(db).items().to_vec() 865 self.trait_data(db).items.iter().map(|it| (*it).into()).collect()
869 } 866 }
870 867
871 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { 868 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
@@ -912,10 +909,10 @@ impl Trait {
912 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { 909 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
913 let trait_data = self.trait_data(db); 910 let trait_data = self.trait_data(db);
914 trait_data 911 trait_data
915 .items() 912 .items
916 .iter() 913 .iter()
917 .filter_map(|item| match item { 914 .filter_map(|item| match item {
918 AssocItem::TypeAlias(t) => Some(*t), 915 AssocItemId::TypeAliasId(t) => Some(TypeAlias::from(*t)),
919 _ => None, 916 _ => None,
920 }) 917 })
921 .find(|t| &t.name(db) == name) 918 .find(|t| &t.name(db) == name)
@@ -930,7 +927,7 @@ impl Trait {
930 } 927 }
931 928
932 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 929 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
933 db.trait_data(self) 930 db.trait_data(self.id)
934 } 931 }
935 932
936 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { 933 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
@@ -938,7 +935,7 @@ impl Trait {
938 } 935 }
939 936
940 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 937 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
941 self.trait_data(db).is_auto() 938 self.trait_data(db).auto
942 } 939 }
943 940
944 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { 941 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
@@ -971,7 +968,7 @@ impl TypeAlias {
971 968
972 /// The containing trait, if this is a trait method definition. 969 /// The containing trait, if this is a trait method definition.
973 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 970 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
974 db.trait_items_index(self.module(db)).get_parent_trait(self.into()) 971 db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from)
975 } 972 }
976 973
977 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 974 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
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/db.rs b/crates/ra_hir/src/db.rs
index 0d35014a0..73859e1e9 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -11,7 +11,6 @@ use crate::{
11 generics::{GenericDef, GenericParams}, 11 generics::{GenericDef, GenericParams},
12 ids, 12 ids,
13 lang_item::{LangItemTarget, LangItems}, 13 lang_item::{LangItemTarget, LangItems},
14 traits::TraitData,
15 ty::{ 14 ty::{
16 method_resolution::CrateImplBlocks, 15 method_resolution::CrateImplBlocks,
17 traits::{AssocTyValue, Impl}, 16 traits::{AssocTyValue, Impl},
@@ -26,7 +25,8 @@ use crate::{
26pub use hir_def::db::{ 25pub use hir_def::db::{
27 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, 26 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
28 EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, 27 EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
29 RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, 28 RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, TraitDataQuery,
29 TraitItemsIndexQuery,
30}; 30};
31pub use hir_expand::db::{ 31pub use hir_expand::db::{
32 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 32 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -37,12 +37,6 @@ pub use hir_expand::db::{
37#[salsa::query_group(DefDatabaseStorage)] 37#[salsa::query_group(DefDatabaseStorage)]
38#[salsa::requires(AstDatabase)] 38#[salsa::requires(AstDatabase)]
39pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { 39pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
40 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
41 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
42
43 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
44 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
45
46 #[salsa::invoke(crate::generics::generic_params_query)] 40 #[salsa::invoke(crate::generics::generic_params_query)]
47 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; 41 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
48 42
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/lib.rs b/crates/ra_hir/src/lib.rs
index da33c9591..7ac9a9041 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -33,7 +33,6 @@ pub mod source_binder;
33 33
34mod ids; 34mod ids;
35mod adt; 35mod adt;
36mod traits;
37mod type_alias; 36mod type_alias;
38mod ty; 37mod ty;
39mod impl_block; 38mod impl_block;
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index a1c1daacd..caa8d0082 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 },
@@ -405,9 +405,16 @@ impl SourceAnalyzer {
405 implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) 405 implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait)
406 } 406 }
407 407
408 pub fn expand(&self, db: &impl HirDatabase, macro_call: &ast::MacroCall) -> Option<Expansion> { 408 pub fn expand(
409 let def = self.resolve_macro_call(db, macro_call)?.id; 409 &self,
410 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(macro_call)); 410 db: &impl HirDatabase,
411 macro_call: Source<&ast::MacroCall>,
412 ) -> Option<Expansion> {
413 let def = self.resolve_macro_call(db, macro_call.value)?.id;
414 let ast_id = AstId::new(
415 macro_call.file_id,
416 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
417 );
411 let macro_call_loc = MacroCallLoc { def, ast_id }; 418 let macro_call_loc = MacroCallLoc { def, ast_id };
412 Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) 419 Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) })
413 } 420 }
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
deleted file mode 100644
index 858972c6f..000000000
--- a/crates/ra_hir/src/traits.rs
+++ /dev/null
@@ -1,82 +0,0 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::name::AsName;
6
7use ra_syntax::ast::{self, NameOwner};
8use rustc_hash::FxHashMap;
9
10use crate::{
11 db::{AstDatabase, DefDatabase},
12 ids::LocationCtx,
13 AssocItem, Const, Function, HasSource, Module, Name, Trait, TypeAlias,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct TraitData {
18 name: Option<Name>,
19 items: Vec<AssocItem>,
20 auto: bool,
21}
22
23impl TraitData {
24 pub(crate) fn trait_data_query(
25 db: &(impl DefDatabase + AstDatabase),
26 tr: Trait,
27 ) -> Arc<TraitData> {
28 let src = tr.source(db);
29 let name = src.value.name().map(|n| n.as_name());
30 let module = tr.module(db);
31 let ctx = LocationCtx::new(db, module.id, src.file_id);
32 let auto = src.value.is_auto();
33 let items = if let Some(item_list) = src.value.item_list() {
34 item_list
35 .impl_items()
36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(),
38 ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(),
39 ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(),
40 })
41 .collect()
42 } else {
43 Vec::new()
44 };
45 Arc::new(TraitData { name, items, auto })
46 }
47
48 pub(crate) fn name(&self) -> &Option<Name> {
49 &self.name
50 }
51
52 pub(crate) fn items(&self) -> &[AssocItem] {
53 &self.items
54 }
55
56 pub(crate) fn is_auto(&self) -> bool {
57 self.auto
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct TraitItemsIndex {
63 traits_by_def: FxHashMap<AssocItem, Trait>,
64}
65
66impl TraitItemsIndex {
67 pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex {
68 let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
69 for decl in module.declarations(db) {
70 if let crate::ModuleDef::Trait(tr) = decl {
71 for item in tr.trait_data(db).items() {
72 index.traits_by_def.insert(*item, tr);
73 }
74 }
75 }
76 index
77 }
78
79 pub(crate) fn get_parent_trait(&self, item: AssocItem) -> Option<Trait> {
80 self.traits_by_def.get(&item).cloned()
81 }
82}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index d20aeaacf..f377fca48 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -232,8 +232,8 @@ fn iterate_trait_method_candidates<T>(
232 // trait, but if we find out it doesn't, we'll skip the rest of the 232 // trait, but if we find out it doesn't, we'll skip the rest of the
233 // iteration 233 // iteration
234 let mut known_implemented = false; 234 let mut known_implemented = false;
235 for &item in data.items() { 235 for &item in data.items.iter() {
236 if !is_valid_candidate(db, name, mode, item) { 236 if !is_valid_candidate(db, name, mode, item.into()) {
237 continue; 237 continue;
238 } 238 }
239 if !known_implemented { 239 if !known_implemented {
@@ -243,7 +243,7 @@ fn iterate_trait_method_candidates<T>(
243 } 243 }
244 } 244 }
245 known_implemented = true; 245 known_implemented = true;
246 if let Some(result) = callback(&ty.value, item) { 246 if let Some(result) = callback(&ty.value, item.into()) {
247 return Some(result); 247 return Some(result);
248 } 248 }
249 } 249 }
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 348aca07f..e4ffdebe9 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -8,18 +8,19 @@ use ra_syntax::ast;
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 body::{scope::ExprScopes, Body, BodySourceMap}, 10 body::{scope::ExprScopes, Body, BodySourceMap},
11 imp::ImplData, 11 impls::ImplData,
12 nameres::{ 12 nameres::{
13 raw::{ImportSourceMap, RawItems}, 13 raw::{ImportSourceMap, RawItems},
14 CrateDefMap, 14 CrateDefMap,
15 }, 15 },
16 DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, 16 traits::{TraitData, TraitItemsIndex},
17 DefWithBodyId, EnumId, FunctionLoc, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId,
17}; 18};
18 19
19#[salsa::query_group(InternDatabaseStorage)] 20#[salsa::query_group(InternDatabaseStorage)]
20pub trait InternDatabase: SourceDatabase { 21pub trait InternDatabase: SourceDatabase {
21 #[salsa::interned] 22 #[salsa::interned]
22 fn intern_function(&self, loc: ItemLoc<ast::FnDef>) -> crate::FunctionId; 23 fn intern_function(&self, loc: FunctionLoc) -> crate::FunctionId;
23 #[salsa::interned] 24 #[salsa::interned]
24 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;
25 #[salsa::interned] 26 #[salsa::interned]
@@ -59,6 +60,12 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
59 #[salsa::invoke(ImplData::impl_data_query)] 60 #[salsa::invoke(ImplData::impl_data_query)]
60 fn impl_data(&self, e: ImplId) -> Arc<ImplData>; 61 fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
61 62
63 #[salsa::invoke(TraitData::trait_data_query)]
64 fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
65
66 #[salsa::invoke(TraitItemsIndex::trait_items_index)]
67 fn trait_items_index(&self, module: ModuleId) -> TraitItemsIndex;
68
62 #[salsa::invoke(Body::body_with_source_map_query)] 69 #[salsa::invoke(Body::body_with_source_map_query)]
63 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 70 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
64 71
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/imp.rs b/crates/ra_hir_def/src/impls.rs
index 4323dfcb6..9be38c5e1 100644
--- a/crates/ra_hir_def/src/imp.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 dffc82ff8..b9a13776f 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,11 +13,12 @@ pub mod path;
13pub mod type_ref; 13pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt; 15pub mod adt;
16pub mod imp; 16pub mod impls;
17pub mod diagnostics; 17pub mod diagnostics;
18pub mod expr; 18pub mod expr;
19pub mod body; 19pub mod body;
20pub mod generics; 20pub mod generics;
21pub mod traits;
21 22
22#[cfg(test)] 23#[cfg(test)]
23mod test_db; 24mod test_db;
@@ -198,16 +199,34 @@ pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
198pub struct FunctionId(salsa::InternId); 199pub struct FunctionId(salsa::InternId);
199impl_intern_key!(FunctionId); 200impl_intern_key!(FunctionId);
200 201
201impl AstItemDef<ast::FnDef> for FunctionId { 202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
202 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::FnDef>) -> Self { 203pub struct FunctionLoc {
203 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)
204 } 212 }
205 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::FnDef> { 213}
206 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)
207 } 219 }
208} 220}
209 221
210#[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)]
211pub struct StructOrUnionId(salsa::InternId); 230pub struct StructOrUnionId(salsa::InternId);
212impl_intern_key!(StructOrUnionId); 231impl_intern_key!(StructOrUnionId);
213impl AstItemDef<ast::StructDef> for StructOrUnionId { 232impl AstItemDef<ast::StructDef> for StructOrUnionId {
@@ -432,3 +451,41 @@ impl_froms!(
432 EnumVariantId, 451 EnumVariantId,
433 ConstId 452 ConstId
434); 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.rs b/crates/ra_hir_def/src/nameres.rs
index e5b073a0f..c01e020ef 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -165,6 +165,14 @@ impl ModuleScope {
165 self.items.iter().chain(BUILTIN_SCOPE.iter()) 165 self.items.iter().chain(BUILTIN_SCOPE.iter())
166 } 166 }
167 167
168 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
169 self.entries()
170 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
171 .flat_map(|per_ns| {
172 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
173 })
174 }
175
168 /// Iterate over all module scoped macros 176 /// Iterate over all module scoped macros
169 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 177 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
170 self.items 178 self.items
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
new file mode 100644
index 000000000..6e36bc0d0
--- /dev/null
+++ b/crates/ra_hir_def/src/traits.rs
@@ -0,0 +1,82 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{AsName, Name},
7 AstId,
8};
9
10use ra_syntax::ast::{self, NameOwner};
11use rustc_hash::FxHashMap;
12
13use crate::{
14 db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern,
15 LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasId,
16};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct TraitData {
20 pub name: Option<Name>,
21 pub items: Vec<AssocItemId>,
22 pub auto: bool,
23}
24
25impl TraitData {
26 pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
27 let src = tr.source(db);
28 let name = src.value.name().map(|n| n.as_name());
29 let module = tr.module(db);
30 let ctx = LocationCtx::new(db, module, src.file_id);
31 let auto = src.value.is_auto();
32 let ast_id_map = db.ast_id_map(src.file_id);
33 let items = if let Some(item_list) = src.value.item_list() {
34 item_list
35 .impl_items()
36 .map(|item_node| match item_node {
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(),
43 ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(),
44 ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(),
45 })
46 .collect()
47 } else {
48 Vec::new()
49 };
50 Arc::new(TraitData { name, items, auto })
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct TraitItemsIndex {
56 traits_by_def: FxHashMap<AssocItemId, TraitId>,
57}
58
59impl TraitItemsIndex {
60 pub fn trait_items_index(db: &impl DefDatabase2, module: ModuleId) -> TraitItemsIndex {
61 let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
62 let crate_def_map = db.crate_def_map(module.krate);
63 for decl in crate_def_map[module.module_id].scope.declarations() {
64 if let ModuleDefId::TraitId(tr) = decl {
65 for item in db.trait_data(tr).items.iter() {
66 match item {
67 AssocItemId::FunctionId(_) => (),
68 _ => {
69 let prev = index.traits_by_def.insert(*item, tr);
70 assert!(prev.is_none());
71 }
72 }
73 }
74 }
75 }
76 index
77 }
78
79 pub fn get_parent_trait(&self, item: AssocItemId) -> Option<TraitId> {
80 self.traits_by_def.get(&item).cloned()
81 }
82}
diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide_api/src/expand.rs
index 0ad125a9e..2f1abf509 100644
--- a/crates/ra_ide_api/src/expand.rs
+++ b/crates/ra_ide_api/src/expand.rs
@@ -55,7 +55,7 @@ pub(crate) fn descend_into_macros(
55 } 55 }
56 let source_analyzer = 56 let source_analyzer =
57 hir::SourceAnalyzer::new(db, token.with_value(token.value.parent()).as_ref(), None); 57 hir::SourceAnalyzer::new(db, token.with_value(token.value.parent()).as_ref(), None);
58 let exp = source_analyzer.expand(db, &macro_call)?; 58 let exp = source_analyzer.expand(db, token.with_value(&macro_call))?;
59 exp.map_token_down(db, token.as_ref()) 59 exp.map_token_down(db, token.as_ref())
60 }) 60 })
61 .last() 61 .last()
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs
index 2d478ec09..7f39262dc 100644
--- a/crates/ra_ide_api/src/expand_macro.rs
+++ b/crates/ra_ide_api/src/expand_macro.rs
@@ -23,7 +23,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
23 let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; 23 let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?;
24 24
25 let source = hir::Source::new(position.file_id.into(), mac.syntax()); 25 let source = hir::Source::new(position.file_id.into(), mac.syntax());
26 let expanded = expand_macro_recur(db, source, &mac)?; 26 let expanded = expand_macro_recur(db, source, source.with_value(&mac))?;
27 27
28 // FIXME: 28 // FIXME:
29 // macro expansion may lose all white space information 29 // macro expansion may lose all white space information
@@ -35,10 +35,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
35fn expand_macro_recur( 35fn expand_macro_recur(
36 db: &RootDatabase, 36 db: &RootDatabase,
37 source: hir::Source<&SyntaxNode>, 37 source: hir::Source<&SyntaxNode>,
38 macro_call: &ast::MacroCall, 38 macro_call: hir::Source<&ast::MacroCall>,
39) -> Option<SyntaxNode> { 39) -> Option<SyntaxNode> {
40 let analyzer = hir::SourceAnalyzer::new(db, source, None); 40 let analyzer = hir::SourceAnalyzer::new(db, source, None);
41 let expansion = analyzer.expand(db, &macro_call)?; 41 let expansion = analyzer.expand(db, macro_call)?;
42 let macro_file_id = expansion.file_id(); 42 let macro_file_id = expansion.file_id();
43 let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; 43 let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?;
44 44
@@ -46,8 +46,8 @@ fn expand_macro_recur(
46 let mut replaces = FxHashMap::default(); 46 let mut replaces = FxHashMap::default();
47 47
48 for child in children.into_iter() { 48 for child in children.into_iter() {
49 let source = hir::Source::new(macro_file_id, source.value); 49 let node = hir::Source::new(macro_file_id, &child);
50 let new_node = expand_macro_recur(db, source, &child)?; 50 let new_node = expand_macro_recur(db, source, node)?;
51 51
52 replaces.insert(child.syntax().clone().into(), new_node.into()); 52 replaces.insert(child.syntax().clone().into(), new_node.into());
53 } 53 }
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 }