aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/adt.rs161
-rw-r--r--crates/ra_hir_def/src/attr.rs112
-rw-r--r--crates/ra_hir_def/src/body.rs16
-rw-r--r--crates/ra_hir_def/src/body/lower.rs6
-rw-r--r--crates/ra_hir_def/src/body/scope.rs6
-rw-r--r--crates/ra_hir_def/src/data.rs217
-rw-r--r--crates/ra_hir_def/src/db.rs60
-rw-r--r--crates/ra_hir_def/src/docs.rs68
-rw-r--r--crates/ra_hir_def/src/generics.rs8
-rw-r--r--crates/ra_hir_def/src/impls.rs86
-rw-r--r--crates/ra_hir_def/src/lang_item.rs120
-rw-r--r--crates/ra_hir_def/src/lib.rs163
-rw-r--r--crates/ra_hir_def/src/nameres.rs83
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs79
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs17
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs54
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir_def/src/per_ns.rs (renamed from crates/ra_hir_def/src/nameres/per_ns.rs)0
-rw-r--r--crates/ra_hir_def/src/resolver.rs75
-rw-r--r--crates/ra_hir_def/src/test_db.rs2
-rw-r--r--crates/ra_hir_def/src/trace.rs49
-rw-r--r--crates/ra_hir_def/src/traits.rs66
24 files changed, 967 insertions, 491 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index d04f54e15..20e9a1eb5 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -2,13 +2,17 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::name::{AsName, Name}; 5use hir_expand::{
6use ra_arena::Arena; 6 either::Either,
7 name::{AsName, Name},
8 Source,
9};
10use ra_arena::{map::ArenaMap, Arena};
7use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 11use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
8 12
9use crate::{ 13use crate::{
10 db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, 14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource,
11 LocalStructFieldId, StructOrUnionId, 15 LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId,
12}; 16};
13 17
14/// Note that we use `StructData` for unions as well! 18/// Note that we use `StructData` for unions as well!
@@ -30,13 +34,9 @@ pub struct EnumVariantData {
30 pub variant_data: Arc<VariantData>, 34 pub variant_data: Arc<VariantData>,
31} 35}
32 36
33/// Fields of an enum variant or struct
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct VariantData(VariantDataInner);
36
37#[derive(Debug, Clone, PartialEq, Eq)] 37#[derive(Debug, Clone, PartialEq, Eq)]
38enum VariantDataInner { 38pub enum VariantData {
39 Struct(Arena<LocalStructFieldId, StructFieldData>), 39 Record(Arena<LocalStructFieldId, StructFieldData>),
40 Tuple(Arena<LocalStructFieldId, StructFieldData>), 40 Tuple(Arena<LocalStructFieldId, StructFieldData>),
41 Unit, 41 Unit,
42} 42}
@@ -49,10 +49,7 @@ pub struct StructFieldData {
49} 49}
50 50
51impl StructData { 51impl StructData {
52 pub(crate) fn struct_data_query( 52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> {
53 db: &impl DefDatabase2,
54 id: StructOrUnionId,
55 ) -> Arc<StructData> {
56 let src = id.source(db); 53 let src = id.source(db);
57 let name = src.value.name().map(|n| n.as_name()); 54 let name = src.value.name().map(|n| n.as_name());
58 let variant_data = VariantData::new(src.value.kind()); 55 let variant_data = VariantData::new(src.value.kind());
@@ -62,20 +59,12 @@ impl StructData {
62} 59}
63 60
64impl EnumData { 61impl EnumData {
65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> { 62 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> {
66 let src = e.source(db); 63 let src = e.source(db);
67 let name = src.value.name().map(|n| n.as_name()); 64 let name = src.value.name().map(|n| n.as_name());
68 let variants = src 65 let mut trace = Trace::new_for_arena();
69 .value 66 lower_enum(&mut trace, &src.value);
70 .variant_list() 67 Arc::new(EnumData { name, variants: trace.into_arena() })
71 .into_iter()
72 .flat_map(|it| it.variants())
73 .map(|var| EnumVariantData {
74 name: var.name().map(|it| it.as_name()),
75 variant_data: Arc::new(VariantData::new(var.kind())),
76 })
77 .collect();
78 Arc::new(EnumData { name, variants })
79 } 68 }
80 69
81 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 70 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
@@ -84,39 +73,109 @@ impl EnumData {
84 } 73 }
85} 74}
86 75
76impl HasChildSource for EnumId {
77 type ChildId = LocalEnumVariantId;
78 type Value = ast::EnumVariant;
79 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> {
80 let src = self.source(db);
81 let mut trace = Trace::new_for_map();
82 lower_enum(&mut trace, &src.value);
83 src.with_value(trace.into_map())
84 }
85}
86
87fn lower_enum(
88 trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>,
89 ast: &ast::EnumDef,
90) {
91 for var in ast.variant_list().into_iter().flat_map(|it| it.variants()) {
92 trace.alloc(
93 || var.clone(),
94 || EnumVariantData {
95 name: var.name().map(|it| it.as_name()),
96 variant_data: Arc::new(VariantData::new(var.kind())),
97 },
98 )
99 }
100}
101
87impl VariantData { 102impl VariantData {
88 fn new(flavor: ast::StructKind) -> Self { 103 fn new(flavor: ast::StructKind) -> Self {
89 let inner = match flavor { 104 let mut trace = Trace::new_for_arena();
90 ast::StructKind::Tuple(fl) => { 105 match lower_struct(&mut trace, &flavor) {
91 let fields = fl 106 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
92 .fields() 107 StructKind::Record => VariantData::Record(trace.into_arena()),
93 .enumerate() 108 StructKind::Unit => VariantData::Unit,
94 .map(|(i, fd)| StructFieldData { 109 }
110 }
111
112 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
113 match &self {
114 VariantData::Record(fields) | VariantData::Tuple(fields) => Some(fields),
115 _ => None,
116 }
117 }
118}
119
120impl HasChildSource for VariantId {
121 type ChildId = LocalStructFieldId;
122 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
123
124 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> {
125 let src = match self {
126 VariantId::EnumVariantId(it) => {
127 // I don't really like the fact that we call into parent source
128 // here, this might add to more queries then necessary.
129 let src = it.parent.child_source(db);
130 src.map(|map| map[it.local_id].kind())
131 }
132 VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()),
133 };
134 let mut trace = Trace::new_for_map();
135 lower_struct(&mut trace, &src.value);
136 src.with_value(trace.into_map())
137 }
138}
139
140enum StructKind {
141 Tuple,
142 Record,
143 Unit,
144}
145
146fn lower_struct(
147 trace: &mut Trace<
148 LocalStructFieldId,
149 StructFieldData,
150 Either<ast::TupleFieldDef, ast::RecordFieldDef>,
151 >,
152 ast: &ast::StructKind,
153) -> StructKind {
154 match ast {
155 ast::StructKind::Tuple(fl) => {
156 for (i, fd) in fl.fields().enumerate() {
157 trace.alloc(
158 || Either::A(fd.clone()),
159 || StructFieldData {
95 name: Name::new_tuple_field(i), 160 name: Name::new_tuple_field(i),
96 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 161 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
97 }) 162 },
98 .collect(); 163 )
99 VariantDataInner::Tuple(fields)
100 } 164 }
101 ast::StructKind::Named(fl) => { 165 StructKind::Tuple
102 let fields = fl 166 }
103 .fields() 167 ast::StructKind::Record(fl) => {
104 .map(|fd| StructFieldData { 168 for fd in fl.fields() {
169 trace.alloc(
170 || Either::B(fd.clone()),
171 || StructFieldData {
105 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 172 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
106 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 173 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
107 }) 174 },
108 .collect(); 175 )
109 VariantDataInner::Struct(fields)
110 } 176 }
111 ast::StructKind::Unit => VariantDataInner::Unit, 177 StructKind::Record
112 };
113 VariantData(inner)
114 }
115
116 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
117 match &self.0 {
118 VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
119 _ => None,
120 } 178 }
179 ast::StructKind::Unit => StructKind::Unit,
121 } 180 }
122} 181}
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 0e961ca12..48ce8cd93 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -1,8 +1,8 @@
1//! A higher level attributes based on TokenTree, with also some shortcuts. 1//! A higher level attributes based on TokenTree, with also some shortcuts.
2 2
3use std::sync::Arc; 3use std::{ops, sync::Arc};
4 4
5use hir_expand::hygiene::Hygiene; 5use hir_expand::{either::Either, hygiene::Hygiene, AstId};
6use mbe::ast_to_token_tree; 6use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions; 7use ra_cfg::CfgOptions;
8use ra_syntax::{ 8use ra_syntax::{
@@ -11,7 +11,81 @@ use ra_syntax::{
11}; 11};
12use tt::Subtree; 12use tt::Subtree;
13 13
14use crate::path::Path; 14use crate::{
15 db::DefDatabase, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup,
16};
17
18#[derive(Default, Debug, Clone, PartialEq, Eq)]
19pub struct Attrs {
20 entries: Option<Arc<[Attr]>>,
21}
22
23impl ops::Deref for Attrs {
24 type Target = [Attr];
25
26 fn deref(&self) -> &[Attr] {
27 match &self.entries {
28 Some(it) => &*it,
29 None => &[],
30 }
31 }
32}
33
34impl Attrs {
35 pub(crate) fn attrs_query(db: &impl DefDatabase, def: AttrDefId) -> Attrs {
36 match def {
37 AttrDefId::ModuleId(module) => {
38 let def_map = db.crate_def_map(module.krate);
39 let src = match def_map[module.module_id].declaration_source(db) {
40 Some(it) => it,
41 None => return Attrs::default(),
42 };
43 let hygiene = Hygiene::new(db, src.file_id);
44 Attr::from_attrs_owner(&src.value, &hygiene)
45 }
46 AttrDefId::StructFieldId(it) => {
47 let src = it.parent.child_source(db);
48 match &src.value[it.local_id] {
49 Either::A(_tuple) => Attrs::default(),
50 Either::B(record) => {
51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(record, &hygiene)
53 }
54 }
55 }
56 AttrDefId::EnumVariantId(it) => {
57 let src = it.parent.child_source(db);
58 let hygiene = Hygiene::new(db, src.file_id);
59 Attr::from_attrs_owner(&src.value[it.local_id], &hygiene)
60 }
61 AttrDefId::AdtId(it) => match it {
62 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
63 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
64 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
65 },
66 AttrDefId::StaticId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
67 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
68 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
69 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
70 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
71 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
72 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db),
73 }
74 }
75
76 pub fn has_atom(&self, atom: &str) -> bool {
77 self.iter().any(|it| it.is_simple_atom(atom))
78 }
79
80 pub fn find_string_value(&self, key: &str) -> Option<SmolStr> {
81 self.iter().filter(|attr| attr.is_simple_atom(key)).find_map(|attr| {
82 match attr.input.as_ref()? {
83 AttrInput::Literal(it) => Some(it.clone()),
84 _ => None,
85 }
86 })
87 }
88}
15 89
16#[derive(Debug, Clone, PartialEq, Eq)] 90#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Attr { 91pub struct Attr {
@@ -43,13 +117,15 @@ impl Attr {
43 Some(Attr { path, input }) 117 Some(Attr { path, input })
44 } 118 }
45 119
46 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Option<Arc<[Attr]>> { 120 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
47 let mut attrs = owner.attrs().peekable(); 121 let mut attrs = owner.attrs().peekable();
48 if attrs.peek().is_none() { 122 let entries = if attrs.peek().is_none() {
49 // Avoid heap allocation 123 // Avoid heap allocation
50 return None; 124 None
51 } 125 } else {
52 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect()) 126 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
127 };
128 Attrs { entries }
53 } 129 }
54 130
55 pub fn is_simple_atom(&self, name: &str) -> bool { 131 pub fn is_simple_atom(&self, name: &str) -> bool {
@@ -82,3 +158,23 @@ impl Attr {
82 cfg_options.is_cfg_enabled(self.as_cfg()?) 158 cfg_options.is_cfg_enabled(self.as_cfg()?)
83 } 159 }
84} 160}
161
162fn attrs_from_ast<D, N>(src: AstId<N>, db: &D) -> Attrs
163where
164 N: ast::AttrsOwner,
165 D: DefDatabase,
166{
167 let hygiene = Hygiene::new(db, src.file_id());
168 Attr::from_attrs_owner(&src.to_node(db), &hygiene)
169}
170
171fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs
172where
173 T: HasSource,
174 T::Value: ast::AttrsOwner,
175 D: DefDatabase,
176{
177 let src = node.source(db);
178 let hygiene = Hygiene::new(db, src.file_id);
179 Attr::from_attrs_owner(&src.value, &hygiene)
180}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index dfb79a30a..225638b42 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -13,7 +13,7 @@ use ra_syntax::{ast, AstNode, AstPtr};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14 14
15use crate::{ 15use crate::{
16 db::DefDatabase2, 16 db::DefDatabase,
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
@@ -28,7 +28,7 @@ pub struct Expander {
28} 28}
29 29
30impl Expander { 30impl Expander {
31 pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { 31 pub fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 32 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 33 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 34 Expander { crate_def_map, current_file_id, hygiene, module }
@@ -36,7 +36,7 @@ impl Expander {
36 36
37 fn enter_expand( 37 fn enter_expand(
38 &mut self, 38 &mut self,
39 db: &impl DefDatabase2, 39 db: &impl DefDatabase,
40 macro_call: ast::MacroCall, 40 macro_call: ast::MacroCall,
41 ) -> Option<(Mark, ast::Expr)> { 41 ) -> Option<(Mark, ast::Expr)> {
42 let ast_id = AstId::new( 42 let ast_id = AstId::new(
@@ -67,7 +67,7 @@ impl Expander {
67 None 67 None
68 } 68 }
69 69
70 fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) { 70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 71 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 72 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 73 std::mem::forget(mark);
@@ -81,7 +81,7 @@ impl Expander {
81 Path::from_src(path, &self.hygiene) 81 Path::from_src(path, &self.hygiene)
82 } 82 }
83 83
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> { 84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
85 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() 85 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros()
86 } 86 }
87} 87}
@@ -142,7 +142,7 @@ pub struct BodySourceMap {
142 142
143impl Body { 143impl Body {
144 pub(crate) fn body_with_source_map_query( 144 pub(crate) fn body_with_source_map_query(
145 db: &impl DefDatabase2, 145 db: &impl DefDatabase,
146 def: DefWithBodyId, 146 def: DefWithBodyId,
147 ) -> (Arc<Body>, Arc<BodySourceMap>) { 147 ) -> (Arc<Body>, Arc<BodySourceMap>) {
148 let mut params = None; 148 let mut params = None;
@@ -169,12 +169,12 @@ impl Body {
169 (Arc::new(body), Arc::new(source_map)) 169 (Arc::new(body), Arc::new(source_map))
170 } 170 }
171 171
172 pub(crate) fn body_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc<Body> { 172 pub(crate) fn body_query(db: &impl DefDatabase, def: DefWithBodyId) -> Arc<Body> {
173 db.body_with_source_map(def).0 173 db.body_with_source_map(def).0
174 } 174 }
175 175
176 fn new( 176 fn new(
177 db: &impl DefDatabase2, 177 db: &impl DefDatabase,
178 expander: Expander, 178 expander: Expander,
179 params: Option<ast::ParamList>, 179 params: Option<ast::ParamList>,
180 body: Option<ast::Expr>, 180 body: Option<ast::Expr>,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index d8e911aa5..f4640dfa4 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -17,7 +17,7 @@ use test_utils::tested_by;
17use crate::{ 17use crate::{
18 body::{Body, BodySourceMap, Expander, PatPtr}, 18 body::{Body, BodySourceMap, Expander, PatPtr},
19 builtin_type::{BuiltinFloat, BuiltinInt}, 19 builtin_type::{BuiltinFloat, BuiltinInt},
20 db::DefDatabase2, 20 db::DefDatabase,
21 expr::{ 21 expr::{
22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
@@ -28,7 +28,7 @@ use crate::{
28}; 28};
29 29
30pub(super) fn lower( 30pub(super) fn lower(
31 db: &impl DefDatabase2, 31 db: &impl DefDatabase,
32 expander: Expander, 32 expander: Expander,
33 params: Option<ast::ParamList>, 33 params: Option<ast::ParamList>,
34 body: Option<ast::Expr>, 34 body: Option<ast::Expr>,
@@ -57,7 +57,7 @@ struct ExprCollector<DB> {
57 57
58impl<'a, DB> ExprCollector<&'a DB> 58impl<'a, DB> ExprCollector<&'a DB>
59where 59where
60 DB: DefDatabase2, 60 DB: DefDatabase,
61{ 61{
62 fn collect( 62 fn collect(
63 mut self, 63 mut self,
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 58740b679..20d707bc4 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -7,7 +7,7 @@ use rustc_hash::FxHashMap;
7 7
8use crate::{ 8use crate::{
9 body::Body, 9 body::Body,
10 db::DefDatabase2, 10 db::DefDatabase,
11 expr::{Expr, ExprId, Pat, PatId, Statement}, 11 expr::{Expr, ExprId, Pat, PatId, Statement},
12 DefWithBodyId, 12 DefWithBodyId,
13}; 13};
@@ -45,7 +45,7 @@ pub struct ScopeData {
45} 45}
46 46
47impl ExprScopes { 47impl ExprScopes {
48 pub(crate) fn expr_scopes_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc<ExprScopes> { 48 pub(crate) fn expr_scopes_query(db: &impl DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
49 let body = db.body(def); 49 let body = db.body(def);
50 Arc::new(ExprScopes::new(&*body)) 50 Arc::new(ExprScopes::new(&*body))
51 } 51 }
@@ -176,7 +176,7 @@ mod tests {
176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
177 use test_utils::{assert_eq_text, covers, extract_offset}; 177 use test_utils::{assert_eq_text, covers, extract_offset};
178 178
179 use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; 179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
180 180
181 fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { 181 fn find_function(db: &TestDB, file_id: FileId) -> FunctionId {
182 let krate = db.test_crate(); 182 let krate = db.test_crate();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
new file mode 100644
index 000000000..f0b3e198a
--- /dev/null
+++ b/crates/ra_hir_def/src/data.rs
@@ -0,0 +1,217 @@
1//! Contains basic data about various HIR declarations.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{self, AsName, Name},
7 AstId,
8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
10
11use crate::{
12 db::DefDatabase,
13 type_ref::{Mutability, TypeRef},
14 AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource,
15 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
16};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct FunctionData {
20 pub name: Name,
21 pub params: Vec<TypeRef>,
22 pub ret_type: TypeRef,
23 /// True if the first param is `self`. This is relevant to decide whether this
24 /// can be called as a method.
25 pub has_self_param: bool,
26}
27
28impl FunctionData {
29 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
30 let src = func.lookup(db).source(db);
31 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
32 let mut params = Vec::new();
33 let mut has_self_param = false;
34 if let Some(param_list) = src.value.param_list() {
35 if let Some(self_param) = param_list.self_param() {
36 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
37 TypeRef::from_ast(type_ref)
38 } else {
39 let self_type = TypeRef::Path(name::SELF_TYPE.into());
40 match self_param.kind() {
41 ast::SelfParamKind::Owned => self_type,
42 ast::SelfParamKind::Ref => {
43 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
44 }
45 ast::SelfParamKind::MutRef => {
46 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
47 }
48 }
49 };
50 params.push(self_type);
51 has_self_param = true;
52 }
53 for param in param_list.params() {
54 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
55 params.push(type_ref);
56 }
57 }
58 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
59 TypeRef::from_ast(type_ref)
60 } else {
61 TypeRef::unit()
62 };
63
64 let sig = FunctionData { name, params, ret_type, has_self_param };
65 Arc::new(sig)
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct TypeAliasData {
71 pub name: Name,
72 pub type_ref: Option<TypeRef>,
73}
74
75impl TypeAliasData {
76 pub(crate) fn type_alias_data_query(
77 db: &impl DefDatabase,
78 typ: TypeAliasId,
79 ) -> Arc<TypeAliasData> {
80 let node = typ.lookup(db).source(db).value;
81 let name = node.name().map_or_else(Name::missing, |n| n.as_name());
82 let type_ref = node.type_ref().map(TypeRef::from_ast);
83 Arc::new(TypeAliasData { name, type_ref })
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct TraitData {
89 pub name: Option<Name>,
90 pub items: Vec<AssocItemId>,
91 pub auto: bool,
92}
93
94impl TraitData {
95 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> {
96 let src = tr.source(db);
97 let name = src.value.name().map(|n| n.as_name());
98 let auto = src.value.is_auto();
99 let ast_id_map = db.ast_id_map(src.file_id);
100 let items = if let Some(item_list) = src.value.item_list() {
101 item_list
102 .impl_items()
103 .map(|item_node| match item_node {
104 ast::ImplItem::FnDef(it) => FunctionLoc {
105 container: ContainerId::TraitId(tr),
106 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
107 }
108 .intern(db)
109 .into(),
110 ast::ImplItem::ConstDef(it) => ConstLoc {
111 container: ContainerId::TraitId(tr),
112 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
113 }
114 .intern(db)
115 .into(),
116 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
117 container: ContainerId::TraitId(tr),
118 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
119 }
120 .intern(db)
121 .into(),
122 })
123 .collect()
124 } else {
125 Vec::new()
126 };
127 Arc::new(TraitData { name, items, auto })
128 }
129
130 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
131 self.items.iter().filter_map(|item| match item {
132 AssocItemId::TypeAliasId(t) => Some(*t),
133 _ => None,
134 })
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct ImplData {
140 pub target_trait: Option<TypeRef>,
141 pub target_type: TypeRef,
142 pub items: Vec<AssocItemId>,
143 pub is_negative: bool,
144}
145
146impl ImplData {
147 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
148 let src = id.source(db);
149 let items = db.ast_id_map(src.file_id);
150
151 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
152 let target_type = TypeRef::from_ast_opt(src.value.target_type());
153 let is_negative = src.value.is_negative();
154
155 let items = if let Some(item_list) = src.value.item_list() {
156 item_list
157 .impl_items()
158 .map(|item_node| match item_node {
159 ast::ImplItem::FnDef(it) => {
160 let def = FunctionLoc {
161 container: ContainerId::ImplId(id),
162 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
163 }
164 .intern(db);
165 def.into()
166 }
167 ast::ImplItem::ConstDef(it) => {
168 let def = ConstLoc {
169 container: ContainerId::ImplId(id),
170 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
171 }
172 .intern(db);
173 def.into()
174 }
175 ast::ImplItem::TypeAliasDef(it) => {
176 let def = TypeAliasLoc {
177 container: ContainerId::ImplId(id),
178 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
179 }
180 .intern(db);
181 def.into()
182 }
183 })
184 .collect()
185 } else {
186 Vec::new()
187 };
188
189 let res = ImplData { target_trait, target_type, items, is_negative };
190 Arc::new(res)
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct ConstData {
196 pub name: Option<Name>,
197 pub type_ref: TypeRef,
198}
199
200impl ConstData {
201 pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
202 let node = konst.lookup(db).source(db).value;
203 const_data_for(&node)
204 }
205
206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
207 let node = konst.source(db).value;
208 const_data_for(&node)
209 }
210}
211
212fn const_data_for<N: NameOwner + TypeAscriptionOwner>(node: &N) -> Arc<ConstData> {
213 let name = node.name().map(|n| n.as_name());
214 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
215 let sig = ConstData { name, type_ref };
216 Arc::new(sig)
217}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 844f8bbe8..7fec2e8c0 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -3,43 +3,46 @@ use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase}; 5use ra_db::{salsa, CrateId, SourceDatabase};
6use ra_syntax::ast; 6use ra_syntax::{ast, SmolStr};
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 attr::Attrs,
10 body::{scope::ExprScopes, Body, BodySourceMap}, 11 body::{scope::ExprScopes, Body, BodySourceMap},
12 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData},
13 docs::Documentation,
11 generics::GenericParams, 14 generics::GenericParams,
12 impls::ImplData, 15 lang_item::{LangItemTarget, LangItems},
13 nameres::{ 16 nameres::{
14 raw::{ImportSourceMap, RawItems}, 17 raw::{ImportSourceMap, RawItems},
15 CrateDefMap, 18 CrateDefMap,
16 }, 19 },
17 traits::TraitData, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
18 DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId, 21 ImplId, ItemLoc, ModuleId, StaticId, StructOrUnionId, TraitId, TypeAliasId, TypeAliasLoc,
19}; 22};
20 23
21#[salsa::query_group(InternDatabaseStorage)] 24#[salsa::query_group(InternDatabaseStorage)]
22pub trait InternDatabase: SourceDatabase { 25pub trait InternDatabase: SourceDatabase {
23 #[salsa::interned] 26 #[salsa::interned]
24 fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId; 27 fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
25 #[salsa::interned] 28 #[salsa::interned]
26 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId; 29 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId;
27 #[salsa::interned] 30 #[salsa::interned]
28 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId; 31 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId;
29 #[salsa::interned] 32 #[salsa::interned]
30 fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId; 33 fn intern_const(&self, loc: ConstLoc) -> ConstId;
31 #[salsa::interned] 34 #[salsa::interned]
32 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId; 35 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> StaticId;
33 #[salsa::interned] 36 #[salsa::interned]
34 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId; 37 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId;
35 #[salsa::interned] 38 #[salsa::interned]
36 fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId; 39 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
37 #[salsa::interned] 40 #[salsa::interned]
38 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId; 41 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> ImplId;
39} 42}
40 43
41#[salsa::query_group(DefDatabase2Storage)] 44#[salsa::query_group(DefDatabaseStorage)]
42pub trait DefDatabase2: InternDatabase + AstDatabase { 45pub trait DefDatabase: InternDatabase + AstDatabase {
43 #[salsa::invoke(RawItems::raw_items_with_source_map_query)] 46 #[salsa::invoke(RawItems::raw_items_with_source_map_query)]
44 fn raw_items_with_source_map( 47 fn raw_items_with_source_map(
45 &self, 48 &self,
@@ -64,6 +67,18 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
64 #[salsa::invoke(TraitData::trait_data_query)] 67 #[salsa::invoke(TraitData::trait_data_query)]
65 fn trait_data(&self, e: TraitId) -> Arc<TraitData>; 68 fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
66 69
70 #[salsa::invoke(TypeAliasData::type_alias_data_query)]
71 fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
72
73 #[salsa::invoke(FunctionData::fn_data_query)]
74 fn function_data(&self, func: FunctionId) -> Arc<FunctionData>;
75
76 #[salsa::invoke(ConstData::const_data_query)]
77 fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
78
79 #[salsa::invoke(ConstData::static_data_query)]
80 fn static_data(&self, konst: StaticId) -> Arc<ConstData>;
81
67 #[salsa::invoke(Body::body_with_source_map_query)] 82 #[salsa::invoke(Body::body_with_source_map_query)]
68 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 83 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
69 84
@@ -75,4 +90,21 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
75 90
76 #[salsa::invoke(GenericParams::generic_params_query)] 91 #[salsa::invoke(GenericParams::generic_params_query)]
77 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; 92 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
93
94 #[salsa::invoke(Attrs::attrs_query)]
95 fn attrs(&self, def: AttrDefId) -> Attrs;
96
97 #[salsa::invoke(LangItems::module_lang_items_query)]
98 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>;
99
100 #[salsa::invoke(LangItems::crate_lang_items_query)]
101 fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
102
103 #[salsa::invoke(LangItems::lang_item_query)]
104 fn lang_item(&self, start_crate: CrateId, item: SmolStr) -> Option<LangItemTarget>;
105
106 // FIXME(https://github.com/rust-analyzer/rust-analyzer/issues/2148#issuecomment-550519102)
107 // Remove this query completely, in favor of `Attrs::docs` method
108 #[salsa::invoke(Documentation::documentation_query)]
109 fn documentation(&self, def: AttrDefId) -> Option<Documentation>;
78} 110}
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
new file mode 100644
index 000000000..69846fd1b
--- /dev/null
+++ b/crates/ra_hir_def/src/docs.rs
@@ -0,0 +1,68 @@
1//! FIXME: write short doc here
2
3use std::sync::Arc;
4
5use hir_expand::either::Either;
6use ra_syntax::ast;
7
8use crate::{db::DefDatabase, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup};
9
10/// Holds documentation
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Documentation(Arc<str>);
13
14impl Into<String> for Documentation {
15 fn into(self) -> String {
16 self.as_str().to_owned()
17 }
18}
19
20impl Documentation {
21 fn new(s: &str) -> Documentation {
22 Documentation(s.into())
23 }
24
25 pub fn as_str(&self) -> &str {
26 &*self.0
27 }
28
29 pub(crate) fn documentation_query(
30 db: &impl DefDatabase,
31 def: AttrDefId,
32 ) -> Option<Documentation> {
33 match def {
34 AttrDefId::ModuleId(module) => {
35 let def_map = db.crate_def_map(module.krate);
36 let src = def_map[module.module_id].declaration_source(db)?;
37 docs_from_ast(&src.value)
38 }
39 AttrDefId::StructFieldId(it) => {
40 let src = it.parent.child_source(db);
41 match &src.value[it.local_id] {
42 Either::A(_tuple) => None,
43 Either::B(record) => docs_from_ast(record),
44 }
45 }
46 AttrDefId::AdtId(it) => match it {
47 AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value),
48 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
49 AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value),
50 },
51 AttrDefId::EnumVariantId(it) => {
52 let src = it.parent.child_source(db);
53 docs_from_ast(&src.value[it.local_id])
54 }
55 AttrDefId::StaticId(it) => docs_from_ast(&it.source(db).value),
56 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value),
57 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)),
58 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value),
59 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
60 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value),
61 AttrDefId::ImplId(_) => None,
62 }
63 }
64}
65
66pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
67 node.doc_comment_text().map(|it| Documentation::new(&it))
68}
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 9e2e4c3cc..015fe772e 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -8,7 +8,7 @@ use hir_expand::name::{self, AsName, Name};
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 9
10use crate::{ 10use crate::{
11 db::DefDatabase2, 11 db::DefDatabase,
12 type_ref::{TypeBound, TypeRef}, 12 type_ref::{TypeBound, TypeRef},
13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, 13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup,
14}; 14};
@@ -42,7 +42,7 @@ pub struct WherePredicate {
42 42
43impl GenericParams { 43impl GenericParams {
44 pub(crate) fn generic_params_query( 44 pub(crate) fn generic_params_query(
45 db: &impl DefDatabase2, 45 db: &impl DefDatabase,
46 def: GenericDefId, 46 def: GenericDefId,
47 ) -> Arc<GenericParams> { 47 ) -> Arc<GenericParams> {
48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); 48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it));
@@ -50,7 +50,7 @@ impl GenericParams {
50 } 50 }
51 51
52 fn new( 52 fn new(
53 db: &impl DefDatabase2, 53 db: &impl DefDatabase,
54 def: GenericDefId, 54 def: GenericDefId,
55 parent_params: Option<Arc<GenericParams>>, 55 parent_params: Option<Arc<GenericParams>>,
56 ) -> GenericParams { 56 ) -> GenericParams {
@@ -168,7 +168,7 @@ impl GenericParams {
168 } 168 }
169} 169}
170 170
171fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option<GenericDefId> { 171fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
172 let container = match def { 172 let container = match def {
173 GenericDefId::FunctionId(it) => it.lookup(db).container, 173 GenericDefId::FunctionId(it) => it.lookup(db).container,
174 GenericDefId::TypeAliasId(it) => it.lookup(db).container, 174 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs
deleted file mode 100644
index 750a869f2..000000000
--- a/crates/ra_hir_def/src/impls.rs
+++ /dev/null
@@ -1,86 +0,0 @@
1//! Defines hir-level representation of impls.
2//!
3//! The handling is similar, but is not quite the same as for other items,
4//! because `impl`s don't have names.
5
6use std::sync::Arc;
7
8use hir_expand::AstId;
9use ra_syntax::ast;
10
11use crate::{
12 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
13 FunctionLoc, ImplId, Intern, TypeAliasLoc,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ImplData {
18 target_trait: Option<TypeRef>,
19 target_type: TypeRef,
20 items: Vec<AssocItemId>,
21 negative: bool,
22}
23
24impl ImplData {
25 pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
26 let src = id.source(db);
27 let items = db.ast_id_map(src.file_id);
28
29 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
30 let target_type = TypeRef::from_ast_opt(src.value.target_type());
31 let negative = src.value.is_negative();
32
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) => {
38 let def = FunctionLoc {
39 container: ContainerId::ImplId(id),
40 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
41 }
42 .intern(db);
43 def.into()
44 }
45 ast::ImplItem::ConstDef(it) => {
46 let def = ConstLoc {
47 container: ContainerId::ImplId(id),
48 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
49 }
50 .intern(db);
51 def.into()
52 }
53 ast::ImplItem::TypeAliasDef(it) => {
54 let def = TypeAliasLoc {
55 container: ContainerId::ImplId(id),
56 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
57 }
58 .intern(db);
59 def.into()
60 }
61 })
62 .collect()
63 } else {
64 Vec::new()
65 };
66
67 let res = ImplData { target_trait, target_type, items, negative };
68 Arc::new(res)
69 }
70
71 pub fn target_trait(&self) -> Option<&TypeRef> {
72 self.target_trait.as_ref()
73 }
74
75 pub fn target_type(&self) -> &TypeRef {
76 &self.target_type
77 }
78
79 pub fn items(&self) -> &[AssocItemId] {
80 &self.items
81 }
82
83 pub fn is_negative(&self) -> bool {
84 self.negative
85 }
86}
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
new file mode 100644
index 000000000..df951c533
--- /dev/null
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -0,0 +1,120 @@
1//! Collects lang items: items marked with `#[lang = "..."]` attribute.
2//!
3//! This attribute to tell the compiler about semi built-in std library
4//! features, such as Fn family of traits.
5use std::sync::Arc;
6
7use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap;
9
10use crate::{
11 db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId,
12 StaticId, StructId, TraitId,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum LangItemTarget {
17 EnumId(EnumId),
18 FunctionId(FunctionId),
19 ImplBlockId(ImplId),
20 StaticId(StaticId),
21 StructId(StructId),
22 TraitId(TraitId),
23}
24
25#[derive(Default, Debug, Clone, PartialEq, Eq)]
26pub struct LangItems {
27 items: FxHashMap<SmolStr, LangItemTarget>,
28}
29
30impl LangItems {
31 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
32 self.items.get(item)
33 }
34
35 /// Salsa query. This will look for lang items in a specific crate.
36 pub(crate) fn crate_lang_items_query(db: &impl DefDatabase, krate: CrateId) -> Arc<LangItems> {
37 let mut lang_items = LangItems::default();
38
39 let crate_def_map = db.crate_def_map(krate);
40
41 crate_def_map
42 .modules()
43 .filter_map(|module_id| db.module_lang_items(ModuleId { krate, module_id }))
44 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
45
46 Arc::new(lang_items)
47 }
48
49 pub(crate) fn module_lang_items_query(
50 db: &impl DefDatabase,
51 module: ModuleId,
52 ) -> Option<Arc<LangItems>> {
53 let mut lang_items = LangItems::default();
54 lang_items.collect_lang_items(db, module);
55 if lang_items.items.is_empty() {
56 None
57 } else {
58 Some(Arc::new(lang_items))
59 }
60 }
61
62 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
63 /// traversing its dependencies.
64 pub(crate) fn lang_item_query(
65 db: &impl DefDatabase,
66 start_crate: CrateId,
67 item: SmolStr,
68 ) -> Option<LangItemTarget> {
69 let lang_items = db.crate_lang_items(start_crate);
70 let start_crate_target = lang_items.items.get(&item);
71 if let Some(target) = start_crate_target {
72 return Some(*target);
73 }
74 db.crate_graph()
75 .dependencies(start_crate)
76 .find_map(|dep| db.lang_item(dep.crate_id, item.clone()))
77 }
78
79 fn collect_lang_items(&mut self, db: &impl DefDatabase, module: ModuleId) {
80 // Look for impl targets
81 let def_map = db.crate_def_map(module.krate);
82 let module_data = &def_map[module.module_id];
83 for &impl_block in module_data.impls.iter() {
84 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
85 }
86
87 for def in module_data.scope.declarations() {
88 match def {
89 ModuleDefId::TraitId(trait_) => {
90 self.collect_lang_item(db, trait_, LangItemTarget::TraitId)
91 }
92 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
93 self.collect_lang_item(db, e, LangItemTarget::EnumId)
94 }
95 ModuleDefId::AdtId(AdtId::StructId(s)) => {
96 self.collect_lang_item(db, s, LangItemTarget::StructId)
97 }
98 ModuleDefId::FunctionId(f) => {
99 self.collect_lang_item(db, f, LangItemTarget::FunctionId)
100 }
101 ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId),
102 _ => {}
103 }
104 }
105 }
106
107 fn collect_lang_item<T>(
108 &mut self,
109 db: &impl DefDatabase,
110 item: T,
111 constructor: fn(T) -> LangItemTarget,
112 ) where
113 T: Into<AttrDefId> + Copy,
114 {
115 let attrs = db.attrs(item.into());
116 if let Some(lang_item_name) = attrs.find_string_value("lang") {
117 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
118 }
119 }
120}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index d579f5c7e..1d195d65d 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,103 +13,48 @@ 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 impls;
17pub mod diagnostics; 16pub mod diagnostics;
18pub mod expr; 17pub mod expr;
19pub mod body; 18pub mod body;
20pub mod generics; 19pub mod generics;
21pub mod traits;
22pub mod resolver; 20pub mod resolver;
21pub mod data;
22pub mod lang_item;
23pub mod docs;
24pub mod per_ns;
25
26mod trace;
27mod nameres;
23 28
24#[cfg(test)] 29#[cfg(test)]
25mod test_db; 30mod test_db;
26#[cfg(test)] 31#[cfg(test)]
27mod marks; 32mod marks;
28 33
29// FIXME: this should be private
30pub mod nameres;
31
32use std::hash::{Hash, Hasher}; 34use std::hash::{Hash, Hasher};
33 35
34use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, Source}; 36use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source};
35use ra_arena::{impl_arena_id, RawId}; 37use ra_arena::{impl_arena_id, map::ArenaMap, RawId};
36use ra_db::{salsa, CrateId, FileId}; 38use ra_db::{salsa, CrateId};
37use ra_syntax::{ast, AstNode, SyntaxNode}; 39use ra_syntax::{ast, AstNode};
38 40
39use crate::{builtin_type::BuiltinType, db::InternDatabase}; 41use crate::{builtin_type::BuiltinType, db::InternDatabase};
40 42
41pub enum ModuleSource { 43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
42 SourceFile(ast::SourceFile), 44pub struct LocalImportId(RawId);
43 Module(ast::Module), 45impl_arena_id!(LocalImportId);
44}
45
46impl ModuleSource {
47 pub fn new(
48 db: &impl db::DefDatabase2,
49 file_id: Option<FileId>,
50 decl_id: Option<AstId<ast::Module>>,
51 ) -> ModuleSource {
52 match (file_id, decl_id) {
53 (Some(file_id), _) => {
54 let source_file = db.parse(file_id).tree();
55 ModuleSource::SourceFile(source_file)
56 }
57 (None, Some(item_id)) => {
58 let module = item_id.to_node(db);
59 assert!(module.item_list().is_some(), "expected inline module");
60 ModuleSource::Module(module)
61 }
62 (None, None) => panic!(),
63 }
64 }
65
66 // FIXME: this methods do not belong here
67 pub fn from_position(
68 db: &impl db::DefDatabase2,
69 position: ra_db::FilePosition,
70 ) -> ModuleSource {
71 let parse = db.parse(position.file_id);
72 match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
73 parse.tree().syntax(),
74 position.offset,
75 ) {
76 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
77 _ => {
78 let source_file = parse.tree();
79 ModuleSource::SourceFile(source_file)
80 }
81 }
82 }
83
84 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource {
85 if let Some(m) =
86 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
87 {
88 ModuleSource::Module(m)
89 } else {
90 let file_id = child.file_id.original_file(db);
91 let source_file = db.parse(file_id).tree();
92 ModuleSource::SourceFile(source_file)
93 }
94 }
95
96 pub fn from_file_id(db: &impl db::DefDatabase2, file_id: FileId) -> ModuleSource {
97 let source_file = db.parse(file_id).tree();
98 ModuleSource::SourceFile(source_file)
99 }
100}
101 46
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
103pub struct ModuleId { 48pub struct ModuleId {
104 pub krate: CrateId, 49 pub krate: CrateId,
105 pub module_id: CrateModuleId, 50 pub module_id: LocalModuleId,
106} 51}
107 52
108/// An ID of a module, **local** to a specific crate 53/// An ID of a module, **local** to a specific crate
109// FIXME: rename to `LocalModuleId`. 54// FIXME: rename to `LocalModuleId`.
110#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 55#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
111pub struct CrateModuleId(RawId); 56pub struct LocalModuleId(RawId);
112impl_arena_id!(CrateModuleId); 57impl_arena_id!(LocalModuleId);
113 58
114macro_rules! impl_intern_key { 59macro_rules! impl_intern_key {
115 ($name:ident) => { 60 ($name:ident) => {
@@ -208,14 +153,14 @@ pub struct FunctionLoc {
208 153
209impl Intern for FunctionLoc { 154impl Intern for FunctionLoc {
210 type ID = FunctionId; 155 type ID = FunctionId;
211 fn intern(self, db: &impl db::DefDatabase2) -> FunctionId { 156 fn intern(self, db: &impl db::DefDatabase) -> FunctionId {
212 db.intern_function(self) 157 db.intern_function(self)
213 } 158 }
214} 159}
215 160
216impl Lookup for FunctionId { 161impl Lookup for FunctionId {
217 type Data = FunctionLoc; 162 type Data = FunctionLoc;
218 fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc { 163 fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc {
219 db.lookup_intern_function(*self) 164 db.lookup_intern_function(*self)
220 } 165 }
221} 166}
@@ -279,8 +224,8 @@ pub enum VariantId {
279 224
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 225#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
281pub struct StructFieldId { 226pub struct StructFieldId {
282 parent: VariantId, 227 pub parent: VariantId,
283 local_id: LocalStructFieldId, 228 pub local_id: LocalStructFieldId,
284} 229}
285 230
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -298,14 +243,14 @@ pub struct ConstLoc {
298 243
299impl Intern for ConstLoc { 244impl Intern for ConstLoc {
300 type ID = ConstId; 245 type ID = ConstId;
301 fn intern(self, db: &impl db::DefDatabase2) -> ConstId { 246 fn intern(self, db: &impl db::DefDatabase) -> ConstId {
302 db.intern_const(self) 247 db.intern_const(self)
303 } 248 }
304} 249}
305 250
306impl Lookup for ConstId { 251impl Lookup for ConstId {
307 type Data = ConstLoc; 252 type Data = ConstLoc;
308 fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc { 253 fn lookup(&self, db: &impl db::DefDatabase) -> ConstLoc {
309 db.lookup_intern_const(*self) 254 db.lookup_intern_const(*self)
310 } 255 }
311} 256}
@@ -346,14 +291,14 @@ pub struct TypeAliasLoc {
346 291
347impl Intern for TypeAliasLoc { 292impl Intern for TypeAliasLoc {
348 type ID = TypeAliasId; 293 type ID = TypeAliasId;
349 fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId { 294 fn intern(self, db: &impl db::DefDatabase) -> TypeAliasId {
350 db.intern_type_alias(self) 295 db.intern_type_alias(self)
351 } 296 }
352} 297}
353 298
354impl Lookup for TypeAliasId { 299impl Lookup for TypeAliasId {
355 type Data = TypeAliasLoc; 300 type Data = TypeAliasLoc;
356 fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc { 301 fn lookup(&self, db: &impl db::DefDatabase) -> TypeAliasLoc {
357 db.lookup_intern_type_alias(*self) 302 db.lookup_intern_type_alias(*self)
358 } 303 }
359} 304}
@@ -476,22 +421,51 @@ impl_froms!(
476 ConstId 421 ConstId
477); 422);
478 423
424#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
425pub enum AttrDefId {
426 ModuleId(ModuleId),
427 StructFieldId(StructFieldId),
428 AdtId(AdtId),
429 FunctionId(FunctionId),
430 EnumVariantId(EnumVariantId),
431 StaticId(StaticId),
432 ConstId(ConstId),
433 TraitId(TraitId),
434 TypeAliasId(TypeAliasId),
435 MacroDefId(MacroDefId),
436 ImplId(ImplId),
437}
438
439impl_froms!(
440 AttrDefId: ModuleId,
441 StructFieldId,
442 AdtId(StructId, EnumId, UnionId),
443 EnumVariantId,
444 StaticId,
445 ConstId,
446 FunctionId,
447 TraitId,
448 TypeAliasId,
449 MacroDefId,
450 ImplId
451);
452
479trait Intern { 453trait Intern {
480 type ID; 454 type ID;
481 fn intern(self, db: &impl db::DefDatabase2) -> Self::ID; 455 fn intern(self, db: &impl db::DefDatabase) -> Self::ID;
482} 456}
483 457
484pub trait Lookup { 458pub trait Lookup {
485 type Data; 459 type Data;
486 fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data; 460 fn lookup(&self, db: &impl db::DefDatabase) -> Self::Data;
487} 461}
488 462
489pub trait HasModule { 463pub trait HasModule {
490 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId; 464 fn module(&self, db: &impl db::DefDatabase) -> ModuleId;
491} 465}
492 466
493impl HasModule for FunctionLoc { 467impl HasModule for FunctionLoc {
494 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 468 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
495 match self.container { 469 match self.container {
496 ContainerId::ModuleId(it) => it, 470 ContainerId::ModuleId(it) => it,
497 ContainerId::ImplId(it) => it.module(db), 471 ContainerId::ImplId(it) => it.module(db),
@@ -501,7 +475,7 @@ impl HasModule for FunctionLoc {
501} 475}
502 476
503impl HasModule for TypeAliasLoc { 477impl HasModule for TypeAliasLoc {
504 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 478 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
505 match self.container { 479 match self.container {
506 ContainerId::ModuleId(it) => it, 480 ContainerId::ModuleId(it) => it,
507 ContainerId::ImplId(it) => it.module(db), 481 ContainerId::ImplId(it) => it.module(db),
@@ -511,7 +485,7 @@ impl HasModule for TypeAliasLoc {
511} 485}
512 486
513impl HasModule for ConstLoc { 487impl HasModule for ConstLoc {
514 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 488 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
515 match self.container { 489 match self.container {
516 ContainerId::ModuleId(it) => it, 490 ContainerId::ModuleId(it) => it,
517 ContainerId::ImplId(it) => it.module(db), 491 ContainerId::ImplId(it) => it.module(db),
@@ -522,13 +496,13 @@ impl HasModule for ConstLoc {
522 496
523pub trait HasSource { 497pub trait HasSource {
524 type Value; 498 type Value;
525 fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>; 499 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>;
526} 500}
527 501
528impl HasSource for FunctionLoc { 502impl HasSource for FunctionLoc {
529 type Value = ast::FnDef; 503 type Value = ast::FnDef;
530 504
531 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::FnDef> { 505 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::FnDef> {
532 let node = self.ast_id.to_node(db); 506 let node = self.ast_id.to_node(db);
533 Source::new(self.ast_id.file_id(), node) 507 Source::new(self.ast_id.file_id(), node)
534 } 508 }
@@ -537,7 +511,7 @@ impl HasSource for FunctionLoc {
537impl HasSource for TypeAliasLoc { 511impl HasSource for TypeAliasLoc {
538 type Value = ast::TypeAliasDef; 512 type Value = ast::TypeAliasDef;
539 513
540 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> { 514 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::TypeAliasDef> {
541 let node = self.ast_id.to_node(db); 515 let node = self.ast_id.to_node(db);
542 Source::new(self.ast_id.file_id(), node) 516 Source::new(self.ast_id.file_id(), node)
543 } 517 }
@@ -546,8 +520,17 @@ impl HasSource for TypeAliasLoc {
546impl HasSource for ConstLoc { 520impl HasSource for ConstLoc {
547 type Value = ast::ConstDef; 521 type Value = ast::ConstDef;
548 522
549 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::ConstDef> { 523 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::ConstDef> {
550 let node = self.ast_id.to_node(db); 524 let node = self.ast_id.to_node(db);
551 Source::new(self.ast_id.file_id(), node) 525 Source::new(self.ast_id.file_id(), node)
552 } 526 }
553} 527}
528
529pub trait HasChildSource {
530 type ChildId;
531 type Value;
532 fn child_source(
533 &self,
534 db: &impl db::DefDatabase,
535 ) -> Source<ArenaMap<Self::ChildId, Self::Value>>;
536}
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index c01e020ef..3b2e99647 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -47,8 +47,7 @@
47//! path and, upon success, we run macro expansion and "collect module" phase on 47//! path and, upon success, we run macro expansion and "collect module" phase on
48//! the result 48//! the result
49 49
50pub mod raw; 50pub(crate) mod raw;
51pub mod per_ns;
52mod collector; 51mod collector;
53mod mod_resolution; 52mod mod_resolution;
54mod path_resolution; 53mod path_resolution;
@@ -58,7 +57,10 @@ mod tests;
58 57
59use std::sync::Arc; 58use std::sync::Arc;
60 59
61use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; 60use hir_expand::{
61 ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId,
62 Source,
63};
62use once_cell::sync::Lazy; 64use once_cell::sync::Lazy;
63use ra_arena::Arena; 65use ra_arena::Arena;
64use ra_db::{CrateId, Edition, FileId}; 66use ra_db::{CrateId, Edition, FileId};
@@ -68,12 +70,11 @@ use rustc_hash::{FxHashMap, FxHashSet};
68 70
69use crate::{ 71use crate::{
70 builtin_type::BuiltinType, 72 builtin_type::BuiltinType,
71 db::DefDatabase2, 73 db::DefDatabase,
72 nameres::{ 74 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
73 diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId,
74 },
75 path::Path, 75 path::Path,
76 AstId, CrateModuleId, FunctionId, ImplId, ModuleDefId, ModuleId, TraitId, 76 per_ns::PerNs,
77 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
77}; 78};
78 79
79/// Contains all top-level defs from a macro-expanded crate 80/// Contains all top-level defs from a macro-expanded crate
@@ -86,8 +87,8 @@ pub struct CrateDefMap {
86 /// a dependency (`std` or `core`). 87 /// a dependency (`std` or `core`).
87 prelude: Option<ModuleId>, 88 prelude: Option<ModuleId>,
88 extern_prelude: FxHashMap<Name, ModuleDefId>, 89 extern_prelude: FxHashMap<Name, ModuleDefId>,
89 root: CrateModuleId, 90 root: LocalModuleId,
90 modules: Arena<CrateModuleId, ModuleData>, 91 modules: Arena<LocalModuleId, ModuleData>,
91 92
92 /// Some macros are not well-behavior, which leads to infinite loop 93 /// Some macros are not well-behavior, which leads to infinite loop
93 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } 94 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
@@ -104,24 +105,27 @@ pub struct CrateDefMap {
104 diagnostics: Vec<DefDiagnostic>, 105 diagnostics: Vec<DefDiagnostic>,
105} 106}
106 107
107impl std::ops::Index<CrateModuleId> for CrateDefMap { 108impl std::ops::Index<LocalModuleId> for CrateDefMap {
108 type Output = ModuleData; 109 type Output = ModuleData;
109 fn index(&self, id: CrateModuleId) -> &ModuleData { 110 fn index(&self, id: LocalModuleId) -> &ModuleData {
110 &self.modules[id] 111 &self.modules[id]
111 } 112 }
112} 113}
113 114
114#[derive(Default, Debug, PartialEq, Eq)] 115#[derive(Default, Debug, PartialEq, Eq)]
115pub struct ModuleData { 116pub struct ModuleData {
116 pub parent: Option<CrateModuleId>, 117 pub parent: Option<LocalModuleId>,
117 pub children: FxHashMap<Name, CrateModuleId>, 118 pub children: FxHashMap<Name, LocalModuleId>,
118 pub scope: ModuleScope, 119 pub scope: ModuleScope,
120
121 // FIXME: these can't be both null, we need a three-state enum here.
119 /// None for root 122 /// None for root
120 pub declaration: Option<AstId<ast::Module>>, 123 pub declaration: Option<AstId<ast::Module>>,
121 /// None for inline modules. 124 /// None for inline modules.
122 /// 125 ///
123 /// Note that non-inline modules, by definition, live inside non-macro file. 126 /// Note that non-inline modules, by definition, live inside non-macro file.
124 pub definition: Option<FileId>, 127 pub definition: Option<FileId>,
128
125 pub impls: Vec<ImplId>, 129 pub impls: Vec<ImplId>,
126} 130}
127 131
@@ -207,21 +211,21 @@ pub struct Resolution {
207 /// None for unresolved 211 /// None for unresolved
208 pub def: PerNs, 212 pub def: PerNs,
209 /// ident by which this is imported into local scope. 213 /// ident by which this is imported into local scope.
210 pub import: Option<ImportId>, 214 pub import: Option<LocalImportId>,
211} 215}
212 216
213impl CrateDefMap { 217impl CrateDefMap {
214 pub(crate) fn crate_def_map_query( 218 pub(crate) fn crate_def_map_query(
215 // Note that this doesn't have `+ AstDatabase`! 219 // Note that this doesn't have `+ AstDatabase`!
216 // This gurantess that `CrateDefMap` is stable across reparses. 220 // This gurantess that `CrateDefMap` is stable across reparses.
217 db: &impl DefDatabase2, 221 db: &impl DefDatabase,
218 krate: CrateId, 222 krate: CrateId,
219 ) -> Arc<CrateDefMap> { 223 ) -> Arc<CrateDefMap> {
220 let _p = profile("crate_def_map_query"); 224 let _p = profile("crate_def_map_query");
221 let def_map = { 225 let def_map = {
222 let crate_graph = db.crate_graph(); 226 let crate_graph = db.crate_graph();
223 let edition = crate_graph.edition(krate); 227 let edition = crate_graph.edition(krate);
224 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 228 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
225 let root = modules.alloc(ModuleData::default()); 229 let root = modules.alloc(ModuleData::default());
226 CrateDefMap { 230 CrateDefMap {
227 krate, 231 krate,
@@ -242,7 +246,7 @@ impl CrateDefMap {
242 self.krate 246 self.krate
243 } 247 }
244 248
245 pub fn root(&self) -> CrateModuleId { 249 pub fn root(&self) -> LocalModuleId {
246 self.root 250 self.root
247 } 251 }
248 252
@@ -256,8 +260,8 @@ impl CrateDefMap {
256 260
257 pub fn add_diagnostics( 261 pub fn add_diagnostics(
258 &self, 262 &self,
259 db: &impl DefDatabase2, 263 db: &impl DefDatabase,
260 module: CrateModuleId, 264 module: LocalModuleId,
261 sink: &mut DiagnosticSink, 265 sink: &mut DiagnosticSink,
262 ) { 266 ) {
263 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 267 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
@@ -265,19 +269,19 @@ impl CrateDefMap {
265 269
266 pub fn resolve_path( 270 pub fn resolve_path(
267 &self, 271 &self,
268 db: &impl DefDatabase2, 272 db: &impl DefDatabase,
269 original_module: CrateModuleId, 273 original_module: LocalModuleId,
270 path: &Path, 274 path: &Path,
271 ) -> (PerNs, Option<usize>) { 275 ) -> (PerNs, Option<usize>) {
272 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 276 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
273 (res.resolved_def, res.segment_index) 277 (res.resolved_def, res.segment_index)
274 } 278 }
275 279
276 pub fn modules(&self) -> impl Iterator<Item = CrateModuleId> + '_ { 280 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ {
277 self.modules.iter().map(|(id, _data)| id) 281 self.modules.iter().map(|(id, _data)| id)
278 } 282 }
279 283
280 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = CrateModuleId> + '_ { 284 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
281 self.modules 285 self.modules
282 .iter() 286 .iter()
283 .filter(move |(_id, data)| data.definition == Some(file_id)) 287 .filter(move |(_id, data)| data.definition == Some(file_id))
@@ -285,17 +289,40 @@ impl CrateDefMap {
285 } 289 }
286} 290}
287 291
292impl ModuleData {
293 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
294 pub fn definition_source(
295 &self,
296 db: &impl DefDatabase,
297 ) -> Source<Either<ast::SourceFile, ast::Module>> {
298 if let Some(file_id) = self.definition {
299 let sf = db.parse(file_id).tree();
300 return Source::new(file_id.into(), Either::A(sf));
301 }
302 let decl = self.declaration.unwrap();
303 Source::new(decl.file_id(), Either::B(decl.to_node(db)))
304 }
305
306 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
307 /// `None` for the crate root.
308 pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
309 let decl = self.declaration?;
310 let value = decl.to_node(db);
311 Some(Source { file_id: decl.file_id(), value })
312 }
313}
314
288mod diagnostics { 315mod diagnostics {
289 use hir_expand::diagnostics::DiagnosticSink; 316 use hir_expand::diagnostics::DiagnosticSink;
290 use ra_db::RelativePathBuf; 317 use ra_db::RelativePathBuf;
291 use ra_syntax::{ast, AstPtr}; 318 use ra_syntax::{ast, AstPtr};
292 319
293 use crate::{db::DefDatabase2, diagnostics::UnresolvedModule, nameres::CrateModuleId, AstId}; 320 use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};
294 321
295 #[derive(Debug, PartialEq, Eq)] 322 #[derive(Debug, PartialEq, Eq)]
296 pub(super) enum DefDiagnostic { 323 pub(super) enum DefDiagnostic {
297 UnresolvedModule { 324 UnresolvedModule {
298 module: CrateModuleId, 325 module: LocalModuleId,
299 declaration: AstId<ast::Module>, 326 declaration: AstId<ast::Module>,
300 candidate: RelativePathBuf, 327 candidate: RelativePathBuf,
301 }, 328 },
@@ -304,8 +331,8 @@ mod diagnostics {
304 impl DefDiagnostic { 331 impl DefDiagnostic {
305 pub(super) fn add_to( 332 pub(super) fn add_to(
306 &self, 333 &self,
307 db: &impl DefDatabase2, 334 db: &impl DefDatabase,
308 target_module: CrateModuleId, 335 target_module: LocalModuleId,
309 sink: &mut DiagnosticSink, 336 sink: &mut DiagnosticSink,
310 ) { 337 ) {
311 match self { 338 match self {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index aae3dcadf..b02364e86 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -12,19 +12,20 @@ use rustc_hash::FxHashMap;
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{ 14use crate::{
15 attr::Attr, 15 attr::Attrs,
16 db::DefDatabase2, 16 db::DefDatabase,
17 nameres::{ 17 nameres::{
18 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 18 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 19 raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 20 },
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId, 22 per_ns::PerNs,
23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, 23 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
24 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
24 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 25 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
25}; 26};
26 27
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 28pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
28 let crate_graph = db.crate_graph(); 29 let crate_graph = db.crate_graph();
29 30
30 // populate external prelude 31 // populate external prelude
@@ -94,10 +95,10 @@ impl MacroStackMonitor {
94struct DefCollector<'a, DB> { 95struct DefCollector<'a, DB> {
95 db: &'a DB, 96 db: &'a DB,
96 def_map: CrateDefMap, 97 def_map: CrateDefMap,
97 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 98 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
98 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 99 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>,
99 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>, 100 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>,
100 mod_dirs: FxHashMap<CrateModuleId, ModDir>, 101 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
101 102
102 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 103 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
103 /// To prevent stack overflow, we add a deep counter here for prevent that. 104 /// To prevent stack overflow, we add a deep counter here for prevent that.
@@ -108,7 +109,7 @@ struct DefCollector<'a, DB> {
108 109
109impl<DB> DefCollector<'_, DB> 110impl<DB> DefCollector<'_, DB>
110where 111where
111 DB: DefDatabase2, 112 DB: DefDatabase,
112{ 113{
113 fn collect(&mut self) { 114 fn collect(&mut self) {
114 let crate_graph = self.db.crate_graph(); 115 let crate_graph = self.db.crate_graph();
@@ -173,7 +174,7 @@ where
173 /// ``` 174 /// ```
174 fn define_macro( 175 fn define_macro(
175 &mut self, 176 &mut self,
176 module_id: CrateModuleId, 177 module_id: LocalModuleId,
177 name: Name, 178 name: Name,
178 macro_: MacroDefId, 179 macro_: MacroDefId,
179 export: bool, 180 export: bool,
@@ -200,7 +201,7 @@ where
200 /// the definition of current module. 201 /// the definition of current module.
201 /// And also, `macro_use` on a module will import all legacy macros visable inside to 202 /// And also, `macro_use` on a module will import all legacy macros visable inside to
202 /// current legacy scope, with possible shadowing. 203 /// current legacy scope, with possible shadowing.
203 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDefId) { 204 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
204 // Always shadowing 205 // Always shadowing
205 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); 206 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
206 } 207 }
@@ -208,7 +209,7 @@ where
208 /// Import macros from `#[macro_use] extern crate`. 209 /// Import macros from `#[macro_use] extern crate`.
209 fn import_macros_from_extern_crate( 210 fn import_macros_from_extern_crate(
210 &mut self, 211 &mut self,
211 current_module_id: CrateModuleId, 212 current_module_id: LocalModuleId,
212 import: &raw::ImportData, 213 import: &raw::ImportData,
213 ) { 214 ) {
214 log::debug!( 215 log::debug!(
@@ -235,7 +236,7 @@ where
235 /// Exported macros are just all macros in the root module scope. 236 /// Exported macros are just all macros in the root module scope.
236 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases 237 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
237 /// created by `use` in the root module, ignoring the visibility of `use`. 238 /// created by `use` in the root module, ignoring the visibility of `use`.
238 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: CrateId) { 239 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
239 let def_map = self.db.crate_def_map(krate); 240 let def_map = self.db.crate_def_map(krate);
240 for (name, def) in def_map[def_map.root].scope.macros() { 241 for (name, def) in def_map[def_map.root].scope.macros() {
241 // `macro_use` only bring things into legacy scope. 242 // `macro_use` only bring things into legacy scope.
@@ -265,7 +266,7 @@ where
265 266
266 fn resolve_import( 267 fn resolve_import(
267 &self, 268 &self,
268 module_id: CrateModuleId, 269 module_id: LocalModuleId,
269 import: &raw::ImportData, 270 import: &raw::ImportData,
270 ) -> (PerNs, ReachedFixedPoint) { 271 ) -> (PerNs, ReachedFixedPoint) {
271 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 272 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
@@ -291,9 +292,9 @@ where
291 292
292 fn record_resolved_import( 293 fn record_resolved_import(
293 &mut self, 294 &mut self,
294 module_id: CrateModuleId, 295 module_id: LocalModuleId,
295 def: PerNs, 296 def: PerNs,
296 import_id: raw::ImportId, 297 import_id: LocalImportId,
297 import: &raw::ImportData, 298 import: &raw::ImportData,
298 ) { 299 ) {
299 if import.is_glob { 300 if import.is_glob {
@@ -387,8 +388,8 @@ where
387 388
388 fn update( 389 fn update(
389 &mut self, 390 &mut self,
390 module_id: CrateModuleId, 391 module_id: LocalModuleId,
391 import: Option<raw::ImportId>, 392 import: Option<LocalImportId>,
392 resolutions: &[(Name, Resolution)], 393 resolutions: &[(Name, Resolution)],
393 ) { 394 ) {
394 self.update_recursive(module_id, import, resolutions, 0) 395 self.update_recursive(module_id, import, resolutions, 0)
@@ -396,8 +397,8 @@ where
396 397
397 fn update_recursive( 398 fn update_recursive(
398 &mut self, 399 &mut self,
399 module_id: CrateModuleId, 400 module_id: LocalModuleId,
400 import: Option<raw::ImportId>, 401 import: Option<LocalImportId>,
401 resolutions: &[(Name, Resolution)], 402 resolutions: &[(Name, Resolution)],
402 depth: usize, 403 depth: usize,
403 ) { 404 ) {
@@ -484,7 +485,7 @@ where
484 485
485 fn collect_macro_expansion( 486 fn collect_macro_expansion(
486 &mut self, 487 &mut self,
487 module_id: CrateModuleId, 488 module_id: LocalModuleId,
488 macro_call_id: MacroCallId, 489 macro_call_id: MacroCallId,
489 macro_def_id: MacroDefId, 490 macro_def_id: MacroDefId,
490 ) { 491 ) {
@@ -522,7 +523,7 @@ where
522/// Walks a single module, populating defs, imports and macros 523/// Walks a single module, populating defs, imports and macros
523struct ModCollector<'a, D> { 524struct ModCollector<'a, D> {
524 def_collector: D, 525 def_collector: D,
525 module_id: CrateModuleId, 526 module_id: LocalModuleId,
526 file_id: HirFileId, 527 file_id: HirFileId,
527 raw_items: &'a raw::RawItems, 528 raw_items: &'a raw::RawItems,
528 mod_dir: ModDir, 529 mod_dir: ModDir,
@@ -530,7 +531,7 @@ struct ModCollector<'a, D> {
530 531
531impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> 532impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
532where 533where
533 DB: DefDatabase2, 534 DB: DefDatabase,
534{ 535{
535 fn collect(&mut self, items: &[raw::RawItem]) { 536 fn collect(&mut self, items: &[raw::RawItem]) {
536 // Note: don't assert that inserted value is fresh: it's simply not true 537 // Note: don't assert that inserted value is fresh: it's simply not true
@@ -549,7 +550,7 @@ where
549 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 550 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
550 // any other items. 551 // any other items.
551 for item in items { 552 for item in items {
552 if self.is_cfg_enabled(item.attrs()) { 553 if self.is_cfg_enabled(&item.attrs) {
553 if let raw::RawItemKind::Import(import_id) = item.kind { 554 if let raw::RawItemKind::Import(import_id) = item.kind {
554 let import = self.raw_items[import_id].clone(); 555 let import = self.raw_items[import_id].clone();
555 if import.is_extern_crate && import.is_macro_use { 556 if import.is_extern_crate && import.is_macro_use {
@@ -560,10 +561,10 @@ where
560 } 561 }
561 562
562 for item in items { 563 for item in items {
563 if self.is_cfg_enabled(item.attrs()) { 564 if self.is_cfg_enabled(&item.attrs) {
564 match item.kind { 565 match item.kind {
565 raw::RawItemKind::Module(m) => { 566 raw::RawItemKind::Module(m) => {
566 self.collect_module(&self.raw_items[m], item.attrs()) 567 self.collect_module(&self.raw_items[m], &item.attrs)
567 } 568 }
568 raw::RawItemKind::Import(import_id) => self 569 raw::RawItemKind::Import(import_id) => self
569 .def_collector 570 .def_collector
@@ -585,9 +586,9 @@ where
585 } 586 }
586 } 587 }
587 588
588 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) { 589 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
589 let path_attr = self.path_attr(attrs); 590 let path_attr = self.path_attr(attrs);
590 let is_macro_use = self.is_macro_use(attrs); 591 let is_macro_use = attrs.has_atom("macro_use");
591 match module { 592 match module {
592 // inline module, just recurse 593 // inline module, just recurse
593 raw::ModuleData::Definition { name, items, ast_id } => { 594 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -647,7 +648,7 @@ where
647 name: Name, 648 name: Name,
648 declaration: AstId<ast::Module>, 649 declaration: AstId<ast::Module>,
649 definition: Option<FileId>, 650 definition: Option<FileId>,
650 ) -> CrateModuleId { 651 ) -> LocalModuleId {
651 let modules = &mut self.def_collector.def_map.modules; 652 let modules = &mut self.def_collector.def_map.modules;
652 let res = modules.alloc(ModuleData::default()); 653 let res = modules.alloc(ModuleData::default());
653 modules[res].parent = Some(self.module_id); 654 modules[res].parent = Some(self.module_id);
@@ -772,24 +773,20 @@ where
772 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); 773 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
773 } 774 }
774 775
775 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { 776 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
776 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); 777 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
777 for (name, macro_) in macros { 778 for (name, macro_) in macros {
778 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); 779 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
779 } 780 }
780 } 781 }
781 782
782 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { 783 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
783 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 784 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
784 } 785 }
785 786
786 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> { 787 fn path_attr<'a>(&self, attrs: &'a Attrs) -> Option<&'a SmolStr> {
787 attrs.iter().find_map(|attr| attr.as_path()) 788 attrs.iter().find_map(|attr| attr.as_path())
788 } 789 }
789
790 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
791 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
792 }
793} 790}
794 791
795fn is_macro_rules(path: &Path) -> bool { 792fn is_macro_rules(path: &Path) -> bool {
@@ -802,12 +799,12 @@ mod tests {
802 use ra_db::{fixture::WithFixture, SourceDatabase}; 799 use ra_db::{fixture::WithFixture, SourceDatabase};
803 use rustc_hash::FxHashSet; 800 use rustc_hash::FxHashSet;
804 801
805 use crate::{db::DefDatabase2, test_db::TestDB}; 802 use crate::{db::DefDatabase, test_db::TestDB};
806 803
807 use super::*; 804 use super::*;
808 805
809 fn do_collect_defs( 806 fn do_collect_defs(
810 db: &impl DefDatabase2, 807 db: &impl DefDatabase,
811 def_map: CrateDefMap, 808 def_map: CrateDefMap,
812 monitor: MacroStackMonitor, 809 monitor: MacroStackMonitor,
813 ) -> CrateDefMap { 810 ) -> CrateDefMap {
@@ -831,7 +828,7 @@ mod tests {
831 828
832 let def_map = { 829 let def_map = {
833 let edition = db.crate_graph().edition(krate); 830 let edition = db.crate_graph().edition(krate);
834 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 831 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
835 let root = modules.alloc(ModuleData::default()); 832 let root = modules.alloc(ModuleData::default());
836 CrateDefMap { 833 CrateDefMap {
837 krate, 834 krate,
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index b3b1379d0..14fb8ba3a 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -3,7 +3,7 @@ use hir_expand::name::Name;
3use ra_db::{FileId, RelativePathBuf}; 3use ra_db::{FileId, RelativePathBuf};
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
5 5
6use crate::{db::DefDatabase2, HirFileId}; 6use crate::{db::DefDatabase, HirFileId};
7 7
8#[derive(Clone, Debug)] 8#[derive(Clone, Debug)]
9pub(super) struct ModDir { 9pub(super) struct ModDir {
@@ -40,7 +40,7 @@ impl ModDir {
40 40
41 pub(super) fn resolve_declaration( 41 pub(super) fn resolve_declaration(
42 &self, 42 &self,
43 db: &impl DefDatabase2, 43 db: &impl DefDatabase,
44 file_id: HirFileId, 44 file_id: HirFileId,
45 name: &Name, 45 name: &Name,
46 attr_path: Option<&SmolStr>, 46 attr_path: Option<&SmolStr>,
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 95692f826..9455f22bb 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -15,10 +15,11 @@ use ra_db::Edition;
15use test_utils::tested_by; 15use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 db::DefDatabase2, 18 db::DefDatabase,
19 nameres::{per_ns::PerNs, CrateDefMap}, 19 nameres::CrateDefMap,
20 path::{Path, PathKind}, 20 path::{Path, PathKind},
21 AdtId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId, 21 per_ns::PerNs,
22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
22}; 23};
23 24
24#[derive(Debug, Clone, Copy, PartialEq, Eq)] 25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,9 +64,9 @@ impl CrateDefMap {
63 // the result. 64 // the result.
64 pub(super) fn resolve_path_fp_with_macro( 65 pub(super) fn resolve_path_fp_with_macro(
65 &self, 66 &self,
66 db: &impl DefDatabase2, 67 db: &impl DefDatabase,
67 mode: ResolveMode, 68 mode: ResolveMode,
68 original_module: CrateModuleId, 69 original_module: LocalModuleId,
69 path: &Path, 70 path: &Path,
70 ) -> ResolvePathResult { 71 ) -> ResolvePathResult {
71 let mut segments = path.segments.iter().enumerate(); 72 let mut segments = path.segments.iter().enumerate();
@@ -216,8 +217,8 @@ impl CrateDefMap {
216 217
217 fn resolve_name_in_module( 218 fn resolve_name_in_module(
218 &self, 219 &self,
219 db: &impl DefDatabase2, 220 db: &impl DefDatabase,
220 module: CrateModuleId, 221 module: LocalModuleId,
221 name: &Name, 222 name: &Name,
222 ) -> PerNs { 223 ) -> PerNs {
223 // Resolve in: 224 // Resolve in:
@@ -243,7 +244,7 @@ impl CrateDefMap {
243 from_crate_root.or(from_extern_prelude) 244 from_crate_root.or(from_extern_prelude)
244 } 245 }
245 246
246 fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs { 247 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
247 if let Some(prelude) = self.prelude { 248 if let Some(prelude) = self.prelude {
248 let keep; 249 let keep;
249 let def_map = if prelude.krate == self.krate { 250 let def_map = if prelude.krate == self.krate {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 7c68fd638..552cbe544 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -12,11 +12,16 @@ use hir_expand::{
12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
13use ra_syntax::{ 13use ra_syntax::{
14 ast::{self, AttrsOwner, NameOwner}, 14 ast::{self, AttrsOwner, NameOwner},
15 AstNode, AstPtr, SourceFile, 15 AstNode, AstPtr,
16}; 16};
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source}; 19use crate::{
20 attr::{Attr, Attrs},
21 db::DefDatabase,
22 path::Path,
23 FileAstId, HirFileId, LocalImportId, Source,
24};
20 25
21/// `RawItems` is a set of top-level items in a file (except for impls). 26/// `RawItems` is a set of top-level items in a file (except for impls).
22/// 27///
@@ -25,7 +30,7 @@ use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, Modu
25#[derive(Debug, Default, PartialEq, Eq)] 30#[derive(Debug, Default, PartialEq, Eq)]
26pub struct RawItems { 31pub struct RawItems {
27 modules: Arena<Module, ModuleData>, 32 modules: Arena<Module, ModuleData>,
28 imports: Arena<ImportId, ImportData>, 33 imports: Arena<LocalImportId, ImportData>,
29 defs: Arena<Def, DefData>, 34 defs: Arena<Def, DefData>,
30 macros: Arena<Macro, MacroData>, 35 macros: Arena<Macro, MacroData>,
31 impls: Arena<Impl, ImplData>, 36 impls: Arena<Impl, ImplData>,
@@ -35,41 +40,31 @@ pub struct RawItems {
35 40
36#[derive(Debug, Default, PartialEq, Eq)] 41#[derive(Debug, Default, PartialEq, Eq)]
37pub struct ImportSourceMap { 42pub struct ImportSourceMap {
38 map: ArenaMap<ImportId, ImportSourcePtr>, 43 map: ArenaMap<LocalImportId, ImportSourcePtr>,
39} 44}
40 45
41type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; 46type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
42type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
43
44fn to_node(ptr: ImportSourcePtr, file: &SourceFile) -> ImportSource {
45 ptr.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
46}
47 47
48impl ImportSourceMap { 48impl ImportSourceMap {
49 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 49 fn insert(&mut self, import: LocalImportId, ptr: ImportSourcePtr) {
50 self.map.insert(import, ptr) 50 self.map.insert(import, ptr)
51 } 51 }
52 52
53 pub fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource { 53 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr {
54 let file = match source { 54 self.map[import].clone()
55 ModuleSource::SourceFile(file) => file.clone(),
56 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
57 };
58
59 to_node(self.map[import], &file)
60 } 55 }
61} 56}
62 57
63impl RawItems { 58impl RawItems {
64 pub(crate) fn raw_items_query( 59 pub(crate) fn raw_items_query(
65 db: &(impl DefDatabase2 + AstDatabase), 60 db: &(impl DefDatabase + AstDatabase),
66 file_id: HirFileId, 61 file_id: HirFileId,
67 ) -> Arc<RawItems> { 62 ) -> Arc<RawItems> {
68 db.raw_items_with_source_map(file_id).0 63 db.raw_items_with_source_map(file_id).0
69 } 64 }
70 65
71 pub(crate) fn raw_items_with_source_map_query( 66 pub(crate) fn raw_items_with_source_map_query(
72 db: &(impl DefDatabase2 + AstDatabase), 67 db: &(impl DefDatabase + AstDatabase),
73 file_id: HirFileId, 68 file_id: HirFileId,
74 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 69 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
75 let mut collector = RawItemsCollector { 70 let mut collector = RawItemsCollector {
@@ -101,9 +96,9 @@ impl Index<Module> for RawItems {
101 } 96 }
102} 97}
103 98
104impl Index<ImportId> for RawItems { 99impl Index<LocalImportId> for RawItems {
105 type Output = ImportData; 100 type Output = ImportData;
106 fn index(&self, idx: ImportId) -> &ImportData { 101 fn index(&self, idx: LocalImportId) -> &ImportData {
107 &self.imports[idx] 102 &self.imports[idx]
108 } 103 }
109} 104}
@@ -129,25 +124,16 @@ impl Index<Impl> for RawItems {
129 } 124 }
130} 125}
131 126
132// Avoid heap allocation on items without attributes.
133type Attrs = Option<Arc<[Attr]>>;
134
135#[derive(Debug, PartialEq, Eq, Clone)] 127#[derive(Debug, PartialEq, Eq, Clone)]
136pub(super) struct RawItem { 128pub(super) struct RawItem {
137 attrs: Attrs, 129 pub(super) attrs: Attrs,
138 pub(super) kind: RawItemKind, 130 pub(super) kind: RawItemKind,
139} 131}
140 132
141impl RawItem {
142 pub(super) fn attrs(&self) -> &[Attr] {
143 self.attrs.as_ref().map_or(&[], |it| &*it)
144 }
145}
146
147#[derive(Debug, PartialEq, Eq, Clone, Copy)] 133#[derive(Debug, PartialEq, Eq, Clone, Copy)]
148pub(super) enum RawItemKind { 134pub(super) enum RawItemKind {
149 Module(Module), 135 Module(Module),
150 Import(ImportId), 136 Import(LocalImportId),
151 Def(Def), 137 Def(Def),
152 Macro(Macro), 138 Macro(Macro),
153 Impl(Impl), 139 Impl(Impl),
@@ -163,10 +149,6 @@ pub(super) enum ModuleData {
163 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 149 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
164} 150}
165 151
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub struct ImportId(RawId);
168impl_arena_id!(ImportId);
169
170#[derive(Debug, Clone, PartialEq, Eq)] 152#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct ImportData { 153pub struct ImportData {
172 pub(super) path: Path, 154 pub(super) path: Path,
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 256f7d4be..f0b86af7c 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -10,7 +10,7 @@ use insta::assert_snapshot;
10use ra_db::{fixture::WithFixture, SourceDatabase}; 10use ra_db::{fixture::WithFixture, SourceDatabase};
11use test_utils::covers; 11use test_utils::covers;
12 12
13use crate::{db::DefDatabase2, nameres::*, test_db::TestDB, CrateModuleId}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId};
14 14
15fn def_map(fixtute: &str) -> String { 15fn def_map(fixtute: &str) -> String {
16 let dm = compute_crate_def_map(fixtute); 16 let dm = compute_crate_def_map(fixtute);
@@ -28,7 +28,7 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
28 go(&mut buf, map, "\ncrate", map.root()); 28 go(&mut buf, map, "\ncrate", map.root());
29 return buf.trim().to_string(); 29 return buf.trim().to_string();
30 30
31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) { 31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
32 *buf += path; 32 *buf += path;
33 *buf += "\n"; 33 *buf += "\n";
34 34
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index eb7b85c07..e11530062 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -665,7 +665,7 @@ fn unresolved_module_diagnostics() {
665 @r###" 665 @r###"
666 [ 666 [
667 UnresolvedModule { 667 UnresolvedModule {
668 module: CrateModuleId( 668 module: LocalModuleId(
669 0, 669 0,
670 ), 670 ),
671 declaration: AstId { 671 declaration: AstId {
diff --git a/crates/ra_hir_def/src/nameres/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 717ed1ef9..717ed1ef9 100644
--- a/crates/ra_hir_def/src/nameres/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 7b5c3ec06..b56de44dd 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -11,14 +11,15 @@ use rustc_hash::FxHashSet;
11use crate::{ 11use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 builtin_type::BuiltinType, 13 builtin_type::BuiltinType,
14 db::DefDatabase2, 14 db::DefDatabase,
15 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
16 generics::GenericParams, 16 generics::GenericParams,
17 nameres::{per_ns::PerNs, CrateDefMap}, 17 nameres::CrateDefMap,
18 path::{Path, PathKind}, 18 path::{Path, PathKind},
19 AdtId, AstItemDef, ConstId, ContainerId, CrateModuleId, DefWithBodyId, EnumId, EnumVariantId, 19 per_ns::PerNs,
20 FunctionId, GenericDefId, ImplId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, 20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
21 TypeAliasId, 21 GenericDefId, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId,
22 TraitId, TypeAliasId,
22}; 23};
23 24
24#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
@@ -30,7 +31,7 @@ pub struct Resolver {
30#[derive(Debug, Clone)] 31#[derive(Debug, Clone)]
31pub(crate) struct ModuleItemMap { 32pub(crate) struct ModuleItemMap {
32 crate_def_map: Arc<CrateDefMap>, 33 crate_def_map: Arc<CrateDefMap>,
33 module_id: CrateModuleId, 34 module_id: LocalModuleId,
34} 35}
35 36
36#[derive(Debug, Clone)] 37#[derive(Debug, Clone)]
@@ -87,7 +88,7 @@ pub enum ValueNs {
87 88
88impl Resolver { 89impl Resolver {
89 /// Resolve known trait from std, like `std::futures::Future` 90 /// Resolve known trait from std, like `std::futures::Future`
90 pub fn resolve_known_trait(&self, db: &impl DefDatabase2, path: &Path) -> Option<TraitId> { 91 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> {
91 let res = self.resolve_module_path(db, path).take_types()?; 92 let res = self.resolve_module_path(db, path).take_types()?;
92 match res { 93 match res {
93 ModuleDefId::TraitId(it) => Some(it), 94 ModuleDefId::TraitId(it) => Some(it),
@@ -96,7 +97,7 @@ impl Resolver {
96 } 97 }
97 98
98 /// Resolve known struct from std, like `std::boxed::Box` 99 /// Resolve known struct from std, like `std::boxed::Box`
99 pub fn resolve_known_struct(&self, db: &impl DefDatabase2, path: &Path) -> Option<StructId> { 100 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> {
100 let res = self.resolve_module_path(db, path).take_types()?; 101 let res = self.resolve_module_path(db, path).take_types()?;
101 match res { 102 match res {
102 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), 103 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
@@ -105,7 +106,7 @@ impl Resolver {
105 } 106 }
106 107
107 /// Resolve known enum from std, like `std::result::Result` 108 /// Resolve known enum from std, like `std::result::Result`
108 pub fn resolve_known_enum(&self, db: &impl DefDatabase2, path: &Path) -> Option<EnumId> { 109 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> {
109 let res = self.resolve_module_path(db, path).take_types()?; 110 let res = self.resolve_module_path(db, path).take_types()?;
110 match res { 111 match res {
111 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), 112 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
@@ -114,7 +115,7 @@ impl Resolver {
114 } 115 }
115 116
116 /// pub only for source-binder 117 /// pub only for source-binder
117 pub fn resolve_module_path(&self, db: &impl DefDatabase2, path: &Path) -> PerNs { 118 pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
118 let (item_map, module) = match self.module() { 119 let (item_map, module) = match self.module() {
119 Some(it) => it, 120 Some(it) => it,
120 None => return PerNs::none(), 121 None => return PerNs::none(),
@@ -128,7 +129,7 @@ impl Resolver {
128 129
129 pub fn resolve_path_in_type_ns( 130 pub fn resolve_path_in_type_ns(
130 &self, 131 &self,
131 db: &impl DefDatabase2, 132 db: &impl DefDatabase,
132 path: &Path, 133 path: &Path,
133 ) -> Option<(TypeNs, Option<usize>)> { 134 ) -> Option<(TypeNs, Option<usize>)> {
134 if path.is_type_relative() { 135 if path.is_type_relative() {
@@ -184,7 +185,7 @@ impl Resolver {
184 185
185 pub fn resolve_path_in_type_ns_fully( 186 pub fn resolve_path_in_type_ns_fully(
186 &self, 187 &self,
187 db: &impl DefDatabase2, 188 db: &impl DefDatabase,
188 path: &Path, 189 path: &Path,
189 ) -> Option<TypeNs> { 190 ) -> Option<TypeNs> {
190 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; 191 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
@@ -196,7 +197,7 @@ impl Resolver {
196 197
197 pub fn resolve_path_in_value_ns<'p>( 198 pub fn resolve_path_in_value_ns<'p>(
198 &self, 199 &self,
199 db: &impl DefDatabase2, 200 db: &impl DefDatabase,
200 path: &'p Path, 201 path: &'p Path,
201 ) -> Option<ResolveValueResult> { 202 ) -> Option<ResolveValueResult> {
202 if path.is_type_relative() { 203 if path.is_type_relative() {
@@ -296,7 +297,7 @@ impl Resolver {
296 297
297 pub fn resolve_path_in_value_ns_fully( 298 pub fn resolve_path_in_value_ns_fully(
298 &self, 299 &self,
299 db: &impl DefDatabase2, 300 db: &impl DefDatabase,
300 path: &Path, 301 path: &Path,
301 ) -> Option<ValueNs> { 302 ) -> Option<ValueNs> {
302 match self.resolve_path_in_value_ns(db, path)? { 303 match self.resolve_path_in_value_ns(db, path)? {
@@ -305,18 +306,18 @@ impl Resolver {
305 } 306 }
306 } 307 }
307 308
308 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> { 309 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
309 let (item_map, module) = self.module()?; 310 let (item_map, module) = self.module()?;
310 item_map.resolve_path(db, module, path).0.get_macros() 311 item_map.resolve_path(db, module, path).0.get_macros()
311 } 312 }
312 313
313 pub fn process_all_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { 314 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
314 for scope in self.scopes.iter().rev() { 315 for scope in self.scopes.iter().rev() {
315 scope.process_names(db, f); 316 scope.process_names(db, f);
316 } 317 }
317 } 318 }
318 319
319 pub fn traits_in_scope(&self, db: &impl DefDatabase2) -> FxHashSet<TraitId> { 320 pub fn traits_in_scope(&self, db: &impl DefDatabase) -> FxHashSet<TraitId> {
320 let mut traits = FxHashSet::default(); 321 let mut traits = FxHashSet::default();
321 for scope in &self.scopes { 322 for scope in &self.scopes {
322 if let Scope::ModuleScope(m) = scope { 323 if let Scope::ModuleScope(m) = scope {
@@ -330,7 +331,7 @@ impl Resolver {
330 traits 331 traits
331 } 332 }
332 333
333 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { 334 fn module(&self) -> Option<(&CrateDefMap, LocalModuleId)> {
334 self.scopes.iter().rev().find_map(|scope| match scope { 335 self.scopes.iter().rev().find_map(|scope| match scope {
335 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 336 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
336 337
@@ -378,7 +379,7 @@ pub enum ScopeDef {
378} 379}
379 380
380impl Scope { 381impl Scope {
381 fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { 382 fn process_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
382 match self { 383 match self {
383 Scope::ModuleScope(m) => { 384 Scope::ModuleScope(m) => {
384 // FIXME: should we provide `self` here? 385 // FIXME: should we provide `self` here?
@@ -425,17 +426,13 @@ impl Scope {
425} 426}
426 427
427// needs arbitrary_self_types to be a method... or maybe move to the def? 428// needs arbitrary_self_types to be a method... or maybe move to the def?
428pub fn resolver_for_expr( 429pub fn resolver_for_expr(db: &impl DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver {
429 db: &impl DefDatabase2,
430 owner: DefWithBodyId,
431 expr_id: ExprId,
432) -> Resolver {
433 let scopes = db.expr_scopes(owner); 430 let scopes = db.expr_scopes(owner);
434 resolver_for_scope(db, owner, scopes.scope_for(expr_id)) 431 resolver_for_scope(db, owner, scopes.scope_for(expr_id))
435} 432}
436 433
437pub fn resolver_for_scope( 434pub fn resolver_for_scope(
438 db: &impl DefDatabase2, 435 db: &impl DefDatabase,
439 owner: DefWithBodyId, 436 owner: DefWithBodyId,
440 scope_id: Option<ScopeId>, 437 scope_id: Option<ScopeId>,
441) -> Resolver { 438) -> Resolver {
@@ -454,7 +451,7 @@ impl Resolver {
454 self 451 self
455 } 452 }
456 453
457 fn push_generic_params_scope(self, db: &impl DefDatabase2, def: GenericDefId) -> Resolver { 454 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
458 let params = db.generic_params(def); 455 let params = db.generic_params(def);
459 if params.params.is_empty() { 456 if params.params.is_empty() {
460 self 457 self
@@ -470,7 +467,7 @@ impl Resolver {
470 fn push_module_scope( 467 fn push_module_scope(
471 self, 468 self,
472 crate_def_map: Arc<CrateDefMap>, 469 crate_def_map: Arc<CrateDefMap>,
473 module_id: CrateModuleId, 470 module_id: LocalModuleId,
474 ) -> Resolver { 471 ) -> Resolver {
475 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 472 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
476 } 473 }
@@ -487,24 +484,24 @@ impl Resolver {
487 484
488pub trait HasResolver { 485pub trait HasResolver {
489 /// Builds a resolver for type references inside this def. 486 /// Builds a resolver for type references inside this def.
490 fn resolver(self, db: &impl DefDatabase2) -> Resolver; 487 fn resolver(self, db: &impl DefDatabase) -> Resolver;
491} 488}
492 489
493impl HasResolver for ModuleId { 490impl HasResolver for ModuleId {
494 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 491 fn resolver(self, db: &impl DefDatabase) -> Resolver {
495 let def_map = db.crate_def_map(self.krate); 492 let def_map = db.crate_def_map(self.krate);
496 Resolver::default().push_module_scope(def_map, self.module_id) 493 Resolver::default().push_module_scope(def_map, self.module_id)
497 } 494 }
498} 495}
499 496
500impl HasResolver for TraitId { 497impl HasResolver for TraitId {
501 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 498 fn resolver(self, db: &impl DefDatabase) -> Resolver {
502 self.module(db).resolver(db).push_generic_params_scope(db, self.into()) 499 self.module(db).resolver(db).push_generic_params_scope(db, self.into())
503 } 500 }
504} 501}
505 502
506impl<T: Into<AdtId>> HasResolver for T { 503impl<T: Into<AdtId>> HasResolver for T {
507 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 504 fn resolver(self, db: &impl DefDatabase) -> Resolver {
508 let def = self.into(); 505 let def = self.into();
509 let module = match def { 506 let module = match def {
510 AdtId::StructId(it) => it.0.module(db), 507 AdtId::StructId(it) => it.0.module(db),
@@ -520,13 +517,13 @@ impl<T: Into<AdtId>> HasResolver for T {
520} 517}
521 518
522impl HasResolver for FunctionId { 519impl HasResolver for FunctionId {
523 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 520 fn resolver(self, db: &impl DefDatabase) -> Resolver {
524 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) 521 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
525 } 522 }
526} 523}
527 524
528impl HasResolver for DefWithBodyId { 525impl HasResolver for DefWithBodyId {
529 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 526 fn resolver(self, db: &impl DefDatabase) -> Resolver {
530 match self { 527 match self {
531 DefWithBodyId::ConstId(c) => c.resolver(db), 528 DefWithBodyId::ConstId(c) => c.resolver(db),
532 DefWithBodyId::FunctionId(f) => f.resolver(db), 529 DefWithBodyId::FunctionId(f) => f.resolver(db),
@@ -536,25 +533,25 @@ impl HasResolver for DefWithBodyId {
536} 533}
537 534
538impl HasResolver for ConstId { 535impl HasResolver for ConstId {
539 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 536 fn resolver(self, db: &impl DefDatabase) -> Resolver {
540 self.lookup(db).container.resolver(db) 537 self.lookup(db).container.resolver(db)
541 } 538 }
542} 539}
543 540
544impl HasResolver for StaticId { 541impl HasResolver for StaticId {
545 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 542 fn resolver(self, db: &impl DefDatabase) -> Resolver {
546 self.module(db).resolver(db) 543 self.module(db).resolver(db)
547 } 544 }
548} 545}
549 546
550impl HasResolver for TypeAliasId { 547impl HasResolver for TypeAliasId {
551 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 548 fn resolver(self, db: &impl DefDatabase) -> Resolver {
552 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) 549 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
553 } 550 }
554} 551}
555 552
556impl HasResolver for ContainerId { 553impl HasResolver for ContainerId {
557 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 554 fn resolver(self, db: &impl DefDatabase) -> Resolver {
558 match self { 555 match self {
559 ContainerId::TraitId(it) => it.resolver(db), 556 ContainerId::TraitId(it) => it.resolver(db),
560 ContainerId::ImplId(it) => it.resolver(db), 557 ContainerId::ImplId(it) => it.resolver(db),
@@ -564,7 +561,7 @@ impl HasResolver for ContainerId {
564} 561}
565 562
566impl HasResolver for GenericDefId { 563impl HasResolver for GenericDefId {
567 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 564 fn resolver(self, db: &impl DefDatabase) -> Resolver {
568 match self { 565 match self {
569 GenericDefId::FunctionId(inner) => inner.resolver(db), 566 GenericDefId::FunctionId(inner) => inner.resolver(db),
570 GenericDefId::AdtId(adt) => adt.resolver(db), 567 GenericDefId::AdtId(adt) => adt.resolver(db),
@@ -578,7 +575,7 @@ impl HasResolver for GenericDefId {
578} 575}
579 576
580impl HasResolver for ImplId { 577impl HasResolver for ImplId {
581 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 578 fn resolver(self, db: &impl DefDatabase) -> Resolver {
582 self.module(db) 579 self.module(db)
583 .resolver(db) 580 .resolver(db)
584 .push_generic_params_scope(db, self.into()) 581 .push_generic_params_scope(db, self.into())
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
index 8ee8e40d0..439e8a412 100644
--- a/crates/ra_hir_def/src/test_db.rs
+++ b/crates/ra_hir_def/src/test_db.rs
@@ -12,7 +12,7 @@ use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath
12 ra_db::SourceDatabaseStorage, 12 ra_db::SourceDatabaseStorage,
13 hir_expand::db::AstDatabaseStorage, 13 hir_expand::db::AstDatabaseStorage,
14 crate::db::InternDatabaseStorage, 14 crate::db::InternDatabaseStorage,
15 crate::db::DefDatabase2Storage 15 crate::db::DefDatabaseStorage
16)] 16)]
17#[derive(Debug, Default)] 17#[derive(Debug, Default)]
18pub struct TestDB { 18pub struct TestDB {
diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs
new file mode 100644
index 000000000..fc26f5a48
--- /dev/null
+++ b/crates/ra_hir_def/src/trace.rs
@@ -0,0 +1,49 @@
1//! Trace is a pretty niche data structure which is used when lowering a CST
2//! into HIR.
3//!
4//! Lowering process calculates two bits of information:
5//! * the lowered syntax itself
6//! * a mapping between lowered syntax and original syntax
7//!
8//! Due to the way salsa works, the mapping is usually hot lava, as it contains
9//! absolute offsets. The `Trace` structure (inspired, at least in name, by
10//! Kotlin's `BindingTrace`) allows use the same code to compute both
11//! projections.
12use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId};
13
14pub(crate) struct Trace<ID: ArenaId, T, V> {
15 for_arena: bool,
16 arena: Arena<ID, T>,
17 map: ArenaMap<ID, V>,
18 len: u32,
19}
20
21impl<ID: ra_arena::ArenaId, T, V> Trace<ID, T, V> {
22 pub(crate) fn new_for_arena() -> Trace<ID, T, V> {
23 Trace { for_arena: true, arena: Arena::default(), map: ArenaMap::default(), len: 0 }
24 }
25
26 pub(crate) fn new_for_map() -> Trace<ID, T, V> {
27 Trace { for_arena: false, arena: Arena::default(), map: ArenaMap::default(), len: 0 }
28 }
29
30 pub(crate) fn alloc(&mut self, value: impl Fn() -> V, data: impl Fn() -> T) {
31 if self.for_arena {
32 self.arena.alloc(data());
33 } else {
34 let id = ID::from_raw(RawId::from(self.len));
35 self.len += 1;
36 self.map.insert(id, value());
37 }
38 }
39
40 pub(crate) fn into_arena(self) -> Arena<ID, T> {
41 assert!(self.for_arena);
42 self.arena
43 }
44
45 pub(crate) fn into_map(self) -> ArenaMap<ID, V> {
46 assert!(!self.for_arena);
47 self.map
48 }
49}
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
deleted file mode 100644
index 6c2d5b2a9..000000000
--- a/crates/ra_hir_def/src/traits.rs
+++ /dev/null
@@ -1,66 +0,0 @@
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};
11
12use crate::{
13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
14 TypeAliasId, TypeAliasLoc,
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct TraitData {
19 pub name: Option<Name>,
20 pub items: Vec<AssocItemId>,
21 pub auto: bool,
22}
23
24impl TraitData {
25 pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
26 let src = tr.source(db);
27 let name = src.value.name().map(|n| n.as_name());
28 let auto = src.value.is_auto();
29 let ast_id_map = db.ast_id_map(src.file_id);
30 let items = if let Some(item_list) = src.value.item_list() {
31 item_list
32 .impl_items()
33 .map(|item_node| match item_node {
34 ast::ImplItem::FnDef(it) => FunctionLoc {
35 container: ContainerId::TraitId(tr),
36 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
37 }
38 .intern(db)
39 .into(),
40 ast::ImplItem::ConstDef(it) => ConstLoc {
41 container: ContainerId::TraitId(tr),
42 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
43 }
44 .intern(db)
45 .into(),
46 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
47 container: ContainerId::TraitId(tr),
48 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
49 }
50 .intern(db)
51 .into(),
52 })
53 .collect()
54 } else {
55 Vec::new()
56 };
57 Arc::new(TraitData { name, items, auto })
58 }
59
60 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
61 self.items.iter().filter_map(|item| match item {
62 AssocItemId::TypeAliasId(t) => Some(*t),
63 _ => None,
64 })
65 }
66}