aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/adt.rs109
-rw-r--r--crates/ra_hir/src/code_model_api.rs187
-rw-r--r--crates/ra_hir/src/code_model_impl.rs15
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs23
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs24
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs146
-rw-r--r--crates/ra_hir/src/db.rs65
-rw-r--r--crates/ra_hir/src/expr.rs22
-rw-r--r--crates/ra_hir/src/generics.rs59
-rw-r--r--crates/ra_hir/src/ids.rs266
-rw-r--r--crates/ra_hir/src/impl_block.rs84
-rw-r--r--crates/ra_hir/src/lib.rs21
-rw-r--r--crates/ra_hir/src/mock.rs13
-rw-r--r--crates/ra_hir/src/module_tree.rs36
-rw-r--r--crates/ra_hir/src/nameres.rs56
-rw-r--r--crates/ra_hir/src/nameres/lower.rs178
-rw-r--r--crates/ra_hir/src/nameres/tests.rs35
-rw-r--r--crates/ra_hir/src/query_definitions.rs26
-rw-r--r--crates/ra_hir/src/source_binder.rs51
-rw-r--r--crates/ra_hir/src/ty.rs218
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs38
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap12
22 files changed, 808 insertions, 876 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index ab1c428db..6b13b464d 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -3,25 +3,35 @@
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use ra_syntax::{ 6use ra_syntax::ast::{self, NameOwner, StructFlavor};
7 SyntaxNode,
8 ast::{self, NameOwner, StructFlavor, AstNode}
9};
10 7
11use crate::{ 8use crate::{
12 DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, 9 Name, AsName, Struct, Enum, EnumVariant, Crate,
13 HirDatabase, DefKind, 10 HirDatabase,
14 SourceItemId,
15 type_ref::TypeRef, 11 type_ref::TypeRef,
12 ids::LocationCtx,
16}; 13};
17 14
18impl Struct { 15#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19 pub(crate) fn new(def_id: DefId) -> Self { 16pub enum AdtDef {
20 Struct { def_id } 17 Struct(Struct),
18 Enum(Enum),
19}
20impl_froms!(AdtDef: Struct, Enum);
21
22impl AdtDef {
23 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
24 match self {
25 AdtDef::Struct(s) => s.module(db),
26 AdtDef::Enum(e) => e.module(db),
27 }
28 .krate(db)
21 } 29 }
30}
22 31
32impl Struct {
23 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { 33 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
24 db.struct_data(self.def_id).variant_data.clone() 34 db.struct_data((*self).into()).variant_data.clone()
25 } 35 }
26} 36}
27 37
@@ -39,38 +49,12 @@ impl StructData {
39 StructData { name, variant_data } 49 StructData { name, variant_data }
40 } 50 }
41 51
42 pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<StructData> { 52 pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<StructData> {
43 let def_loc = def_id.loc(db); 53 let (_, struct_def) = struct_.source(db);
44 assert!(def_loc.kind == DefKind::Struct); 54 Arc::new(StructData::new(&*struct_def))
45 let syntax = db.file_item(def_loc.source_item_id);
46 let struct_def =
47 ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node");
48 Arc::new(StructData::new(struct_def))
49 } 55 }
50} 56}
51 57
52fn get_def_id(
53 db: &impl HirDatabase,
54 same_file_loc: &DefLoc,
55 node: &SyntaxNode,
56 expected_kind: DefKind,
57) -> DefId {
58 let file_id = same_file_loc.source_item_id.file_id;
59 let file_items = db.file_items(file_id);
60
61 let item_id = file_items.id_of(file_id, node);
62 let source_item_id = SourceItemId {
63 item_id: Some(item_id),
64 ..same_file_loc.source_item_id
65 };
66 let loc = DefLoc {
67 kind: expected_kind,
68 source_item_id,
69 ..*same_file_loc
70 };
71 loc.id(db)
72}
73
74#[derive(Debug, Clone, PartialEq, Eq)] 58#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct EnumData { 59pub struct EnumData {
76 pub(crate) name: Option<Name>, 60 pub(crate) name: Option<Name>,
@@ -83,27 +67,24 @@ impl EnumData {
83 EnumData { name, variants } 67 EnumData { name, variants }
84 } 68 }
85 69
86 pub(crate) fn enum_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<EnumData> { 70 pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> {
87 let def_loc = def_id.loc(db); 71 let (file_id, enum_def) = e.source(db);
88 assert!(def_loc.kind == DefKind::Enum); 72 let module = e.module(db);
89 let syntax = db.file_item(def_loc.source_item_id); 73 let ctx = LocationCtx::new(db, module, file_id);
90 let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node");
91 let variants = if let Some(vl) = enum_def.variant_list() { 74 let variants = if let Some(vl) = enum_def.variant_list() {
92 vl.variants() 75 vl.variants()
93 .filter_map(|variant_def| { 76 .filter_map(|variant_def| {
94 let name = variant_def.name().map(|n| n.as_name()); 77 let name = variant_def.name()?.as_name();
95 78 let var = EnumVariant {
96 name.map(|n| { 79 id: ctx.to_def(variant_def),
97 let def_id = 80 };
98 get_def_id(db, &def_loc, variant_def.syntax(), DefKind::EnumVariant); 81 Some((name, var))
99 (n, EnumVariant::new(def_id))
100 })
101 }) 82 })
102 .collect() 83 .collect()
103 } else { 84 } else {
104 Vec::new() 85 Vec::new()
105 }; 86 };
106 Arc::new(EnumData::new(enum_def, variants)) 87 Arc::new(EnumData::new(&*enum_def, variants))
107 } 88 }
108} 89}
109 90
@@ -128,21 +109,15 @@ impl EnumVariantData {
128 109
129 pub(crate) fn enum_variant_data_query( 110 pub(crate) fn enum_variant_data_query(
130 db: &impl HirDatabase, 111 db: &impl HirDatabase,
131 def_id: DefId, 112 var: EnumVariant,
132 ) -> Arc<EnumVariantData> { 113 ) -> Arc<EnumVariantData> {
133 let def_loc = def_id.loc(db); 114 let (file_id, variant_def) = var.source(db);
134 assert!(def_loc.kind == DefKind::EnumVariant); 115 let enum_def = variant_def.parent_enum();
135 let syntax = db.file_item(def_loc.source_item_id); 116 let ctx = LocationCtx::new(db, var.module(db), file_id);
136 let variant_def = ast::EnumVariant::cast(&syntax) 117 let e = Enum {
137 .expect("enum variant def should point to EnumVariant node"); 118 id: ctx.to_def(enum_def),
138 let enum_node = syntax 119 };
139 .parent() 120 Arc::new(EnumVariantData::new(&*variant_def, e))
140 .expect("enum variant should have enum variant list ancestor")
141 .parent()
142 .expect("enum variant list should have enum ancestor");
143 let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum);
144
145 Arc::new(EnumVariantData::new(variant_def, Enum::new(enum_def_id)))
146 } 121 }
147} 122}
148 123
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 3ff07bd60..6739627b4 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -5,22 +5,23 @@ use ra_db::{CrateId, FileId};
5use ra_syntax::{ast::self, TreeArc, SyntaxNode}; 5use ra_syntax::{ast::self, TreeArc, SyntaxNode};
6 6
7use crate::{ 7use crate::{
8 Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, 8 Name, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId,
9 type_ref::TypeRef, 9 type_ref::TypeRef,
10 nameres::{ModuleScope, lower::ImportId}, 10 nameres::{ModuleScope, lower::ImportId},
11 db::HirDatabase, 11 db::HirDatabase,
12 expr::BodySyntaxMapping, 12 expr::BodySyntaxMapping,
13 ty::InferenceResult, 13 ty::{InferenceResult, VariantDef},
14 adt::VariantData, 14 adt::VariantData,
15 generics::GenericParams, 15 generics::GenericParams,
16 code_model_impl::def_id_to_ast, 16 docs::{Documentation, Docs, docs_from_ast},
17 docs::{Documentation, Docs, docs_from_ast} 17 module_tree::ModuleId,
18 ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef, ConstId, StaticId, TraitId, TypeId},
18}; 19};
19 20
20/// hir::Crate describes a single crate. It's the main interface with which 21/// hir::Crate describes a single crate. It's the main interface with which
21/// a crate's dependencies interact. Mostly, it should be just a proxy for the 22/// a crate's dependencies interact. Mostly, it should be just a proxy for the
22/// root module. 23/// root module.
23#[derive(Debug, Clone, PartialEq, Eq, Hash)] 24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub struct Crate { 25pub struct Crate {
25 pub(crate) crate_id: CrateId, 26 pub(crate) crate_id: CrateId,
26} 27}
@@ -45,22 +46,40 @@ impl Crate {
45 46
46#[derive(Debug)] 47#[derive(Debug)]
47pub enum Def { 48pub enum Def {
49 Item,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53pub struct Module {
54 pub(crate) krate: CrateId,
55 pub(crate) module_id: ModuleId,
56}
57
58/// The defs which can be visible in the module.
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum ModuleDef {
48 Module(Module), 61 Module(Module),
62 Function(Function),
49 Struct(Struct), 63 Struct(Struct),
50 Enum(Enum), 64 Enum(Enum),
65 // Can't be directly declared, but can be imported.
51 EnumVariant(EnumVariant), 66 EnumVariant(EnumVariant),
52 Function(Function),
53 Const(Const), 67 Const(Const),
54 Static(Static), 68 Static(Static),
55 Trait(Trait), 69 Trait(Trait),
56 Type(Type), 70 Type(Type),
57 Item,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Hash)]
61pub struct Module {
62 pub(crate) def_id: DefId,
63} 71}
72impl_froms!(
73 ModuleDef: Module,
74 Function,
75 Struct,
76 Enum,
77 EnumVariant,
78 Const,
79 Static,
80 Trait,
81 Type
82);
64 83
65pub enum ModuleSource { 84pub enum ModuleSource {
66 SourceFile(TreeArc<ast::SourceFile>), 85 SourceFile(TreeArc<ast::SourceFile>),
@@ -149,7 +168,7 @@ impl Module {
149 self.scope_impl(db) 168 self.scope_impl(db)
150 } 169 }
151 170
152 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> { 171 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> {
153 self.resolve_path_impl(db, path) 172 self.resolve_path_impl(db, path)
154 } 173 }
155 174
@@ -160,7 +179,7 @@ impl Module {
160 179
161#[derive(Debug, Clone, PartialEq, Eq, Hash)] 180#[derive(Debug, Clone, PartialEq, Eq, Hash)]
162pub struct StructField { 181pub struct StructField {
163 parent: DefId, 182 parent: VariantDef,
164 name: Name, 183 name: Name,
165} 184}
166 185
@@ -174,38 +193,38 @@ impl StructField {
174 } 193 }
175} 194}
176 195
177#[derive(Debug, Clone, PartialEq, Eq, Hash)] 196#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
178pub struct Struct { 197pub struct Struct {
179 pub(crate) def_id: DefId, 198 pub(crate) id: StructId,
180} 199}
181 200
182impl Struct { 201impl Struct {
183 pub fn def_id(&self) -> DefId { 202 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
184 self.def_id 203 self.id.source(db)
204 }
205
206 pub fn module(&self, db: &impl HirDatabase) -> Module {
207 self.id.module(db)
185 } 208 }
186 209
187 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { 210 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
188 db.struct_data(self.def_id).name.clone() 211 db.struct_data(*self).name.clone()
189 } 212 }
190 213
191 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { 214 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
192 db.struct_data(self.def_id) 215 db.struct_data(*self)
193 .variant_data 216 .variant_data
194 .fields() 217 .fields()
195 .iter() 218 .iter()
196 .map(|it| StructField { 219 .map(|it| StructField {
197 parent: self.def_id, 220 parent: (*self).into(),
198 name: it.name.clone(), 221 name: it.name.clone(),
199 }) 222 })
200 .collect() 223 .collect()
201 } 224 }
202 225
203 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
204 def_id_to_ast(db, self.def_id)
205 }
206
207 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 226 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
208 db.generic_params(self.def_id) 227 db.generic_params((*self).into())
209 } 228 }
210} 229}
211 230
@@ -215,34 +234,30 @@ impl Docs for Struct {
215 } 234 }
216} 235}
217 236
218#[derive(Debug, Clone, PartialEq, Eq, Hash)] 237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
219pub struct Enum { 238pub struct Enum {
220 pub(crate) def_id: DefId, 239 pub(crate) id: EnumId,
221} 240}
222 241
223impl Enum { 242impl Enum {
224 pub(crate) fn new(def_id: DefId) -> Self { 243 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
225 Enum { def_id } 244 self.id.source(db)
226 } 245 }
227 246
228 pub fn def_id(&self) -> DefId { 247 pub fn module(&self, db: &impl HirDatabase) -> Module {
229 self.def_id 248 self.id.module(db)
230 } 249 }
231 250
232 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { 251 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
233 db.enum_data(self.def_id).name.clone() 252 db.enum_data(*self).name.clone()
234 } 253 }
235 254
236 pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> { 255 pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> {
237 db.enum_data(self.def_id).variants.clone() 256 db.enum_data(*self).variants.clone()
238 }
239
240 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
241 def_id_to_ast(db, self.def_id)
242 } 257 }
243 258
244 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 259 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
245 db.generic_params(self.def_id) 260 db.generic_params((*self).into())
246 } 261 }
247} 262}
248 263
@@ -252,30 +267,28 @@ impl Docs for Enum {
252 } 267 }
253} 268}
254 269
255#[derive(Debug, Clone, PartialEq, Eq, Hash)] 270#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
256pub struct EnumVariant { 271pub struct EnumVariant {
257 pub(crate) def_id: DefId, 272 pub(crate) id: EnumVariantId,
258} 273}
259 274
260impl EnumVariant { 275impl EnumVariant {
261 pub(crate) fn new(def_id: DefId) -> Self { 276 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) {
262 EnumVariant { def_id } 277 self.id.source(db)
263 } 278 }
264 279 pub fn module(&self, db: &impl HirDatabase) -> Module {
265 pub fn def_id(&self) -> DefId { 280 self.id.module(db)
266 self.def_id
267 } 281 }
268
269 pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum { 282 pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum {
270 db.enum_variant_data(self.def_id).parent_enum.clone() 283 db.enum_variant_data(*self).parent_enum.clone()
271 } 284 }
272 285
273 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { 286 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
274 db.enum_variant_data(self.def_id).name.clone() 287 db.enum_variant_data(*self).name.clone()
275 } 288 }
276 289
277 pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { 290 pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
278 db.enum_variant_data(self.def_id).variant_data.clone() 291 db.enum_variant_data(*self).variant_data.clone()
279 } 292 }
280 293
281 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { 294 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
@@ -283,15 +296,11 @@ impl EnumVariant {
283 .fields() 296 .fields()
284 .iter() 297 .iter()
285 .map(|it| StructField { 298 .map(|it| StructField {
286 parent: self.def_id, 299 parent: (*self).into(),
287 name: it.name.clone(), 300 name: it.name.clone(),
288 }) 301 })
289 .collect() 302 .collect()
290 } 303 }
291
292 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) {
293 def_id_to_ast(db, self.def_id)
294 }
295} 304}
296 305
297impl Docs for EnumVariant { 306impl Docs for EnumVariant {
@@ -300,9 +309,9 @@ impl Docs for EnumVariant {
300 } 309 }
301} 310}
302 311
303#[derive(Debug, Clone, PartialEq, Eq, Hash)] 312#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
304pub struct Function { 313pub struct Function {
305 pub(crate) def_id: DefId, 314 pub(crate) id: FunctionId,
306} 315}
307 316
308pub use crate::code_model_impl::function::ScopeEntryWithSyntax; 317pub use crate::code_model_impl::function::ScopeEntryWithSyntax;
@@ -339,21 +348,21 @@ impl FnSignature {
339} 348}
340 349
341impl Function { 350impl Function {
342 pub fn def_id(&self) -> DefId { 351 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) {
343 self.def_id 352 self.id.source(db)
344 } 353 }
345 354
346 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { 355 pub fn module(&self, db: &impl HirDatabase) -> Module {
347 def_id_to_ast(db, self.def_id) 356 self.id.module(db)
348 } 357 }
349 358
350 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { 359 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
351 db.body_syntax_mapping(self.def_id) 360 db.body_syntax_mapping(*self)
352 } 361 }
353 362
354 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { 363 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
355 let scopes = db.fn_scopes(self.def_id); 364 let scopes = db.fn_scopes(*self);
356 let syntax_mapping = db.body_syntax_mapping(self.def_id); 365 let syntax_mapping = db.body_syntax_mapping(*self);
357 ScopesWithSyntaxMapping { 366 ScopesWithSyntaxMapping {
358 scopes, 367 scopes,
359 syntax_mapping, 368 syntax_mapping,
@@ -361,15 +370,15 @@ impl Function {
361 } 370 }
362 371
363 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { 372 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
364 db.fn_signature(self.def_id) 373 db.fn_signature(*self)
365 } 374 }
366 375
367 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 376 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
368 db.infer(self.def_id) 377 db.infer(*self)
369 } 378 }
370 379
371 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 380 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
372 db.generic_params(self.def_id) 381 db.generic_params((*self).into())
373 } 382 }
374} 383}
375 384
@@ -379,18 +388,14 @@ impl Docs for Function {
379 } 388 }
380} 389}
381 390
382#[derive(Debug, Clone, PartialEq, Eq, Hash)] 391#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
383pub struct Const { 392pub struct Const {
384 pub(crate) def_id: DefId, 393 pub(crate) id: ConstId,
385} 394}
386 395
387impl Const { 396impl Const {
388 pub(crate) fn new(def_id: DefId) -> Const {
389 Const { def_id }
390 }
391
392 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) { 397 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) {
393 def_id_to_ast(db, self.def_id) 398 self.id.source(db)
394 } 399 }
395} 400}
396 401
@@ -400,18 +405,14 @@ impl Docs for Const {
400 } 405 }
401} 406}
402 407
403#[derive(Debug, Clone, PartialEq, Eq, Hash)] 408#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
404pub struct Static { 409pub struct Static {
405 pub(crate) def_id: DefId, 410 pub(crate) id: StaticId,
406} 411}
407 412
408impl Static { 413impl Static {
409 pub(crate) fn new(def_id: DefId) -> Static {
410 Static { def_id }
411 }
412
413 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) { 414 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) {
414 def_id_to_ast(db, self.def_id) 415 self.id.source(db)
415 } 416 }
416} 417}
417 418
@@ -421,22 +422,18 @@ impl Docs for Static {
421 } 422 }
422} 423}
423 424
424#[derive(Debug, Clone, PartialEq, Eq, Hash)] 425#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
425pub struct Trait { 426pub struct Trait {
426 pub(crate) def_id: DefId, 427 pub(crate) id: TraitId,
427} 428}
428 429
429impl Trait { 430impl Trait {
430 pub(crate) fn new(def_id: DefId) -> Trait {
431 Trait { def_id }
432 }
433
434 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { 431 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) {
435 def_id_to_ast(db, self.def_id) 432 self.id.source(db)
436 } 433 }
437 434
438 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 435 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
439 db.generic_params(self.def_id) 436 db.generic_params((*self).into())
440 } 437 }
441} 438}
442 439
@@ -446,22 +443,18 @@ impl Docs for Trait {
446 } 443 }
447} 444}
448 445
449#[derive(Debug, Clone, PartialEq, Eq, Hash)] 446#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
450pub struct Type { 447pub struct Type {
451 pub(crate) def_id: DefId, 448 pub(crate) id: TypeId,
452} 449}
453 450
454impl Type { 451impl Type {
455 pub(crate) fn new(def_id: DefId) -> Type {
456 Type { def_id }
457 }
458
459 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { 452 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) {
460 def_id_to_ast(db, self.def_id) 453 self.id.source(db)
461 } 454 }
462 455
463 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 456 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
464 db.generic_params(self.def_id) 457 db.generic_params((*self).into())
465 } 458 }
466} 459}
467 460
diff --git a/crates/ra_hir/src/code_model_impl.rs b/crates/ra_hir/src/code_model_impl.rs
index 0cea9f7b6..1f28fab74 100644
--- a/crates/ra_hir/src/code_model_impl.rs
+++ b/crates/ra_hir/src/code_model_impl.rs
@@ -1,18 +1,3 @@
1mod krate; // `crate` is invalid ident :( 1mod krate; // `crate` is invalid ident :(
2mod module; 2mod module;
3pub(crate) mod function; 3pub(crate) mod function;
4
5use ra_syntax::{AstNode, TreeArc};
6
7use crate::{HirDatabase, DefId, HirFileId};
8
9pub(crate) fn def_id_to_ast<N: AstNode>(
10 db: &impl HirDatabase,
11 def_id: DefId,
12) -> (HirFileId, TreeArc<N>) {
13 let (file_id, syntax) = def_id.source(db);
14 let ast = N::cast(&syntax)
15 .unwrap_or_else(|| panic!("def points to wrong source {:?} {:?}", def_id, syntax))
16 .to_owned();
17 (file_id, ast)
18}
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index c68c6bfbf..e0dd4d629 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -2,41 +2,32 @@ mod scope;
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_syntax::{TreeArc, ast::{self, NameOwner}}; 5use ra_syntax::ast::{self, NameOwner};
6 6
7use crate::{ 7use crate::{
8 DefId, HirDatabase, Name, AsName, Function, FnSignature, Module, 8 HirDatabase, Name, AsName, Function, FnSignature,
9 type_ref::{TypeRef, Mutability}, 9 type_ref::{TypeRef, Mutability},
10 expr::Body, 10 expr::Body,
11 impl_block::ImplBlock, 11 impl_block::ImplBlock,
12 code_model_impl::def_id_to_ast,
13}; 12};
14 13
15pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; 14pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
16 15
17impl Function { 16impl Function {
18 pub(crate) fn new(def_id: DefId) -> Function {
19 Function { def_id }
20 }
21
22 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 17 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
23 db.body_hir(self.def_id) 18 db.body_hir(*self)
24 }
25
26 pub(crate) fn module(&self, db: &impl HirDatabase) -> Module {
27 self.def_id.module(db)
28 } 19 }
29 20
30 /// The containing impl block, if this is a method. 21 /// The containing impl block, if this is a method.
31 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { 22 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> {
32 self.def_id.impl_block(db) 23 let module_impls = db.impls_in_module(self.module(db));
24 ImplBlock::containing(module_impls, (*self).into())
33 } 25 }
34} 26}
35 27
36impl FnSignature { 28impl FnSignature {
37 pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> { 29 pub(crate) fn fn_signature_query(db: &impl HirDatabase, func: Function) -> Arc<FnSignature> {
38 // FIXME: we're using def_id_to_ast here to avoid returning Cancelable... this is a bit hacky 30 let (_, node) = func.source(db);
39 let node: TreeArc<ast::FnDef> = def_id_to_ast(db, def_id).1;
40 let name = node 31 let name = node
41 .name() 32 .name()
42 .map(|n| n.as_name()) 33 .map(|n| n.as_name())
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs
index 8c6e34873..cdd30b402 100644
--- a/crates/ra_hir/src/code_model_impl/krate.rs
+++ b/crates/ra_hir/src/code_model_impl/krate.rs
@@ -1,7 +1,7 @@
1use ra_db::CrateId; 1use ra_db::CrateId;
2 2
3use crate::{ 3use crate::{
4 HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId, 4 Crate, CrateDependency, AsName, Module,
5 db::HirDatabase, 5 db::HirDatabase,
6}; 6};
7 7
@@ -21,27 +21,13 @@ impl Crate {
21 .collect() 21 .collect()
22 } 22 }
23 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> { 23 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> {
24 let crate_graph = db.crate_graph(); 24 let module_tree = db.module_tree(self.crate_id);
25 let file_id = crate_graph.crate_root(self.crate_id); 25 let module_id = module_tree.modules().next()?;
26 let source_root_id = db.file_source_root(file_id);
27 let file_id = HirFileId::from(file_id);
28 let module_tree = db.module_tree(source_root_id);
29 // FIXME: teach module tree about crate roots instead of guessing
30 let source = SourceItemId {
31 file_id,
32 item_id: None,
33 };
34 let module_id = module_tree.find_module_by_source(source)?;
35 26
36 let def_loc = DefLoc { 27 let module = Module {
37 kind: DefKind::Module, 28 krate: self.crate_id,
38 source_root_id,
39 module_id, 29 module_id,
40 source_item_id: module_id.source(&module_tree),
41 }; 30 };
42 let def_id = def_loc.id(db);
43
44 let module = Module::new(def_id);
45 Some(module) 31 Some(module)
46 } 32 }
47} 33}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index d94079f11..6419d3934 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -1,52 +1,33 @@
1use ra_db::{SourceRootId, FileId}; 1use ra_db::FileId;
2use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; 2use ra_syntax::{ast, SyntaxNode, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Problem, 5 Module, ModuleSource, Problem, ModuleDef,
6 Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, 6 Crate, Name, Path, PathKind, PerNs,
7 module_tree::ModuleId, 7 module_tree::ModuleId,
8 nameres::{ModuleScope, lower::ImportId}, 8 nameres::{ModuleScope, lower::ImportId},
9 db::HirDatabase, 9 db::HirDatabase,
10}; 10};
11 11
12impl Module { 12impl Module {
13 pub(crate) fn new(def_id: DefId) -> Self { 13 fn with_module_id(&self, module_id: ModuleId) -> Module {
14 crate::code_model_api::Module { def_id } 14 Module {
15 }
16
17 pub(crate) fn from_module_id(
18 db: &impl HirDatabase,
19 source_root_id: SourceRootId,
20 module_id: ModuleId,
21 ) -> Self {
22 let module_tree = db.module_tree(source_root_id);
23 let def_loc = DefLoc {
24 kind: DefKind::Module,
25 source_root_id,
26 module_id, 15 module_id,
27 source_item_id: module_id.source(&module_tree), 16 krate: self.krate,
28 }; 17 }
29 let def_id = def_loc.id(db);
30 Module::new(def_id)
31 } 18 }
32 19
33 pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> { 20 pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> {
34 let loc = self.def_id.loc(db); 21 let module_tree = db.module_tree(self.krate);
35 let module_tree = db.module_tree(loc.source_root_id); 22 let link = self.module_id.parent_link(&module_tree)?;
36 let link = loc.module_id.parent_link(&module_tree)?;
37 Some(link.name(&module_tree).clone()) 23 Some(link.name(&module_tree).clone())
38 } 24 }
39 25
40 pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { 26 pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) {
41 let loc = self.def_id.loc(db); 27 let module_tree = db.module_tree(self.krate);
42 let file_id = loc.source_item_id.file_id.as_original_file(); 28 let source = self.module_id.source(&module_tree);
43 let syntax_node = db.file_item(loc.source_item_id); 29 let module_source = ModuleSource::from_source_item_id(db, source);
44 let module_source = if let Some(source_file) = ast::SourceFile::cast(&syntax_node) { 30 let file_id = source.file_id.as_original_file();
45 ModuleSource::SourceFile(source_file.to_owned())
46 } else {
47 let module = ast::Module::cast(&syntax_node).unwrap();
48 ModuleSource::Module(module.to_owned())
49 };
50 (file_id, module_source) 31 (file_id, module_source)
51 } 32 }
52 33
@@ -54,9 +35,8 @@ impl Module {
54 &self, 35 &self,
55 db: &impl HirDatabase, 36 db: &impl HirDatabase,
56 ) -> Option<(FileId, TreeArc<ast::Module>)> { 37 ) -> Option<(FileId, TreeArc<ast::Module>)> {
57 let loc = self.def_id.loc(db); 38 let module_tree = db.module_tree(self.krate);
58 let module_tree = db.module_tree(loc.source_root_id); 39 let link = self.module_id.parent_link(&module_tree)?;
59 let link = loc.module_id.parent_link(&module_tree)?;
60 let file_id = link 40 let file_id = link
61 .owner(&module_tree) 41 .owner(&module_tree)
62 .source(&module_tree) 42 .source(&module_tree)
@@ -71,85 +51,67 @@ impl Module {
71 db: &impl HirDatabase, 51 db: &impl HirDatabase,
72 import: ImportId, 52 import: ImportId,
73 ) -> TreeArc<ast::PathSegment> { 53 ) -> TreeArc<ast::PathSegment> {
74 let loc = self.def_id.loc(db); 54 let source_map = db.lower_module_source_map(self.clone());
75 let source_map = db.lower_module_source_map(loc.source_root_id, loc.module_id);
76 let (_, source) = self.definition_source(db); 55 let (_, source) = self.definition_source(db);
77 source_map.get(&source, import) 56 source_map.get(&source, import)
78 } 57 }
79 58
80 pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option<Crate> { 59 pub(crate) fn krate_impl(&self, _db: &impl HirDatabase) -> Option<Crate> {
81 let root = self.crate_root(db); 60 Some(Crate::new(self.krate))
82 let loc = root.def_id.loc(db);
83 let file_id = loc.source_item_id.file_id.as_original_file();
84
85 let crate_graph = db.crate_graph();
86 let crate_id = crate_graph.crate_id_for_crate_root(file_id)?;
87 Some(Crate::new(crate_id))
88 } 61 }
89 62
90 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { 63 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module {
91 let loc = self.def_id.loc(db); 64 let module_tree = db.module_tree(self.krate);
92 let module_tree = db.module_tree(loc.source_root_id); 65 let module_id = self.module_id.crate_root(&module_tree);
93 let module_id = loc.module_id.crate_root(&module_tree); 66 self.with_module_id(module_id)
94 Module::from_module_id(db, loc.source_root_id, module_id)
95 } 67 }
96 68
97 /// Finds a child module with the specified name. 69 /// Finds a child module with the specified name.
98 pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { 70 pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
99 let loc = self.def_id.loc(db); 71 let module_tree = db.module_tree(self.krate);
100 let module_tree = db.module_tree(loc.source_root_id); 72 let child_id = self.module_id.child(&module_tree, name)?;
101 let child_id = loc.module_id.child(&module_tree, name)?; 73 Some(self.with_module_id(child_id))
102 Some(Module::from_module_id(db, loc.source_root_id, child_id))
103 } 74 }
104 75
105 /// Iterates over all child modules. 76 /// Iterates over all child modules.
106 pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { 77 pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> {
107 // FIXME this should be implementable without collecting into a vec, but 78 let module_tree = db.module_tree(self.krate);
108 // it's kind of hard since the iterator needs to keep a reference to the 79 let children = self
109 // module tree.
110 let loc = self.def_id.loc(db);
111 let module_tree = db.module_tree(loc.source_root_id);
112 let children = loc
113 .module_id 80 .module_id
114 .children(&module_tree) 81 .children(&module_tree)
115 .map(|(_, module_id)| Module::from_module_id(db, loc.source_root_id, module_id)) 82 .map(|(_, module_id)| self.with_module_id(module_id))
116 .collect::<Vec<_>>(); 83 .collect::<Vec<_>>();
117 children.into_iter() 84 children.into_iter()
118 } 85 }
119 86
120 pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> { 87 pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> {
121 let loc = self.def_id.loc(db); 88 let module_tree = db.module_tree(self.krate);
122 let module_tree = db.module_tree(loc.source_root_id); 89 let parent_id = self.module_id.parent(&module_tree)?;
123 let parent_id = loc.module_id.parent(&module_tree)?; 90 Some(self.with_module_id(parent_id))
124 Some(Module::from_module_id(db, loc.source_root_id, parent_id))
125 } 91 }
126 92
127 /// Returns a `ModuleScope`: a set of items, visible in this module. 93 /// Returns a `ModuleScope`: a set of items, visible in this module.
128 pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { 94 pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope {
129 let loc = self.def_id.loc(db); 95 let item_map = db.item_map(self.krate);
130 let item_map = db.item_map(loc.source_root_id); 96 item_map.per_module[&self.module_id].clone()
131 item_map.per_module[&loc.module_id].clone()
132 } 97 }
133 98
134 pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> { 99 pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> {
135 let mut curr_per_ns = PerNs::types( 100 let mut curr_per_ns: PerNs<ModuleDef> = PerNs::types(match path.kind {
136 match path.kind { 101 PathKind::Crate => self.crate_root(db).into(),
137 PathKind::Crate => self.crate_root(db), 102 PathKind::Self_ | PathKind::Plain => self.clone().into(),
138 PathKind::Self_ | PathKind::Plain => self.clone(), 103 PathKind::Super => {
139 PathKind::Super => { 104 if let Some(p) = self.parent(db) {
140 if let Some(p) = self.parent(db) { 105 p.into()
141 p 106 } else {
142 } else {
143 return PerNs::none();
144 }
145 }
146 PathKind::Abs => {
147 // TODO: absolute use is not supported
148 return PerNs::none(); 107 return PerNs::none();
149 } 108 }
150 } 109 }
151 .def_id, 110 PathKind::Abs => {
152 ); 111 // TODO: absolute use is not supported
112 return PerNs::none();
113 }
114 });
153 115
154 for segment in path.segments.iter() { 116 for segment in path.segments.iter() {
155 let curr = match curr_per_ns.as_ref().take_types() { 117 let curr = match curr_per_ns.as_ref().take_types() {
@@ -164,15 +126,16 @@ impl Module {
164 } 126 }
165 }; 127 };
166 // resolve segment in curr 128 // resolve segment in curr
167 curr_per_ns = match curr.resolve(db) { 129
168 Def::Module(m) => { 130 curr_per_ns = match curr {
131 ModuleDef::Module(m) => {
169 let scope = m.scope(db); 132 let scope = m.scope(db);
170 match scope.get(&segment.name) { 133 match scope.get(&segment.name) {
171 Some(r) => r.def_id, 134 Some(r) => r.def_id.clone(),
172 None => PerNs::none(), 135 None => PerNs::none(),
173 } 136 }
174 } 137 }
175 Def::Enum(e) => { 138 ModuleDef::Enum(e) => {
176 // enum variant 139 // enum variant
177 let matching_variant = e 140 let matching_variant = e
178 .variants(db) 141 .variants(db)
@@ -180,7 +143,7 @@ impl Module {
180 .find(|(n, _variant)| n == &segment.name); 143 .find(|(n, _variant)| n == &segment.name);
181 144
182 match matching_variant { 145 match matching_variant {
183 Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), 146 Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()),
184 None => PerNs::none(), 147 None => PerNs::none(),
185 } 148 }
186 } 149 }
@@ -199,8 +162,7 @@ impl Module {
199 &self, 162 &self,
200 db: &impl HirDatabase, 163 db: &impl HirDatabase,
201 ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { 164 ) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
202 let loc = self.def_id.loc(db); 165 let module_tree = db.module_tree(self.krate);
203 let module_tree = db.module_tree(loc.source_root_id); 166 self.module_id.problems(&module_tree, db)
204 loc.module_id.problems(&module_tree, db)
205 } 167 }
206} 168}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index cc03da1e2..5304f5d31 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,20 +1,21 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceRootId, SyntaxDatabase, salsa}; 4use ra_db::{SyntaxDatabase, CrateId, salsa};
5 5
6use crate::{ 6use crate::{
7 HirInterner, DefId, MacroCallId, Name, HirFileId, 7 MacroCallId, Name, HirFileId,
8 SourceFileItems, SourceItemId, Crate, 8 SourceFileItems, SourceItemId, Crate, Module, HirInterner,
9 query_definitions, 9 query_definitions,
10 FnSignature, FnScopes, 10 Function, FnSignature, FnScopes,
11 Struct, Enum, EnumVariant,
11 macros::MacroExpansion, 12 macros::MacroExpansion,
12 module_tree::{ModuleId, ModuleTree}, 13 module_tree::ModuleTree,
13 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, 14 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, 15 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef},
15 adt::{StructData, EnumData, EnumVariantData}, 16 adt::{StructData, EnumData, EnumVariantData},
16 impl_block::ModuleImplBlocks, 17 impl_block::ModuleImplBlocks,
17 generics::GenericParams, 18 generics::{GenericParams, GenericDef},
18}; 19};
19 20
20#[salsa::query_group] 21#[salsa::query_group]
@@ -26,25 +27,25 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
26 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; 27 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
27 28
28 #[salsa::invoke(query_definitions::fn_scopes)] 29 #[salsa::invoke(query_definitions::fn_scopes)]
29 fn fn_scopes(&self, def_id: DefId) -> Arc<FnScopes>; 30 fn fn_scopes(&self, func: Function) -> Arc<FnScopes>;
30 31
31 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 32 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
32 fn struct_data(&self, def_id: DefId) -> Arc<StructData>; 33 fn struct_data(&self, s: Struct) -> Arc<StructData>;
33 34
34 #[salsa::invoke(crate::adt::EnumData::enum_data_query)] 35 #[salsa::invoke(crate::adt::EnumData::enum_data_query)]
35 fn enum_data(&self, def_id: DefId) -> Arc<EnumData>; 36 fn enum_data(&self, e: Enum) -> Arc<EnumData>;
36 37
37 #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)] 38 #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)]
38 fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>; 39 fn enum_variant_data(&self, var: EnumVariant) -> Arc<EnumVariantData>;
39 40
40 #[salsa::invoke(crate::ty::infer)] 41 #[salsa::invoke(crate::ty::infer)]
41 fn infer(&self, def_id: DefId) -> Arc<InferenceResult>; 42 fn infer(&self, func: Function) -> Arc<InferenceResult>;
42 43
43 #[salsa::invoke(crate::ty::type_for_def)] 44 #[salsa::invoke(crate::ty::type_for_def)]
44 fn type_for_def(&self, def_id: DefId) -> Ty; 45 fn type_for_def(&self, def: TypableDef) -> Ty;
45 46
46 #[salsa::invoke(crate::ty::type_for_field)] 47 #[salsa::invoke(crate::ty::type_for_field)]
47 fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>; 48 fn type_for_field(&self, def: VariantDef, field: Name) -> Option<Ty>;
48 49
49 #[salsa::invoke(query_definitions::file_items)] 50 #[salsa::invoke(query_definitions::file_items)]
50 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; 51 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
@@ -56,51 +57,35 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
56 fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; 57 fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>;
57 58
58 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] 59 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)]
59 fn lower_module( 60 fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>);
60 &self,
61 source_root_id: SourceRootId,
62 module_id: ModuleId,
63 ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>);
64 61
65 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)] 62 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)]
66 fn lower_module_module( 63 fn lower_module_module(&self, module: Module) -> Arc<LoweredModule>;
67 &self,
68 source_root_id: SourceRootId,
69 module_id: ModuleId,
70 ) -> Arc<LoweredModule>;
71 64
72 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] 65 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)]
73 fn lower_module_source_map( 66 fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>;
74 &self,
75 source_root_id: SourceRootId,
76 module_id: ModuleId,
77 ) -> Arc<ImportSourceMap>;
78 67
79 #[salsa::invoke(query_definitions::item_map)] 68 #[salsa::invoke(query_definitions::item_map)]
80 fn item_map(&self, source_root_id: SourceRootId) -> Arc<ItemMap>; 69 fn item_map(&self, crate_id: CrateId) -> Arc<ItemMap>;
81 70
82 #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] 71 #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)]
83 fn module_tree(&self, source_root_id: SourceRootId) -> Arc<ModuleTree>; 72 fn module_tree(&self, crate_id: CrateId) -> Arc<ModuleTree>;
84 73
85 #[salsa::invoke(crate::impl_block::impls_in_module)] 74 #[salsa::invoke(crate::impl_block::impls_in_module)]
86 fn impls_in_module( 75 fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>;
87 &self,
88 source_root_id: SourceRootId,
89 module_id: ModuleId,
90 ) -> Arc<ModuleImplBlocks>;
91 76
92 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 77 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
93 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 78 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
94 79
95 #[salsa::invoke(crate::expr::body_hir)] 80 #[salsa::invoke(crate::expr::body_hir)]
96 fn body_hir(&self, def_id: DefId) -> Arc<crate::expr::Body>; 81 fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>;
97 82
98 #[salsa::invoke(crate::expr::body_syntax_mapping)] 83 #[salsa::invoke(crate::expr::body_syntax_mapping)]
99 fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; 84 fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>;
100 85
101 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] 86 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
102 fn generic_params(&self, def_id: DefId) -> Arc<GenericParams>; 87 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
103 88
104 #[salsa::invoke(crate::FnSignature::fn_signature_query)] 89 #[salsa::invoke(crate::FnSignature::fn_signature_query)]
105 fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; 90 fn fn_signature(&self, func: Function) -> Arc<FnSignature>;
106} 91}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 1a3821692..29469af2c 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -9,7 +9,11 @@ use ra_syntax::{
9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor} 9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor}
10}; 10};
11 11
12use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; 12use crate::{
13 Path, Name, HirDatabase, Function,
14 name::AsName,
15 type_ref::{Mutability, TypeRef},
16};
13use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; 17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
14 18
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 19#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -435,8 +439,8 @@ impl Pat {
435 439
436// Queries 440// Queries
437 441
438pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc<Body> { 442pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> {
439 Arc::clone(&body_syntax_mapping(db, def_id).body) 443 Arc::clone(&body_syntax_mapping(db, func).body)
440} 444}
441 445
442struct ExprCollector { 446struct ExprCollector {
@@ -955,14 +959,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
955 collector.into_body_syntax_mapping(params, body) 959 collector.into_body_syntax_mapping(params, body)
956} 960}
957 961
958pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, def_id: DefId) -> Arc<BodySyntaxMapping> { 962pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> {
959 let def = def_id.resolve(db); 963 let (_, fn_def) = func.source(db);
960 964 let body_syntax_mapping = collect_fn_body_syntax(&fn_def);
961 let body_syntax_mapping = match def {
962 Def::Function(f) => collect_fn_body_syntax(&f.source(db).1),
963 // TODO: consts, etc.
964 _ => panic!("Trying to get body for item type without body"),
965 };
966
967 Arc::new(body_syntax_mapping) 965 Arc::new(body_syntax_mapping)
968} 966}
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index d8248ad49..64c20a462 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -5,9 +5,9 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use ra_syntax::ast::{TypeParamList, AstNode, NameOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner};
9 9
10use crate::{db::HirDatabase, DefId, Name, AsName}; 10use crate::{db::HirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type};
11 11
12/// Data about a generic parameter (to a function, struct, impl, ...). 12/// Data about a generic parameter (to a function, struct, impl, ...).
13#[derive(Clone, PartialEq, Eq, Debug)] 13#[derive(Clone, PartialEq, Eq, Debug)]
@@ -22,26 +22,53 @@ pub struct GenericParams {
22 pub(crate) params: Vec<GenericParam>, 22 pub(crate) params: Vec<GenericParam>,
23} 23}
24 24
25#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
26pub enum GenericDef {
27 Function(Function),
28 Struct(Struct),
29 Enum(Enum),
30 Trait(Trait),
31 Type(Type),
32}
33impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type);
34
25impl GenericParams { 35impl GenericParams {
26 pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> { 36 pub(crate) fn generic_params_query(
27 let (_file_id, node) = def_id.source(db); 37 db: &impl HirDatabase,
38 def: GenericDef,
39 ) -> Arc<GenericParams> {
28 let mut generics = GenericParams::default(); 40 let mut generics = GenericParams::default();
29 if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { 41 match def {
30 for (idx, type_param) in type_param_list.type_params().enumerate() { 42 GenericDef::Function(it) => generics.fill(&*it.source(db).1),
31 let name = type_param 43 GenericDef::Struct(it) => generics.fill(&*it.source(db).1),
32 .name() 44 GenericDef::Enum(it) => generics.fill(&*it.source(db).1),
33 .map(AsName::as_name) 45 GenericDef::Trait(it) => generics.fill(&*it.source(db).1),
34 .unwrap_or_else(Name::missing); 46 GenericDef::Type(it) => generics.fill(&*it.source(db).1),
35 let param = GenericParam {
36 idx: idx as u32,
37 name,
38 };
39 generics.params.push(param);
40 }
41 } 47 }
48
42 Arc::new(generics) 49 Arc::new(generics)
43 } 50 }
44 51
52 fn fill(&mut self, node: &impl TypeParamsOwner) {
53 if let Some(params) = node.type_param_list() {
54 self.fill_params(params)
55 }
56 }
57
58 fn fill_params(&mut self, params: &ast::TypeParamList) {
59 for (idx, type_param) in params.type_params().enumerate() {
60 let name = type_param
61 .name()
62 .map(AsName::as_name)
63 .unwrap_or_else(Name::missing);
64 let param = GenericParam {
65 idx: idx as u32,
66 name,
67 };
68 self.params.push(param);
69 }
70 }
71
45 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 72 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
46 self.params.iter().find(|p| &p.name == name) 73 self.params.iter().find(|p| &p.name == name)
47 } 74 }
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 43f0e81f9..b125a1518 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,22 +1,41 @@
1use ra_db::{SourceRootId, LocationIntener, FileId}; 1use std::{
2 marker::PhantomData,
3 hash::{Hash, Hasher},
4};
5
6use ra_db::{LocationIntener, FileId};
2use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; 7use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
3use ra_arena::{Arena, RawId, impl_arena_id}; 8use ra_arena::{Arena, RawId, ArenaId, impl_arena_id};
4 9
5use crate::{ 10use crate::{
6 HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, 11 HirDatabase,
7 Module, Trait, Type, Static, Const, 12 Module,
8 module_tree::ModuleId,
9}; 13};
10 14
11#[derive(Debug, Default)] 15#[derive(Debug, Default)]
12pub struct HirInterner { 16pub struct HirInterner {
13 defs: LocationIntener<DefLoc, DefId>,
14 macros: LocationIntener<MacroCallLoc, MacroCallId>, 17 macros: LocationIntener<MacroCallLoc, MacroCallId>,
18 fns: LocationIntener<ItemLoc<ast::FnDef>, FunctionId>,
19 structs: LocationIntener<ItemLoc<ast::StructDef>, StructId>,
20 enums: LocationIntener<ItemLoc<ast::EnumDef>, EnumId>,
21 enum_variants: LocationIntener<ItemLoc<ast::EnumVariant>, EnumVariantId>,
22 consts: LocationIntener<ItemLoc<ast::ConstDef>, ConstId>,
23 statics: LocationIntener<ItemLoc<ast::StaticDef>, StaticId>,
24 traits: LocationIntener<ItemLoc<ast::TraitDef>, TraitId>,
25 types: LocationIntener<ItemLoc<ast::TypeDef>, TypeId>,
15} 26}
16 27
17impl HirInterner { 28impl HirInterner {
18 pub fn len(&self) -> usize { 29 pub fn len(&self) -> usize {
19 self.defs.len() + self.macros.len() 30 self.macros.len()
31 + self.fns.len()
32 + self.structs.len()
33 + self.enums.len()
34 + self.enum_variants.len()
35 + self.consts.len()
36 + self.statics.len()
37 + self.traits.len()
38 + self.types.len()
20 } 39 }
21} 40}
22 41
@@ -110,10 +129,9 @@ impl From<MacroCallId> for HirFileId {
110pub struct MacroCallId(RawId); 129pub struct MacroCallId(RawId);
111impl_arena_id!(MacroCallId); 130impl_arena_id!(MacroCallId);
112 131
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 132#[derive(Debug, Clone, PartialEq, Eq, Hash)]
114pub struct MacroCallLoc { 133pub struct MacroCallLoc {
115 pub(crate) source_root_id: SourceRootId, 134 pub(crate) module: Module,
116 pub(crate) module_id: ModuleId,
117 pub(crate) source_item_id: SourceItemId, 135 pub(crate) source_item_id: SourceItemId,
118} 136}
119 137
@@ -130,117 +148,161 @@ impl MacroCallLoc {
130 } 148 }
131} 149}
132 150
133/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) 151#[derive(Debug)]
134/// in a specific module. 152pub struct ItemLoc<N: AstNode> {
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 153 pub(crate) module: Module,
136pub struct DefId(RawId); 154 raw: SourceItemId,
137impl_arena_id!(DefId); 155 _ty: PhantomData<N>,
138
139#[derive(Clone, Debug, PartialEq, Eq, Hash)]
140pub struct DefLoc {
141 pub(crate) kind: DefKind,
142 pub(crate) source_root_id: SourceRootId,
143 pub(crate) module_id: ModuleId,
144 pub(crate) source_item_id: SourceItemId,
145} 156}
146 157
147#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 158impl<N: AstNode> PartialEq for ItemLoc<N> {
148pub(crate) enum DefKind { 159 fn eq(&self, other: &Self) -> bool {
149 Module, 160 self.module == other.module && self.raw == other.raw
150 Function, 161 }
151 Struct, 162}
152 Enum, 163impl<N: AstNode> Eq for ItemLoc<N> {}
153 EnumVariant, 164impl<N: AstNode> Hash for ItemLoc<N> {
154 Const, 165 fn hash<H: Hasher>(&self, hasher: &mut H) {
155 Static, 166 self.module.hash(hasher);
156 Trait, 167 self.raw.hash(hasher);
157 Type, 168 }
158 Item,
159
160 /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the
161 /// name `Foo` needs to resolve to different types depending on whether we
162 /// are in the types or values namespace: As a type, `Foo` of course refers
163 /// to the struct `Foo`; as a value, `Foo` is a callable type with signature
164 /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to
165 /// have different defs in the two namespaces.
166 ///
167 /// rustc does the same; note that it even creates a struct constructor if
168 /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc).
169 StructCtor,
170} 169}
171 170
172impl DefId { 171impl<N: AstNode> Clone for ItemLoc<N> {
173 pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> DefLoc { 172 fn clone(&self) -> ItemLoc<N> {
174 db.as_ref().defs.id2loc(self) 173 ItemLoc {
174 module: self.module,
175 raw: self.raw,
176 _ty: PhantomData,
177 }
175 } 178 }
179}
176 180
177 pub fn resolve(self, db: &impl HirDatabase) -> Def { 181#[derive(Clone, Copy)]
178 let loc = self.loc(db); 182pub(crate) struct LocationCtx<DB> {
179 match loc.kind { 183 db: DB,
180 DefKind::Module => { 184 module: Module,
181 let module = Module::from_module_id(db, loc.source_root_id, loc.module_id); 185 file_id: HirFileId,
182 Def::Module(module) 186}
183 }
184 DefKind::Function => {
185 let function = Function::new(self);
186 Def::Function(function)
187 }
188 DefKind::Struct => {
189 let struct_def = Struct::new(self);
190 Def::Struct(struct_def)
191 }
192 DefKind::Enum => Def::Enum(Enum::new(self)),
193 DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)),
194 DefKind::Const => {
195 let def = Const::new(self);
196 Def::Const(def)
197 }
198 DefKind::Static => {
199 let def = Static::new(self);
200 Def::Static(def)
201 }
202 DefKind::Trait => {
203 let def = Trait::new(self);
204 Def::Trait(def)
205 }
206 DefKind::Type => {
207 let def = Type::new(self);
208 Def::Type(def)
209 }
210 187
211 DefKind::StructCtor => Def::Item, 188impl<'a, DB: HirDatabase> LocationCtx<&'a DB> {
212 DefKind::Item => Def::Item, 189 pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> {
190 LocationCtx {
191 db,
192 module,
193 file_id,
213 } 194 }
214 } 195 }
196 pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF
197 where
198 N: AstNode,
199 DEF: AstItemDef<N>,
200 {
201 DEF::from_ast(self, ast)
202 }
203}
204
205pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
206 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>;
207 fn from_ast(ctx: LocationCtx<&impl HirDatabase>, ast: &N) -> Self {
208 let items = ctx.db.file_items(ctx.file_id);
209 let raw = SourceItemId {
210 file_id: ctx.file_id,
211 item_id: Some(items.id_of(ctx.file_id, ast.syntax())),
212 };
213 let loc = ItemLoc {
214 module: ctx.module,
215 raw,
216 _ty: PhantomData,
217 };
218
219 Self::interner(ctx.db.as_ref()).loc2id(&loc)
220 }
221 fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) {
222 let int = Self::interner(db.as_ref());
223 let loc = int.id2loc(self);
224 let syntax = db.file_item(loc.raw);
225 let ast = N::cast(&syntax)
226 .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw))
227 .to_owned();
228 (loc.raw.file_id, ast)
229 }
230 fn module(self, db: &impl HirDatabase) -> Module {
231 let int = Self::interner(db.as_ref());
232 let loc = int.id2loc(self);
233 loc.module
234 }
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
238pub struct FunctionId(RawId);
239impl_arena_id!(FunctionId);
240impl AstItemDef<ast::FnDef> for FunctionId {
241 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::FnDef>, Self> {
242 &interner.fns
243 }
244}
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
247pub struct StructId(RawId);
248impl_arena_id!(StructId);
249impl AstItemDef<ast::StructDef> for StructId {
250 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::StructDef>, Self> {
251 &interner.structs
252 }
253}
215 254
216 pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<SyntaxNode>) { 255#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
217 let loc = self.loc(db); 256pub struct EnumId(RawId);
218 let syntax = db.file_item(loc.source_item_id); 257impl_arena_id!(EnumId);
219 (loc.source_item_id.file_id, syntax) 258impl AstItemDef<ast::EnumDef> for EnumId {
259 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::EnumDef>, Self> {
260 &interner.enums
220 } 261 }
262}
221 263
222 /// For a module, returns that module; for any other def, returns the containing module. 264#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
223 pub fn module(self, db: &impl HirDatabase) -> Module { 265pub struct EnumVariantId(RawId);
224 let loc = self.loc(db); 266impl_arena_id!(EnumVariantId);
225 Module::from_module_id(db, loc.source_root_id, loc.module_id) 267impl AstItemDef<ast::EnumVariant> for EnumVariantId {
268 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::EnumVariant>, Self> {
269 &interner.enum_variants
226 } 270 }
271}
227 272
228 /// Returns the containing crate. 273#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
229 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { 274pub struct ConstId(RawId);
230 self.module(db).krate(db) 275impl_arena_id!(ConstId);
276impl AstItemDef<ast::ConstDef> for ConstId {
277 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::ConstDef>, Self> {
278 &interner.consts
231 } 279 }
280}
232 281
233 /// Returns the containing impl block, if this is an impl item. 282#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
234 pub fn impl_block(self, db: &impl HirDatabase) -> Option<ImplBlock> { 283pub struct StaticId(RawId);
235 let loc = self.loc(db); 284impl_arena_id!(StaticId);
236 let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id); 285impl AstItemDef<ast::StaticDef> for StaticId {
237 ImplBlock::containing(module_impls, self) 286 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::StaticDef>, Self> {
287 &interner.statics
288 }
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
292pub struct TraitId(RawId);
293impl_arena_id!(TraitId);
294impl AstItemDef<ast::TraitDef> for TraitId {
295 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::TraitDef>, Self> {
296 &interner.traits
238 } 297 }
239} 298}
240 299
241impl DefLoc { 300#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242 pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> DefId { 301pub struct TypeId(RawId);
243 db.as_ref().defs.loc2id(&self) 302impl_arena_id!(TypeId);
303impl AstItemDef<ast::TypeDef> for TypeId {
304 fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::TypeDef>, Self> {
305 &interner.types
244 } 306 }
245} 307}
246 308
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 551d0d149..222e47349 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -3,14 +3,13 @@ use rustc_hash::FxHashMap;
3 3
4use ra_arena::{Arena, RawId, impl_arena_id}; 4use ra_arena::{Arena, RawId, impl_arena_id};
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast::{self, AstNode};
6use ra_db::{SourceRootId};
7 6
8use crate::{ 7use crate::{
9 DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, 8 Const, Type,
10 Function, HirInterner, 9 Function, HirFileId,
11 db::HirDatabase, 10 db::HirDatabase,
12 type_ref::TypeRef, 11 type_ref::TypeRef,
13 module_tree::ModuleId, 12 ids::LocationCtx,
14}; 13};
15 14
16use crate::code_model_api::{Module, ModuleSource}; 15use crate::code_model_api::{Module, ModuleSource};
@@ -24,9 +23,9 @@ pub struct ImplBlock {
24impl ImplBlock { 23impl ImplBlock {
25 pub(crate) fn containing( 24 pub(crate) fn containing(
26 module_impl_blocks: Arc<ModuleImplBlocks>, 25 module_impl_blocks: Arc<ModuleImplBlocks>,
27 def_id: DefId, 26 item: ImplItem,
28 ) -> Option<ImplBlock> { 27 ) -> Option<ImplBlock> {
29 let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?; 28 let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
30 Some(ImplBlock { 29 Some(ImplBlock {
31 module_impl_blocks, 30 module_impl_blocks,
32 impl_id, 31 impl_id,
@@ -66,39 +65,25 @@ pub struct ImplData {
66 65
67impl ImplData { 66impl ImplData {
68 pub(crate) fn from_ast( 67 pub(crate) fn from_ast(
69 db: &impl AsRef<HirInterner>, 68 db: &impl HirDatabase,
70 file_items: &SourceFileItems, 69 file_id: HirFileId,
71 module: &Module, 70 module: Module,
72 node: &ast::ImplBlock, 71 node: &ast::ImplBlock,
73 ) -> Self { 72 ) -> Self {
74 let target_trait = node.target_trait().map(TypeRef::from_ast); 73 let target_trait = node.target_trait().map(TypeRef::from_ast);
75 let target_type = TypeRef::from_ast_opt(node.target_type()); 74 let target_type = TypeRef::from_ast_opt(node.target_type());
76 let module_loc = module.def_id.loc(db); 75 let ctx = LocationCtx::new(db, module, file_id);
77 let items = if let Some(item_list) = node.item_list() { 76 let items = if let Some(item_list) = node.item_list() {
78 item_list 77 item_list
79 .impl_items() 78 .impl_items()
80 .map(|item_node| { 79 .map(|item_node| match item_node.kind() {
81 let kind = match item_node.kind() { 80 ast::ImplItemKind::FnDef(it) => {
82 ast::ImplItemKind::FnDef(..) => DefKind::Function, 81 ImplItem::Method(Function { id: ctx.to_def(it) })
83 ast::ImplItemKind::ConstDef(..) => DefKind::Item,
84 ast::ImplItemKind::TypeDef(..) => DefKind::Item,
85 };
86 let item_id = file_items.id_of_unchecked(item_node.syntax());
87 let source_item_id = SourceItemId {
88 file_id: module_loc.source_item_id.file_id,
89 item_id: Some(item_id),
90 };
91 let def_loc = DefLoc {
92 kind,
93 source_item_id,
94 ..module_loc
95 };
96 let def_id = def_loc.id(db);
97 match item_node.kind() {
98 ast::ImplItemKind::FnDef(..) => ImplItem::Method(Function::new(def_id)),
99 ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id),
100 ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id),
101 } 82 }
83 ast::ImplItemKind::ConstDef(it) => {
84 ImplItem::Const(Const { id: ctx.to_def(it) })
85 }
86 ast::ImplItemKind::TypeDef(it) => ImplItem::Type(Type { id: ctx.to_def(it) }),
102 }) 87 })
103 .collect() 88 .collect()
104 } else { 89 } else {
@@ -124,22 +109,19 @@ impl ImplData {
124 } 109 }
125} 110}
126 111
127#[derive(Debug, Clone, PartialEq, Eq)] 112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113//TODO: rename to ImplDef?
128pub enum ImplItem { 114pub enum ImplItem {
129 Method(Function), 115 Method(Function),
130 // these don't have their own types yet 116 Const(Const),
131 Const(DefId), 117 Type(Type),
132 Type(DefId),
133 // Existential 118 // Existential
134} 119}
120impl_froms!(ImplItem: Const, Type);
135 121
136impl ImplItem { 122impl From<Function> for ImplItem {
137 pub fn def_id(&self) -> DefId { 123 fn from(func: Function) -> ImplItem {
138 match self { 124 ImplItem::Method(func)
139 ImplItem::Method(f) => f.def_id(),
140 ImplItem::Const(def_id) => *def_id,
141 ImplItem::Type(def_id) => *def_id,
142 }
143 } 125 }
144} 126}
145 127
@@ -155,7 +137,7 @@ impl_arena_id!(ImplId);
155#[derive(Debug, PartialEq, Eq)] 137#[derive(Debug, PartialEq, Eq)]
156pub struct ModuleImplBlocks { 138pub struct ModuleImplBlocks {
157 pub(crate) impls: Arena<ImplId, ImplData>, 139 pub(crate) impls: Arena<ImplId, ImplData>,
158 impls_by_def: FxHashMap<DefId, ImplId>, 140 impls_by_def: FxHashMap<ImplItem, ImplId>,
159} 141}
160 142
161impl ModuleImplBlocks { 143impl ModuleImplBlocks {
@@ -168,6 +150,7 @@ impl ModuleImplBlocks {
168 150
169 fn collect(&mut self, db: &impl HirDatabase, module: Module) { 151 fn collect(&mut self, db: &impl HirDatabase, module: Module) {
170 let (file_id, module_source) = module.definition_source(db); 152 let (file_id, module_source) = module.definition_source(db);
153 let file_id: HirFileId = file_id.into();
171 let node = match &module_source { 154 let node = match &module_source {
172 ModuleSource::SourceFile(node) => node.syntax(), 155 ModuleSource::SourceFile(node) => node.syntax(),
173 ModuleSource::Module(node) => node 156 ModuleSource::Module(node) => node
@@ -176,25 +159,18 @@ impl ModuleImplBlocks {
176 .syntax(), 159 .syntax(),
177 }; 160 };
178 161
179 let source_file_items = db.file_items(file_id.into());
180
181 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { 162 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
182 let impl_block = ImplData::from_ast(db, &source_file_items, &module, impl_block_ast); 163 let impl_block = ImplData::from_ast(db, file_id, module, impl_block_ast);
183 let id = self.impls.alloc(impl_block); 164 let id = self.impls.alloc(impl_block);
184 for impl_item in &self.impls[id].items { 165 for &impl_item in &self.impls[id].items {
185 self.impls_by_def.insert(impl_item.def_id(), id); 166 self.impls_by_def.insert(impl_item, id);
186 } 167 }
187 } 168 }
188 } 169 }
189} 170}
190 171
191pub(crate) fn impls_in_module( 172pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> {
192 db: &impl HirDatabase,
193 source_root_id: SourceRootId,
194 module_id: ModuleId,
195) -> Arc<ModuleImplBlocks> {
196 let mut result = ModuleImplBlocks::new(); 173 let mut result = ModuleImplBlocks::new();
197 let module = Module::from_module_id(db, source_root_id, module_id);
198 result.collect(db, module); 174 result.collect(db, module);
199 Arc::new(result) 175 Arc::new(result)
200} 176}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 87b5a8b8a..596f9c38c 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -5,6 +5,18 @@
5//! to a particular crate instance. That is, it has cfg flags and features 5//! to a particular crate instance. That is, it has cfg flags and features
6//! applied. So, the relation between syntax and HIR is many-to-one. 6//! applied. So, the relation between syntax and HIR is many-to-one.
7 7
8macro_rules! impl_froms {
9 ($e:ident: $($v:ident), *) => {
10 $(
11 impl From<$v> for $e {
12 fn from(it: $v) -> $e {
13 $e::$v(it)
14 }
15 }
16 )*
17 }
18}
19
8pub mod db; 20pub mod db;
9#[cfg(test)] 21#[cfg(test)]
10mod mock; 22mod mock;
@@ -34,25 +46,26 @@ mod marks;
34use crate::{ 46use crate::{
35 db::HirDatabase, 47 db::HirDatabase,
36 name::{AsName, KnownName}, 48 name::{AsName, KnownName},
37 ids::{DefKind, SourceItemId, SourceFileItems}, 49 ids::{SourceItemId, SourceFileItems},
38}; 50};
39 51
40pub use self::{ 52pub use self::{
41 path::{Path, PathKind}, 53 path::{Path, PathKind},
42 name::Name, 54 name::Name,
43 ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, 55 ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner},
44 macros::{MacroDef, MacroInput, MacroExpansion}, 56 macros::{MacroDef, MacroInput, MacroExpansion},
45 nameres::{ItemMap, PerNs, Namespace, Resolution}, 57 nameres::{ItemMap, PerNs, Namespace, Resolution},
46 ty::Ty, 58 ty::Ty,
47 impl_block::{ImplBlock, ImplItem}, 59 impl_block::{ImplBlock, ImplItem},
48 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, 60 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
49 docs::{Docs, Documentation} 61 docs::{Docs, Documentation},
62 adt::AdtDef,
50}; 63};
51 64
52pub use self::code_model_api::{ 65pub use self::code_model_api::{
53 Crate, CrateDependency, 66 Crate, CrateDependency,
54 Def, 67 Def,
55 Module, ModuleSource, Problem, 68 Module, ModuleDef, ModuleSource, Problem,
56 Struct, Enum, EnumVariant, 69 Struct, Enum, EnumVariant,
57 Function, FnSignature, ScopeEntryWithSyntax, 70 Function, FnSignature, ScopeEntryWithSyntax,
58 StructField, 71 StructField,
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 4145c8048..361366f6a 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -35,10 +35,6 @@ impl MockDatabase {
35 let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text); 35 let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text);
36 db.query_mut(ra_db::SourceRootQuery) 36 db.query_mut(ra_db::SourceRootQuery)
37 .set(WORKSPACE, Arc::new(source_root.clone())); 37 .set(WORKSPACE, Arc::new(source_root.clone()));
38
39 let mut crate_graph = CrateGraph::default();
40 crate_graph.add_crate_root(file_id);
41 db.set_crate_graph(crate_graph);
42 (db, source_root, file_id) 38 (db, source_root, file_id)
43 } 39 }
44 40
@@ -97,6 +93,8 @@ impl MockDatabase {
97 text: &str, 93 text: &str,
98 ) -> FileId { 94 ) -> FileId {
99 assert!(path.starts_with('/')); 95 assert!(path.starts_with('/'));
96 let is_crate_root = path == "/lib.rs" || path == "/main.rs";
97
100 let path = RelativePathBuf::from_path(&path[1..]).unwrap(); 98 let path = RelativePathBuf::from_path(&path[1..]).unwrap();
101 let file_id = FileId(self.file_counter); 99 let file_id = FileId(self.file_counter);
102 self.file_counter += 1; 100 self.file_counter += 1;
@@ -107,6 +105,12 @@ impl MockDatabase {
107 self.query_mut(ra_db::FileSourceRootQuery) 105 self.query_mut(ra_db::FileSourceRootQuery)
108 .set(file_id, source_root_id); 106 .set(file_id, source_root_id);
109 source_root.files.insert(path, file_id); 107 source_root.files.insert(path, file_id);
108
109 if is_crate_root {
110 let mut crate_graph = CrateGraph::default();
111 crate_graph.add_crate_root(file_id);
112 self.set_crate_graph(crate_graph);
113 }
110 file_id 114 file_id
111 } 115 }
112 116
@@ -202,6 +206,7 @@ salsa::database_storage! {
202 fn file_relative_path() for ra_db::FileRelativePathQuery; 206 fn file_relative_path() for ra_db::FileRelativePathQuery;
203 fn file_source_root() for ra_db::FileSourceRootQuery; 207 fn file_source_root() for ra_db::FileSourceRootQuery;
204 fn source_root() for ra_db::SourceRootQuery; 208 fn source_root() for ra_db::SourceRootQuery;
209 fn source_root_crates() for ra_db::SourceRootCratesQuery;
205 fn local_roots() for ra_db::LocalRootsQuery; 210 fn local_roots() for ra_db::LocalRootsQuery;
206 fn library_roots() for ra_db::LibraryRootsQuery; 211 fn library_roots() for ra_db::LibraryRootsQuery;
207 fn crate_graph() for ra_db::CrateGraphQuery; 212 fn crate_graph() for ra_db::CrateGraphQuery;
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index b201bf69b..c00834c4c 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4use arrayvec::ArrayVec; 4use arrayvec::ArrayVec;
5use relative_path::RelativePathBuf; 5use relative_path::RelativePathBuf;
6use ra_db::{FileId, SourceRootId, SourceRoot}; 6use ra_db::{FileId, SourceRoot, CrateId};
7use ra_syntax::{ 7use ra_syntax::{
8 SyntaxNode, TreeArc, 8 SyntaxNode, TreeArc,
9 algo::generate, 9 algo::generate,
@@ -126,13 +126,10 @@ struct LinkData {
126} 126}
127 127
128impl ModuleTree { 128impl ModuleTree {
129 pub(crate) fn module_tree_query( 129 pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ModuleTree> {
130 db: &impl HirDatabase,
131 source_root: SourceRootId,
132 ) -> Arc<ModuleTree> {
133 db.check_canceled(); 130 db.check_canceled();
134 let mut res = ModuleTree::default(); 131 let mut res = ModuleTree::default();
135 res.init(db, source_root); 132 res.init_crate(db, crate_id);
136 Arc::new(res) 133 Arc::new(res)
137 } 134 }
138 135
@@ -145,24 +142,21 @@ impl ModuleTree {
145 Some(res) 142 Some(res)
146 } 143 }
147 144
148 fn init(&mut self, db: &impl HirDatabase, source_root: SourceRootId) { 145 fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) {
146 let crate_graph = db.crate_graph();
147 let file_id = crate_graph.crate_root(crate_id);
148 let source_root_id = db.file_source_root(file_id);
149
149 let mut roots = FxHashMap::default(); 150 let mut roots = FxHashMap::default();
150 let mut visited = FxHashSet::default(); 151 let mut visited = FxHashSet::default();
151 152
152 let source_root = db.source_root(source_root); 153 let source_root = db.source_root(source_root_id);
153 for &file_id in source_root.files.values() { 154 let source = SourceItemId {
154 let source = SourceItemId { 155 file_id: file_id.into(),
155 file_id: file_id.into(), 156 item_id: None,
156 item_id: None, 157 };
157 }; 158 let module_id = self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source);
158 if visited.contains(&source) { 159 roots.insert(file_id, module_id);
159 continue; // TODO: use explicit crate_roots here
160 }
161 assert!(!roots.contains_key(&file_id));
162 let module_id =
163 self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source);
164 roots.insert(file_id, module_id);
165 }
166 } 160 }
167 161
168 fn init_subtree( 162 fn init_subtree(
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 1d163edf7..a3bc98958 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -16,19 +16,19 @@
16//! structure itself is modified. 16//! structure itself is modified.
17pub(crate) mod lower; 17pub(crate) mod lower;
18 18
19use crate::nameres::lower::*;
20
21use std::sync::Arc; 19use std::sync::Arc;
22 20
21use ra_db::CrateId;
23use rustc_hash::{FxHashMap, FxHashSet}; 22use rustc_hash::{FxHashMap, FxHashSet};
24use ra_db::SourceRootId;
25 23
26use crate::{ 24use crate::{
27 DefId, DefLoc, DefKind, 25 Module, ModuleDef,
28 Path, PathKind, 26 Path, PathKind,
29 HirDatabase, Crate, 27 HirDatabase, Crate,
30 Name, 28 Name,
31 module_tree::{ModuleId, ModuleTree}, 29 module_tree::{ModuleId, ModuleTree},
30//FIXME: deglobify
31 nameres::lower::*,
32}; 32};
33 33
34/// `ItemMap` is the result of name resolution. It contains, for each 34/// `ItemMap` is the result of name resolution. It contains, for each
@@ -58,7 +58,7 @@ impl ModuleScope {
58#[derive(Debug, Clone, PartialEq, Eq)] 58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct Resolution { 59pub struct Resolution {
60 /// None for unresolved 60 /// None for unresolved
61 pub def_id: PerNs<DefId>, 61 pub def_id: PerNs<ModuleDef>,
62 /// ident by which this is imported into local scope. 62 /// ident by which this is imported into local scope.
63 pub import: Option<ImportId>, 63 pub import: Option<ImportId>,
64} 64}
@@ -152,7 +152,7 @@ impl<T> PerNs<T> {
152pub(crate) struct Resolver<'a, DB> { 152pub(crate) struct Resolver<'a, DB> {
153 db: &'a DB, 153 db: &'a DB,
154 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, 154 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
155 source_root: SourceRootId, 155 krate: CrateId,
156 module_tree: Arc<ModuleTree>, 156 module_tree: Arc<ModuleTree>,
157 processed_imports: FxHashSet<(ModuleId, ImportId)>, 157 processed_imports: FxHashSet<(ModuleId, ImportId)>,
158 result: ItemMap, 158 result: ItemMap,
@@ -165,13 +165,13 @@ where
165 pub(crate) fn new( 165 pub(crate) fn new(
166 db: &'a DB, 166 db: &'a DB,
167 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, 167 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
168 source_root: SourceRootId, 168 krate: CrateId,
169 module_tree: Arc<ModuleTree>,
170 ) -> Resolver<'a, DB> { 169 ) -> Resolver<'a, DB> {
170 let module_tree = db.module_tree(krate);
171 Resolver { 171 Resolver {
172 db, 172 db,
173 input, 173 input,
174 source_root, 174 krate,
175 module_tree, 175 module_tree,
176 processed_imports: FxHashSet::default(), 176 processed_imports: FxHashSet::default(),
177 result: ItemMap::default(), 177 result: ItemMap::default(),
@@ -210,7 +210,7 @@ where
210 let krate = Crate::new(crate_id); 210 let krate = Crate::new(crate_id);
211 for dep in krate.dependencies(self.db) { 211 for dep in krate.dependencies(self.db) {
212 if let Some(module) = dep.krate.root_module(self.db) { 212 if let Some(module) = dep.krate.root_module(self.db) {
213 let def_id = module.def_id; 213 let def_id = module.into();
214 self.add_module_item( 214 self.add_module_item(
215 &mut module_items, 215 &mut module_items,
216 dep.name.clone(), 216 dep.name.clone(),
@@ -244,20 +244,22 @@ where
244 244
245 // Populate modules 245 // Populate modules
246 for (name, module_id) in module_id.children(&self.module_tree) { 246 for (name, module_id) in module_id.children(&self.module_tree) {
247 let def_loc = DefLoc { 247 let module = Module {
248 kind: DefKind::Module,
249 source_root_id: self.source_root,
250 module_id, 248 module_id,
251 source_item_id: module_id.source(&self.module_tree), 249 krate: self.krate,
252 }; 250 };
253 let def_id = def_loc.id(self.db); 251 self.add_module_item(&mut module_items, name, PerNs::types(module.into()));
254 self.add_module_item(&mut module_items, name, PerNs::types(def_id));
255 } 252 }
256 253
257 self.result.per_module.insert(module_id, module_items); 254 self.result.per_module.insert(module_id, module_items);
258 } 255 }
259 256
260 fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs<DefId>) { 257 fn add_module_item(
258 &self,
259 module_items: &mut ModuleScope,
260 name: Name,
261 def_id: PerNs<ModuleDef>,
262 ) {
261 let resolution = Resolution { 263 let resolution = Resolution {
262 def_id, 264 def_id,
263 import: None, 265 import: None,
@@ -329,17 +331,11 @@ where
329 ); 331 );
330 return false; 332 return false;
331 }; 333 };
332 curr = match type_def_id.loc(self.db) { 334 curr = match type_def_id {
333 DefLoc { 335 ModuleDef::Module(module) => {
334 kind: DefKind::Module, 336 if module.krate == self.krate {
335 module_id: target_module_id, 337 module.module_id
336 source_root_id,
337 ..
338 } => {
339 if source_root_id == self.source_root {
340 target_module_id
341 } else { 338 } else {
342 let module = crate::code_model_api::Module::new(type_def_id);
343 let path = Path { 339 let path = Path {
344 segments: import.path.segments[i + 1..].iter().cloned().collect(), 340 segments: import.path.segments[i + 1..].iter().cloned().collect(),
345 kind: PathKind::Crate, 341 kind: PathKind::Crate,
@@ -359,7 +355,7 @@ where
359 "resolved import {:?} ({:?}) cross-source root to {:?}", 355 "resolved import {:?} ({:?}) cross-source root to {:?}",
360 last_segment.name, 356 last_segment.name,
361 import, 357 import,
362 def_id.map(|did| did.loc(self.db)) 358 def_id,
363 ); 359 );
364 return true; 360 return true;
365 } else { 361 } else {
@@ -372,7 +368,7 @@ where
372 log::debug!( 368 log::debug!(
373 "path segment {:?} resolved to non-module {:?}, but is not last", 369 "path segment {:?} resolved to non-module {:?}, but is not last",
374 segment.name, 370 segment.name,
375 type_def_id.loc(self.db) 371 type_def_id,
376 ); 372 );
377 return true; // this resolved to a non-module, so the path won't ever resolve 373 return true; // this resolved to a non-module, so the path won't ever resolve
378 } 374 }
@@ -382,7 +378,7 @@ where
382 "resolved import {:?} ({:?}) within source root to {:?}", 378 "resolved import {:?} ({:?}) within source root to {:?}",
383 segment.name, 379 segment.name,
384 import, 380 import,
385 def_id.map(|did| did.loc(self.db)) 381 def_id,
386 ); 382 );
387 self.update(module_id, |items| { 383 self.update(module_id, |items| {
388 let res = Resolution { 384 let res = Resolution {
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 4eea6ff1d..b4fe99ea7 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -1,17 +1,17 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, 4 AstNode, SourceFile, TreeArc, AstPtr,
5 ast::{self, ModuleItemOwner, NameOwner}, 5 ast::{self, ModuleItemOwner, NameOwner},
6}; 6};
7use ra_db::SourceRootId;
8use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 7use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
9use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
10 9
11use crate::{ 10use crate::{
12 SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, 11 SourceItemId, Path, ModuleSource, HirDatabase, Name,
13 HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc, 12 HirFileId, MacroCallLoc, AsName, PerNs, Function,
14 module_tree::ModuleId 13 ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type,
14 ids::LocationCtx,
15}; 15};
16 16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -32,7 +32,7 @@ pub(super) struct ImportData {
32/// can avoid redoing name resolution. 32/// can avoid redoing name resolution.
33#[derive(Debug, Default, PartialEq, Eq)] 33#[derive(Debug, Default, PartialEq, Eq)]
34pub struct LoweredModule { 34pub struct LoweredModule {
35 pub(crate) declarations: FxHashMap<Name, PerNs<DefId>>, 35 pub(crate) declarations: FxHashMap<Name, PerNs<ModuleDef>>,
36 pub(super) imports: Arena<ImportId, ImportData>, 36 pub(super) imports: Arena<ImportId, ImportData>,
37} 37}
38 38
@@ -59,37 +59,31 @@ impl ImportSourceMap {
59impl LoweredModule { 59impl LoweredModule {
60 pub(crate) fn lower_module_module_query( 60 pub(crate) fn lower_module_module_query(
61 db: &impl HirDatabase, 61 db: &impl HirDatabase,
62 source_root_id: SourceRootId, 62 module: Module,
63 module_id: ModuleId,
64 ) -> Arc<LoweredModule> { 63 ) -> Arc<LoweredModule> {
65 db.lower_module(source_root_id, module_id).0 64 db.lower_module(module).0
66 } 65 }
67 66
68 pub(crate) fn lower_module_source_map_query( 67 pub(crate) fn lower_module_source_map_query(
69 db: &impl HirDatabase, 68 db: &impl HirDatabase,
70 source_root_id: SourceRootId, 69 module: Module,
71 module_id: ModuleId,
72 ) -> Arc<ImportSourceMap> { 70 ) -> Arc<ImportSourceMap> {
73 db.lower_module(source_root_id, module_id).1 71 db.lower_module(module).1
74 } 72 }
75 73
76 pub(crate) fn lower_module_query( 74 pub(crate) fn lower_module_query(
77 db: &impl HirDatabase, 75 db: &impl HirDatabase,
78 source_root_id: SourceRootId, 76 module: Module,
79 module_id: ModuleId,
80 ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { 77 ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) {
81 let module_tree = db.module_tree(source_root_id); 78 let (file_id, source) = module.definition_source(db);
82 let source = module_id.source(&module_tree); 79 let file_id: HirFileId = file_id.into();
83 let file_id = source.file_id;
84 let source = ModuleSource::from_source_item_id(db, source);
85 let mut source_map = ImportSourceMap::default(); 80 let mut source_map = ImportSourceMap::default();
86 let mut res = LoweredModule::default(); 81 let mut res = LoweredModule::default();
87 match source { 82 match source {
88 ModuleSource::SourceFile(it) => res.fill( 83 ModuleSource::SourceFile(it) => res.fill(
89 &mut source_map, 84 &mut source_map,
90 db, 85 db,
91 source_root_id, 86 module,
92 module_id,
93 file_id, 87 file_id,
94 &mut it.items_with_macros(), 88 &mut it.items_with_macros(),
95 ), 89 ),
@@ -98,8 +92,7 @@ impl LoweredModule {
98 res.fill( 92 res.fill(
99 &mut source_map, 93 &mut source_map,
100 db, 94 db,
101 source_root_id, 95 module,
102 module_id,
103 file_id, 96 file_id,
104 &mut item_list.items_with_macros(), 97 &mut item_list.items_with_macros(),
105 ) 98 )
@@ -113,8 +106,7 @@ impl LoweredModule {
113 &mut self, 106 &mut self,
114 source_map: &mut ImportSourceMap, 107 source_map: &mut ImportSourceMap,
115 db: &impl HirDatabase, 108 db: &impl HirDatabase,
116 source_root_id: SourceRootId, 109 module: Module,
117 module_id: ModuleId,
118 file_id: HirFileId, 110 file_id: HirFileId,
119 items: &mut Iterator<Item = ast::ItemOrMacro>, 111 items: &mut Iterator<Item = ast::ItemOrMacro>,
120 ) { 112 ) {
@@ -123,21 +115,12 @@ impl LoweredModule {
123 for item in items { 115 for item in items {
124 match item { 116 match item {
125 ast::ItemOrMacro::Item(it) => { 117 ast::ItemOrMacro::Item(it) => {
126 self.add_def_id( 118 self.add_def_id(source_map, db, module, file_id, it);
127 source_map,
128 db,
129 source_root_id,
130 module_id,
131 file_id,
132 &file_items,
133 it,
134 );
135 } 119 }
136 ast::ItemOrMacro::Macro(macro_call) => { 120 ast::ItemOrMacro::Macro(macro_call) => {
137 let item_id = file_items.id_of_unchecked(macro_call.syntax()); 121 let item_id = file_items.id_of_unchecked(macro_call.syntax());
138 let loc = MacroCallLoc { 122 let loc = MacroCallLoc {
139 source_root_id, 123 module,
140 module_id,
141 source_item_id: SourceItemId { 124 source_item_id: SourceItemId {
142 file_id, 125 file_id,
143 item_id: Some(item_id), 126 item_id: Some(item_id),
@@ -145,18 +128,9 @@ impl LoweredModule {
145 }; 128 };
146 let id = loc.id(db); 129 let id = loc.id(db);
147 let file_id = HirFileId::from(id); 130 let file_id = HirFileId::from(id);
148 let file_items = db.file_items(file_id);
149 //FIXME: expand recursively 131 //FIXME: expand recursively
150 for item in db.hir_source_file(file_id).items() { 132 for item in db.hir_source_file(file_id).items() {
151 self.add_def_id( 133 self.add_def_id(source_map, db, module, file_id, item);
152 source_map,
153 db,
154 source_root_id,
155 module_id,
156 file_id,
157 &file_items,
158 item,
159 );
160 } 134 }
161 } 135 }
162 } 136 }
@@ -167,41 +141,74 @@ impl LoweredModule {
167 &mut self, 141 &mut self,
168 source_map: &mut ImportSourceMap, 142 source_map: &mut ImportSourceMap,
169 db: &impl HirDatabase, 143 db: &impl HirDatabase,
170 source_root_id: SourceRootId, 144 module: Module,
171 module_id: ModuleId,
172 file_id: HirFileId, 145 file_id: HirFileId,
173 file_items: &SourceFileItems,
174 item: &ast::ModuleItem, 146 item: &ast::ModuleItem,
175 ) { 147 ) {
176 let name = match item.kind() { 148 let ctx = LocationCtx::new(db, module, file_id);
177 ast::ModuleItemKind::StructDef(it) => it.name(), 149 match item.kind() {
178 ast::ModuleItemKind::EnumDef(it) => it.name(), 150 ast::ModuleItemKind::StructDef(it) => {
179 ast::ModuleItemKind::FnDef(it) => it.name(), 151 if let Some(name) = it.name() {
180 ast::ModuleItemKind::TraitDef(it) => it.name(), 152 let s = Struct { id: ctx.to_def(it) };
181 ast::ModuleItemKind::TypeDef(it) => it.name(), 153 let s: ModuleDef = s.into();
154 self.declarations.insert(name.as_name(), PerNs::both(s, s));
155 }
156 }
157 ast::ModuleItemKind::EnumDef(it) => {
158 if let Some(name) = it.name() {
159 let e = Enum { id: ctx.to_def(it) };
160 let e: ModuleDef = e.into();
161 self.declarations.insert(name.as_name(), PerNs::types(e));
162 }
163 }
164 ast::ModuleItemKind::FnDef(it) => {
165 if let Some(name) = it.name() {
166 let func = Function { id: ctx.to_def(it) };
167 self.declarations
168 .insert(name.as_name(), PerNs::values(func.into()));
169 }
170 }
171 ast::ModuleItemKind::TraitDef(it) => {
172 if let Some(name) = it.name() {
173 let t = Trait { id: ctx.to_def(it) };
174 self.declarations
175 .insert(name.as_name(), PerNs::types(t.into()));
176 }
177 }
178 ast::ModuleItemKind::TypeDef(it) => {
179 if let Some(name) = it.name() {
180 let t = Type { id: ctx.to_def(it) };
181 self.declarations
182 .insert(name.as_name(), PerNs::types(t.into()));
183 }
184 }
182 ast::ModuleItemKind::ImplBlock(_) => { 185 ast::ModuleItemKind::ImplBlock(_) => {
183 // impls don't define items 186 // impls don't define items
184 return;
185 } 187 }
186 ast::ModuleItemKind::UseItem(it) => { 188 ast::ModuleItemKind::UseItem(it) => {
187 self.add_use_item(source_map, it); 189 self.add_use_item(source_map, it);
188 return;
189 } 190 }
190 ast::ModuleItemKind::ExternCrateItem(_) => { 191 ast::ModuleItemKind::ExternCrateItem(_) => {
191 // TODO 192 // TODO
192 return;
193 } 193 }
194 ast::ModuleItemKind::ConstDef(it) => it.name(), 194 ast::ModuleItemKind::ConstDef(it) => {
195 ast::ModuleItemKind::StaticDef(it) => it.name(), 195 if let Some(name) = it.name() {
196 let c = Const { id: ctx.to_def(it) };
197 self.declarations
198 .insert(name.as_name(), PerNs::values(c.into()));
199 }
200 }
201 ast::ModuleItemKind::StaticDef(it) => {
202 if let Some(name) = it.name() {
203 let s = Static { id: ctx.to_def(it) };
204 self.declarations
205 .insert(name.as_name(), PerNs::values(s.into()));
206 }
207 }
196 ast::ModuleItemKind::Module(_) => { 208 ast::ModuleItemKind::Module(_) => {
197 // modules are handled separately direclty by nameres 209 // modules are handled separately direclty by nameres
198 return;
199 } 210 }
200 }; 211 };
201 if let Some(name) = name {
202 let def_id = assign_def_id(db, source_root_id, module_id, file_id, file_items, item);
203 self.declarations.insert(name.as_name(), def_id);
204 }
205 } 212 }
206 213
207 fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { 214 fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) {
@@ -216,46 +223,3 @@ impl LoweredModule {
216 }) 223 })
217 } 224 }
218} 225}
219
220fn assign_def_id(
221 db: &impl HirDatabase,
222 source_root_id: SourceRootId,
223 module_id: ModuleId,
224 file_id: HirFileId,
225 file_items: &SourceFileItems,
226 item: &ast::ModuleItem,
227) -> PerNs<DefId> {
228 // depending on the item kind, the location can define something in
229 // the values namespace, the types namespace, or both
230 let kind = DefKind::for_syntax_kind(item.syntax().kind());
231 let def_id = kind.map(|k| {
232 let item_id = file_items.id_of_unchecked(item.syntax());
233 let def_loc = DefLoc {
234 kind: k,
235 source_root_id,
236 module_id,
237 source_item_id: SourceItemId {
238 file_id,
239 item_id: Some(item_id),
240 },
241 };
242 def_loc.id(db)
243 });
244 def_id
245}
246
247impl DefKind {
248 fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
249 match kind {
250 SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
251 SyntaxKind::MODULE => PerNs::types(DefKind::Module),
252 SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
253 SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
254 SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),
255 SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type),
256 SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const),
257 SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static),
258 _ => PerNs::none(),
259 }
260 }
261}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index e92007453..9322bf08c 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -1,6 +1,6 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::{FilesDatabase, CrateGraph, SourceRootId, salsa::Database}; 3use ra_db::{CrateGraph, SourceRootId, salsa::Database};
4use relative_path::RelativePath; 4use relative_path::RelativePath;
5use test_utils::{assert_eq_text, covers}; 5use test_utils::{assert_eq_text, covers};
6 6
@@ -13,10 +13,10 @@ use crate::{
13 13
14fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { 14fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
15 let (db, pos) = MockDatabase::with_position(fixture); 15 let (db, pos) = MockDatabase::with_position(fixture);
16 let source_root = db.file_source_root(pos.file_id);
17 let module = crate::source_binder::module_from_position(&db, pos).unwrap(); 16 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
18 let module_id = module.def_id.loc(&db).module_id; 17 let krate = module.krate(&db).unwrap();
19 (db.item_map(source_root), module_id) 18 let module_id = module.module_id;
19 (db.item_map(krate.crate_id), module_id)
20} 20}
21 21
22fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { 22fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
@@ -238,14 +238,13 @@ fn item_map_across_crates() {
238 238
239 db.set_crate_graph(crate_graph); 239 db.set_crate_graph(crate_graph);
240 240
241 let source_root = db.file_source_root(main_id);
242 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 241 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
243 let module_id = module.def_id.loc(&db).module_id; 242 let krate = module.krate(&db).unwrap();
244 let item_map = db.item_map(source_root); 243 let item_map = db.item_map(krate.crate_id);
245 244
246 check_module_item_map( 245 check_module_item_map(
247 &item_map, 246 &item_map,
248 module_id, 247 module.module_id,
249 " 248 "
250 Baz: t v 249 Baz: t v
251 test_crate: t 250 test_crate: t
@@ -292,12 +291,12 @@ fn import_across_source_roots() {
292 db.set_crate_graph(crate_graph); 291 db.set_crate_graph(crate_graph);
293 292
294 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 293 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
295 let module_id = module.def_id.loc(&db).module_id; 294 let krate = module.krate(&db).unwrap();
296 let item_map = db.item_map(source_root); 295 let item_map = db.item_map(krate.crate_id);
297 296
298 check_module_item_map( 297 check_module_item_map(
299 &item_map, 298 &item_map,
300 module_id, 299 module.module_id,
301 " 300 "
302 C: t v 301 C: t v
303 test_crate: t 302 test_crate: t
@@ -333,14 +332,13 @@ fn reexport_across_crates() {
333 332
334 db.set_crate_graph(crate_graph); 333 db.set_crate_graph(crate_graph);
335 334
336 let source_root = db.file_source_root(main_id);
337 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 335 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
338 let module_id = module.def_id.loc(&db).module_id; 336 let krate = module.krate(&db).unwrap();
339 let item_map = db.item_map(source_root); 337 let item_map = db.item_map(krate.crate_id);
340 338
341 check_module_item_map( 339 check_module_item_map(
342 &item_map, 340 &item_map,
343 module_id, 341 module.module_id,
344 " 342 "
345 Baz: t v 343 Baz: t v
346 test_crate: t 344 test_crate: t
@@ -350,10 +348,11 @@ fn reexport_across_crates() {
350 348
351fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { 349fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
352 let (mut db, pos) = MockDatabase::with_position(initial); 350 let (mut db, pos) = MockDatabase::with_position(initial);
353 let source_root = db.file_source_root(pos.file_id); 351 let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
352 let krate = module.krate(&db).unwrap();
354 { 353 {
355 let events = db.log_executed(|| { 354 let events = db.log_executed(|| {
356 db.item_map(source_root); 355 db.item_map(krate.crate_id);
357 }); 356 });
358 assert!(format!("{:?}", events).contains("item_map")) 357 assert!(format!("{:?}", events).contains("item_map"))
359 } 358 }
@@ -362,7 +361,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
362 361
363 { 362 {
364 let events = db.log_executed(|| { 363 let events = db.log_executed(|| {
365 db.item_map(source_root); 364 db.item_map(krate.crate_id);
366 }); 365 });
367 assert!( 366 assert!(
368 !format!("{:?}", events).contains("item_map"), 367 !format!("{:?}", events).contains("item_map"),
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index 074153862..cf8c7e435 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -7,17 +7,17 @@ use rustc_hash::FxHashMap;
7use ra_syntax::{ 7use ra_syntax::{
8 AstNode, SyntaxNode, TreeArc, 8 AstNode, SyntaxNode, TreeArc,
9}; 9};
10use ra_db::SourceRootId; 10use ra_db::{CrateId};
11 11
12use crate::{ 12use crate::{
13 SourceFileItems, SourceItemId, DefId, HirFileId, 13 SourceFileItems, SourceItemId, HirFileId,
14 FnScopes, 14 Function, FnScopes, Module,
15 db::HirDatabase, 15 db::HirDatabase,
16 nameres::{ItemMap, Resolver}, 16 nameres::{ItemMap, Resolver},
17}; 17};
18 18
19pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { 19pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> {
20 let body = db.body_hir(def_id); 20 let body = db.body_hir(func);
21 let res = FnScopes::new(body); 21 let res = FnScopes::new(body);
22 Arc::new(res) 22 Arc::new(res)
23} 23}
@@ -41,15 +41,23 @@ pub(super) fn file_item(
41 } 41 }
42} 42}
43 43
44pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> { 44pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> {
45 let start = Instant::now(); 45 let start = Instant::now();
46 let module_tree = db.module_tree(source_root); 46 let module_tree = db.module_tree(crate_id);
47 let input = module_tree 47 let input = module_tree
48 .modules() 48 .modules()
49 .map(|id| (id, db.lower_module_module(source_root, id))) 49 .map(|module_id| {
50 (
51 module_id,
52 db.lower_module_module(Module {
53 krate: crate_id,
54 module_id,
55 }),
56 )
57 })
50 .collect::<FxHashMap<_, _>>(); 58 .collect::<FxHashMap<_, _>>();
51 59
52 let resolver = Resolver::new(db, &input, source_root, module_tree); 60 let resolver = Resolver::new(db, &input, crate_id);
53 let res = resolver.resolve(); 61 let res = resolver.resolve();
54 let elapsed = start.elapsed(); 62 let elapsed = start.elapsed();
55 log::info!("item_map: {:?}", elapsed); 63 log::info!("item_map: {:?}", elapsed);
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index bde0be37b..dbe040805 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,8 +13,9 @@ use ra_syntax::{
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, SourceItemId, 16 HirDatabase, Function, SourceItemId, ModuleDef,
17 DefKind, DefLoc, AsName, Module, 17 AsName, Module,
18 ids::LocationCtx,
18}; 19};
19 20
20/// Locates the module by `FileId`. Picks topmost module in the file. 21/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -84,9 +85,13 @@ pub fn module_from_child_node(
84 85
85fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> { 86fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> {
86 let source_root_id = db.file_source_root(source.file_id.as_original_file()); 87 let source_root_id = db.file_source_root(source.file_id.as_original_file());
87 let module_tree = db.module_tree(source_root_id); 88 db.source_root_crates(source_root_id)
88 let module_id = module_tree.find_module_by_source(source)?; 89 .iter()
89 Some(Module::from_module_id(db, source_root_id, module_id)) 90 .find_map(|&krate| {
91 let module_tree = db.module_tree(krate);
92 let module_id = module_tree.find_module_by_source(source)?;
93 Some(Module { krate, module_id })
94 })
90} 95}
91 96
92pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { 97pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
@@ -101,30 +106,21 @@ pub fn function_from_source(
101 fn_def: &ast::FnDef, 106 fn_def: &ast::FnDef,
102) -> Option<Function> { 107) -> Option<Function> {
103 let module = module_from_child_node(db, file_id, fn_def.syntax())?; 108 let module = module_from_child_node(db, file_id, fn_def.syntax())?;
104 let res = function_from_module(db, &module, fn_def); 109 let res = function_from_module(db, module, fn_def);
105 Some(res) 110 Some(res)
106} 111}
107 112
108pub fn function_from_module( 113pub fn function_from_module(
109 db: &impl HirDatabase, 114 db: &impl HirDatabase,
110 module: &Module, 115 module: Module,
111 fn_def: &ast::FnDef, 116 fn_def: &ast::FnDef,
112) -> Function { 117) -> Function {
113 let loc = module.def_id.loc(db); 118 let (file_id, _) = module.definition_source(db);
114 let file_id = loc.source_item_id.file_id; 119 let file_id = file_id.into();
115 let file_items = db.file_items(file_id); 120 let ctx = LocationCtx::new(db, module, file_id);
116 let item_id = file_items.id_of(file_id, fn_def.syntax()); 121 Function {
117 let source_item_id = SourceItemId { 122 id: ctx.to_def(fn_def),
118 file_id, 123 }
119 item_id: Some(item_id),
120 };
121 let def_loc = DefLoc {
122 kind: DefKind::Function,
123 source_root_id: loc.source_root_id,
124 module_id: loc.module_id,
125 source_item_id,
126 };
127 Function::new(def_loc.id(db))
128} 124}
129 125
130pub fn function_from_child_node( 126pub fn function_from_child_node(
@@ -141,15 +137,18 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te
141 Some(it) => it, 137 Some(it) => it,
142 None => return Vec::new(), 138 None => return Vec::new(),
143 }; 139 };
144 let loc = module.def_id.loc(db); 140 let items = db.lower_module_module(module);
145 let items = db.lower_module_module(loc.source_root_id, loc.module_id);
146 let mut res = Vec::new(); 141 let mut res = Vec::new();
147 142
148 for macro_call_id in items 143 for macro_call_id in items
149 .declarations 144 .declarations
150 .iter() 145 .iter()
151 .filter_map(|(_, it)| it.take_types()) 146 .filter_map(|(_, it)| it.clone().take_types())
152 .filter_map(|it| it.loc(db).source_item_id.file_id.as_macro_call_id()) 147 .filter_map(|it| match it {
148 ModuleDef::Trait(it) => Some(it),
149 _ => None,
150 })
151 .filter_map(|it| it.source(db).0.as_macro_call_id())
153 { 152 {
154 if let Some(exp) = db.expand_macro_invocation(macro_call_id) { 153 if let Some(exp) = db.expand_macro_invocation(macro_call_id) {
155 let loc = macro_call_id.loc(db); 154 let loc = macro_call_id.loc(db);
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index e690ae158..c7f77e7a3 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -24,15 +24,14 @@ use std::ops::Index;
24use std::sync::Arc; 24use std::sync::Arc;
25use std::{fmt, mem}; 25use std::{fmt, mem};
26 26
27use log;
28use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; 27use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError};
29use ra_arena::map::ArenaMap; 28use ra_arena::map::ArenaMap;
30use join_to_string::join; 29use join_to_string::join;
31use rustc_hash::FxHashMap; 30use rustc_hash::FxHashMap;
32 31
33use crate::{ 32use crate::{
34 Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, 33 Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock,
35 FnSignature, FnScopes, 34 FnSignature, FnScopes, ModuleDef, AdtDef,
36 db::HirDatabase, 35 db::HirDatabase,
37 type_ref::{TypeRef, Mutability}, 36 type_ref::{TypeRef, Mutability},
38 name::KnownName, 37 name::KnownName,
@@ -184,7 +183,7 @@ pub enum Ty {
184 /// Structures, enumerations and unions. 183 /// Structures, enumerations and unions.
185 Adt { 184 Adt {
186 /// The DefId of the struct/enum. 185 /// The DefId of the struct/enum.
187 def_id: DefId, 186 def_id: AdtDef,
188 /// The name, for displaying. 187 /// The name, for displaying.
189 name: Name, 188 name: Name,
190 /// Substitutions for the generic parameters of the type. 189 /// Substitutions for the generic parameters of the type.
@@ -381,12 +380,16 @@ impl Ty {
381 } 380 }
382 381
383 // Resolve in module (in type namespace) 382 // Resolve in module (in type namespace)
384 let resolved = match module.resolve_path(db, path).take_types() { 383 let typable: TypableDef = match module
385 Some(r) => r, 384 .resolve_path(db, path)
385 .take_types()
386 .and_then(|it| it.into())
387 {
386 None => return Ty::Unknown, 388 None => return Ty::Unknown,
389 Some(it) => it,
387 }; 390 };
388 let ty = db.type_for_def(resolved); 391 let ty = db.type_for_def(typable);
389 let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved); 392 let substs = Ty::substs_from_path(db, module, impl_block, generics, path, typable);
390 ty.apply_substs(substs) 393 ty.apply_substs(substs)
391 } 394 }
392 395
@@ -399,20 +402,18 @@ impl Ty {
399 impl_block: Option<&ImplBlock>, 402 impl_block: Option<&ImplBlock>,
400 outer_generics: &GenericParams, 403 outer_generics: &GenericParams,
401 path: &Path, 404 path: &Path,
402 resolved: DefId, 405 resolved: TypableDef,
403 ) -> Substs { 406 ) -> Substs {
404 let mut substs = Vec::new(); 407 let mut substs = Vec::new();
405 let def = resolved.resolve(db);
406 let last = path 408 let last = path
407 .segments 409 .segments
408 .last() 410 .last()
409 .expect("path should have at least one segment"); 411 .expect("path should have at least one segment");
410 let (def_generics, segment) = match def { 412 let (def_generics, segment) = match resolved {
411 Def::Struct(s) => (s.generic_params(db), last), 413 TypableDef::Function(func) => (func.generic_params(db), last),
412 Def::Enum(e) => (e.generic_params(db), last), 414 TypableDef::Struct(s) => (s.generic_params(db), last),
413 Def::Function(f) => (f.generic_params(db), last), 415 TypableDef::Enum(e) => (e.generic_params(db), last),
414 Def::Trait(t) => (t.generic_params(db), last), 416 TypableDef::EnumVariant(var) => {
415 Def::EnumVariant(ev) => {
416 // the generic args for an enum variant may be either specified 417 // the generic args for an enum variant may be either specified
417 // on the segment referring to the enum, or on the segment 418 // on the segment referring to the enum, or on the segment
418 // referring to the variant. So `Option::<T>::None` and 419 // referring to the variant. So `Option::<T>::None` and
@@ -426,9 +427,8 @@ impl Ty {
426 // Option::None::<T> 427 // Option::None::<T>
427 last 428 last
428 }; 429 };
429 (ev.parent_enum(db).generic_params(db), segment) 430 (var.parent_enum(db).generic_params(db), segment)
430 } 431 }
431 _ => return Substs::empty(),
432 }; 432 };
433 // substs_from_path 433 // substs_from_path
434 if let Some(generic_args) = &segment.args_and_bindings { 434 if let Some(generic_args) = &segment.args_and_bindings {
@@ -639,7 +639,7 @@ fn make_substs(generics: &GenericParams) -> Substs {
639fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 639fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
640 let generics = s.generic_params(db); 640 let generics = s.generic_params(db);
641 Ty::Adt { 641 Ty::Adt {
642 def_id: s.def_id(), 642 def_id: s.into(),
643 name: s.name(db).unwrap_or_else(Name::missing), 643 name: s.name(db).unwrap_or_else(Name::missing),
644 substs: make_substs(&generics), 644 substs: make_substs(&generics),
645 } 645 }
@@ -648,7 +648,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
648pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 648pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
649 let generics = s.generic_params(db); 649 let generics = s.generic_params(db);
650 Ty::Adt { 650 Ty::Adt {
651 def_id: s.def_id(), 651 def_id: s.into(),
652 name: s.name(db).unwrap_or_else(Name::missing), 652 name: s.name(db).unwrap_or_else(Name::missing),
653 substs: make_substs(&generics), 653 substs: make_substs(&generics),
654 } 654 }
@@ -660,66 +660,74 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T
660 type_for_enum(db, enum_parent) 660 type_for_enum(db, enum_parent)
661} 661}
662 662
663pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { 663#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
664 let def = def_id.resolve(db); 664pub enum TypableDef {
665 Function(Function),
666 Struct(Struct),
667 Enum(Enum),
668 EnumVariant(EnumVariant),
669}
670impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant);
671
672impl From<ModuleDef> for Option<TypableDef> {
673 fn from(def: ModuleDef) -> Option<TypableDef> {
674 let res = match def {
675 ModuleDef::Function(f) => f.into(),
676 ModuleDef::Struct(s) => s.into(),
677 ModuleDef::Enum(e) => e.into(),
678 ModuleDef::EnumVariant(v) => v.into(),
679 ModuleDef::Const(_)
680 | ModuleDef::Static(_)
681 | ModuleDef::Module(_)
682 | ModuleDef::Trait(_)
683 | ModuleDef::Type(_) => return None,
684 };
685 Some(res)
686 }
687}
688
689pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
665 match def { 690 match def {
666 Def::Module(..) => { 691 TypableDef::Function(f) => type_for_fn(db, f),
667 log::debug!("trying to get type for module {:?}", def_id); 692 TypableDef::Struct(s) => type_for_struct(db, s),
668 Ty::Unknown 693 TypableDef::Enum(e) => type_for_enum(db, e),
669 } 694 TypableDef::EnumVariant(v) => type_for_enum_variant(db, v),
670 Def::Function(f) => type_for_fn(db, f),
671 Def::Struct(s) => type_for_struct(db, s),
672 Def::Enum(e) => type_for_enum(db, e),
673 Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
674 _ => {
675 log::debug!(
676 "trying to get type for item of unknown type {:?} {:?}",
677 def_id,
678 def
679 );
680 Ty::Unknown
681 }
682 } 695 }
683} 696}
684 697
685pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { 698#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
686 let def = def_id.resolve(db); 699pub enum VariantDef {
687 let (variant_data, generics) = match def { 700 Struct(Struct),
688 Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), 701 EnumVariant(EnumVariant),
689 Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), 702}
690 // TODO: unions 703impl_froms!(VariantDef: Struct, EnumVariant);
691 Def::Enum(_) => { 704
692 // this can happen in (invalid) code, but enums don't have fields themselves 705pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> {
693 return None; 706 let (variant_data, generics, module) = match def {
694 } 707 VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)),
695 _ => panic!( 708 VariantDef::EnumVariant(var) => (
696 "trying to get type for field {:?} in non-struct/variant {:?}", 709 var.variant_data(db),
697 field, def_id 710 var.parent_enum(db).generic_params(db),
711 var.module(db),
698 ), 712 ),
699 }; 713 };
700 let module = def_id.module(db); 714 // We can't have an impl block ere, right?
701 let impl_block = def_id.impl_block(db); 715 // let impl_block = def_id.impl_block(db);
702 let type_ref = variant_data.get_field_type_ref(&field)?; 716 let type_ref = variant_data.get_field_type_ref(&field)?;
703 Some(Ty::from_hir( 717 Some(Ty::from_hir(db, &module, None, &generics, &type_ref))
704 db,
705 &module,
706 impl_block.as_ref(),
707 &generics,
708 &type_ref,
709 ))
710} 718}
711 719
712/// The result of type inference: A mapping from expressions and patterns to types. 720/// The result of type inference: A mapping from expressions and patterns to types.
713#[derive(Clone, PartialEq, Eq, Debug)] 721#[derive(Clone, PartialEq, Eq, Debug)]
714pub struct InferenceResult { 722pub struct InferenceResult {
715 /// For each method call expr, record the function it resolved to. 723 /// For each method call expr, record the function it resolved to.
716 method_resolutions: FxHashMap<ExprId, DefId>, 724 method_resolutions: FxHashMap<ExprId, Function>,
717 type_of_expr: ArenaMap<ExprId, Ty>, 725 type_of_expr: ArenaMap<ExprId, Ty>,
718 type_of_pat: ArenaMap<PatId, Ty>, 726 type_of_pat: ArenaMap<PatId, Ty>,
719} 727}
720 728
721impl InferenceResult { 729impl InferenceResult {
722 pub fn method_resolution(&self, expr: ExprId) -> Option<DefId> { 730 pub fn method_resolution(&self, expr: ExprId) -> Option<Function> {
723 self.method_resolutions.get(&expr).map(|it| *it) 731 self.method_resolutions.get(&expr).map(|it| *it)
724 } 732 }
725} 733}
@@ -749,7 +757,7 @@ struct InferenceContext<'a, D: HirDatabase> {
749 module: Module, 757 module: Module,
750 impl_block: Option<ImplBlock>, 758 impl_block: Option<ImplBlock>,
751 var_unification_table: InPlaceUnificationTable<TypeVarId>, 759 var_unification_table: InPlaceUnificationTable<TypeVarId>,
752 method_resolutions: FxHashMap<ExprId, DefId>, 760 method_resolutions: FxHashMap<ExprId, Function>,
753 type_of_expr: ArenaMap<ExprId, Ty>, 761 type_of_expr: ArenaMap<ExprId, Ty>,
754 type_of_pat: ArenaMap<PatId, Ty>, 762 type_of_pat: ArenaMap<PatId, Ty>,
755 /// The return type of the function being inferred. 763 /// The return type of the function being inferred.
@@ -875,8 +883,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
875 self.type_of_expr.insert(expr, ty); 883 self.type_of_expr.insert(expr, ty);
876 } 884 }
877 885
878 fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) { 886 fn write_method_resolution(&mut self, expr: ExprId, func: Function) {
879 self.method_resolutions.insert(expr, def_id); 887 self.method_resolutions.insert(expr, func);
880 } 888 }
881 889
882 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { 890 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
@@ -1063,20 +1071,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1063 }; 1071 };
1064 1072
1065 // resolve in module 1073 // resolve in module
1066 let resolved = self.module.resolve_path(self.db, &path).take_values()?; 1074 let typable: Option<TypableDef> = self
1067 let ty = self.db.type_for_def(resolved); 1075 .module
1076 .resolve_path(self.db, &path)
1077 .take_values()?
1078 .into();
1079 let typable = typable?;
1080 let ty = self.db.type_for_def(typable);
1068 let ty = self.insert_type_vars(ty); 1081 let ty = self.insert_type_vars(ty);
1069 Some(ty) 1082 Some(ty)
1070 } 1083 }
1071 1084
1072 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { 1085 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
1073 let path = match path { 1086 let path = match path {
1074 Some(path) => path, 1087 Some(path) => path,
1075 None => return (Ty::Unknown, None), 1088 None => return (Ty::Unknown, None),
1076 }; 1089 };
1077 let def_id = match self.module.resolve_path(self.db, &path).take_types() { 1090 let typable: Option<TypableDef> = self
1078 Some(def_id) => def_id, 1091 .module
1079 _ => return (Ty::Unknown, None), 1092 .resolve_path(self.db, &path)
1093 .take_types()
1094 .and_then(|it| it.into());
1095 let def = match typable {
1096 None => return (Ty::Unknown, None),
1097 Some(it) => it,
1080 }; 1098 };
1081 // TODO remove the duplication between here and `Ty::from_path`? 1099 // TODO remove the duplication between here and `Ty::from_path`?
1082 // TODO provide generics of function 1100 // TODO provide generics of function
@@ -1087,38 +1105,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1087 self.impl_block.as_ref(), 1105 self.impl_block.as_ref(),
1088 &generics, 1106 &generics,
1089 path, 1107 path,
1090 def_id, 1108 def,
1091 ); 1109 );
1092 match def_id.resolve(self.db) { 1110 match def {
1093 Def::Struct(s) => { 1111 TypableDef::Struct(s) => {
1094 let ty = type_for_struct(self.db, s); 1112 let ty = type_for_struct(self.db, s);
1095 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1113 let ty = self.insert_type_vars(ty.apply_substs(substs));
1096 (ty, Some(def_id)) 1114 (ty, Some(s.into()))
1097 } 1115 }
1098 Def::EnumVariant(ev) => { 1116 TypableDef::EnumVariant(var) => {
1099 let ty = type_for_enum_variant(self.db, ev); 1117 let ty = type_for_enum_variant(self.db, var);
1100 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1118 let ty = self.insert_type_vars(ty.apply_substs(substs));
1101 (ty, Some(def_id)) 1119 (ty, Some(var.into()))
1102 } 1120 }
1103 _ => (Ty::Unknown, None), 1121 TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None),
1104 } 1122 }
1105 } 1123 }
1106 1124
1107 fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { 1125 fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
1108 let (ty, def_id) = self.resolve_variant(path); 1126 let (ty, def) = self.resolve_variant(path);
1109 let def_id = def_id?; 1127 match def? {
1110 let def = def_id.resolve(self.db); 1128 VariantDef::Struct(s) => {
1111
1112 match def {
1113 Def::Struct(s) => {
1114 let fields = s.fields(self.db); 1129 let fields = s.fields(self.db);
1115 Some((ty, fields)) 1130 Some((ty, fields))
1116 } 1131 }
1117 Def::EnumVariant(ev) => { 1132 VariantDef::EnumVariant(var) => {
1118 let fields = ev.fields(self.db); 1133 let fields = var.fields(self.db);
1119 Some((ty, fields)) 1134 Some((ty, fields))
1120 } 1135 }
1121 _ => None,
1122 } 1136 }
1123 } 1137 }
1124 1138
@@ -1216,6 +1230,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1216 .module 1230 .module
1217 .resolve_path(self.db, &path) 1231 .resolve_path(self.db, &path)
1218 .take_values() 1232 .take_values()
1233 .and_then(|module_def| module_def.into())
1219 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), 1234 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)),
1220 Pat::Bind { 1235 Pat::Bind {
1221 mode, 1236 mode,
@@ -1336,9 +1351,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1336 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 1351 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
1337 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 1352 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
1338 let method_ty = match resolved { 1353 let method_ty = match resolved {
1339 Some(def_id) => { 1354 Some(func) => {
1340 self.write_method_resolution(expr, def_id); 1355 self.write_method_resolution(expr, func);
1341 self.db.type_for_def(def_id) 1356 self.db.type_for_def(func.into())
1342 } 1357 }
1343 None => Ty::Unknown, 1358 None => Ty::Unknown,
1344 }; 1359 };
@@ -1407,7 +1422,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1407 for field in fields { 1422 for field in fields {
1408 let field_ty = if let Some(def_id) = def_id { 1423 let field_ty = if let Some(def_id) = def_id {
1409 self.db 1424 self.db
1410 .type_for_field(def_id, field.name.clone()) 1425 .type_for_field(def_id.into(), field.name.clone())
1411 .unwrap_or(Ty::Unknown) 1426 .unwrap_or(Ty::Unknown)
1412 .subst(&substs) 1427 .subst(&substs)
1413 } else { 1428 } else {
@@ -1431,10 +1446,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1431 i.and_then(|i| fields.get(i).cloned()) 1446 i.and_then(|i| fields.get(i).cloned())
1432 } 1447 }
1433 Ty::Adt { 1448 Ty::Adt {
1434 def_id, ref substs, .. 1449 def_id: AdtDef::Struct(s),
1450 ref substs,
1451 ..
1435 } => self 1452 } => self
1436 .db 1453 .db
1437 .type_for_field(def_id, name.clone()) 1454 .type_for_field(s.into(), name.clone())
1438 .map(|ty| ty.subst(substs)), 1455 .map(|ty| ty.subst(substs)),
1439 _ => None, 1456 _ => None,
1440 }) 1457 })
@@ -1607,16 +1624,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1607 } 1624 }
1608} 1625}
1609 1626
1610pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> { 1627pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
1611 db.check_canceled(); 1628 db.check_canceled();
1612 let function = Function::new(def_id); // TODO: consts also need inference 1629 let body = func.body(db);
1613 let body = function.body(db); 1630 let scopes = db.fn_scopes(func);
1614 let scopes = db.fn_scopes(def_id); 1631 let module = func.module(db);
1615 let module = function.module(db); 1632 let impl_block = func.impl_block(db);
1616 let impl_block = function.impl_block(db);
1617 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1633 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
1618 1634
1619 let signature = function.signature(db); 1635 let signature = func.signature(db);
1620 ctx.collect_fn_signature(&signature); 1636 ctx.collect_fn_signature(&signature);
1621 1637
1622 ctx.infer_body(); 1638 ctx.infer_body();
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 9f65c5fe1..9a571c2aa 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -6,19 +6,17 @@ use std::sync::Arc;
6 6
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use ra_db::SourceRootId;
10
11use crate::{ 9use crate::{
12 HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, 10 HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function,
13 impl_block::{ImplId, ImplBlock, ImplItem}, 11 impl_block::{ImplId, ImplBlock, ImplItem},
14 generics::GenericParams 12 generics::GenericParams,
13 ty::{AdtDef, Ty}
15}; 14};
16use super::Ty;
17 15
18/// This is used as a key for indexing impls. 16/// This is used as a key for indexing impls.
19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 17#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
20pub enum TyFingerprint { 18pub enum TyFingerprint {
21 Adt(DefId), 19 Adt(AdtDef),
22 // we'll also want to index impls for primitive types etc. 20 // we'll also want to index impls for primitive types etc.
23} 21}
24 22
@@ -37,7 +35,7 @@ impl TyFingerprint {
37#[derive(Debug, PartialEq, Eq)] 35#[derive(Debug, PartialEq, Eq)]
38pub struct CrateImplBlocks { 36pub struct CrateImplBlocks {
39 /// To make sense of the ModuleIds, we need the source root. 37 /// To make sense of the ModuleIds, we need the source root.
40 source_root_id: SourceRootId, 38 krate: Crate,
41 impls: FxHashMap<TyFingerprint, Vec<(ModuleId, ImplId)>>, 39 impls: FxHashMap<TyFingerprint, Vec<(ModuleId, ImplId)>>,
42} 40}
43 41
@@ -53,14 +51,17 @@ impl CrateImplBlocks {
53 .into_iter() 51 .into_iter()
54 .flat_map(|i| i.iter()) 52 .flat_map(|i| i.iter())
55 .map(move |(module_id, impl_id)| { 53 .map(move |(module_id, impl_id)| {
56 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id); 54 let module = Module {
55 krate: self.krate.crate_id,
56 module_id: *module_id,
57 };
58 let module_impl_blocks = db.impls_in_module(module);
57 ImplBlock::from_id(module_impl_blocks, *impl_id) 59 ImplBlock::from_id(module_impl_blocks, *impl_id)
58 }) 60 })
59 } 61 }
60 62
61 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { 63 fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) {
62 let module_id = module.def_id.loc(db).module_id; 64 let module_impl_blocks = db.impls_in_module(module.clone());
63 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id);
64 65
65 for (impl_id, impl_data) in module_impl_blocks.impls.iter() { 66 for (impl_id, impl_data) in module_impl_blocks.impls.iter() {
66 let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); 67 let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id);
@@ -81,13 +82,13 @@ impl CrateImplBlocks {
81 self.impls 82 self.impls
82 .entry(target_ty_fp) 83 .entry(target_ty_fp)
83 .or_insert_with(Vec::new) 84 .or_insert_with(Vec::new)
84 .push((module_id, impl_id)); 85 .push((module.module_id, impl_id));
85 } 86 }
86 } 87 }
87 } 88 }
88 89
89 for child in module.children(db) { 90 for child in module.children(db) {
90 self.collect_recursive(db, child); 91 self.collect_recursive(db, &child);
91 } 92 }
92 } 93 }
93 94
@@ -95,15 +96,12 @@ impl CrateImplBlocks {
95 db: &impl HirDatabase, 96 db: &impl HirDatabase,
96 krate: Crate, 97 krate: Crate,
97 ) -> Arc<CrateImplBlocks> { 98 ) -> Arc<CrateImplBlocks> {
98 let crate_graph = db.crate_graph();
99 let file_id = crate_graph.crate_root(krate.crate_id);
100 let source_root_id = db.file_source_root(file_id);
101 let mut crate_impl_blocks = CrateImplBlocks { 99 let mut crate_impl_blocks = CrateImplBlocks {
102 source_root_id, 100 krate: krate.clone(),
103 impls: FxHashMap::default(), 101 impls: FxHashMap::default(),
104 }; 102 };
105 if let Some(module) = krate.root_module(db) { 103 if let Some(module) = krate.root_module(db) {
106 crate_impl_blocks.collect_recursive(db, module); 104 crate_impl_blocks.collect_recursive(db, &module);
107 } 105 }
108 Arc::new(crate_impl_blocks) 106 Arc::new(crate_impl_blocks)
109 } 107 }
@@ -120,11 +118,11 @@ impl Ty {
120 // TODO: cache this as a query? 118 // TODO: cache this as a query?
121 // - if so, what signature? (TyFingerprint, Name)? 119 // - if so, what signature? (TyFingerprint, Name)?
122 // - or maybe cache all names and def_ids of methods per fingerprint? 120 // - or maybe cache all names and def_ids of methods per fingerprint?
123 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<DefId> { 121 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<Function> {
124 self.iterate_methods(db, |f| { 122 self.iterate_methods(db, |f| {
125 let sig = f.signature(db); 123 let sig = f.signature(db);
126 if sig.name() == name && sig.has_self_param() { 124 if sig.name() == name && sig.has_self_param() {
127 Some(f.def_id()) 125 Some(f)
128 } else { 126 } else {
129 None 127 None
130 } 128 }
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
index c4a2d5cf8..8747fae18 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
@@ -1,19 +1,19 @@
1--- 1---
2created: "2019-01-22T14:45:00.058678600+00:00" 2created: "2019-01-24T14:51:32.808861856+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: crates/ra_hir/src/ty/tests.rs
6--- 6---
7[72; 154) '{ ...a.c; }': () 7[72; 154) '{ ...a.c; }': ()
8[82; 83) 'c': [unknown] 8[82; 83) 'c': [unknown]
9[86; 87) 'C': [unknown] 9[86; 87) 'C': C
10[86; 90) 'C(1)': [unknown] 10[86; 90) 'C(1)': [unknown]
11[88; 89) '1': i32 11[88; 89) '1': i32
12[96; 97) 'B': [unknown] 12[96; 97) 'B': B
13[107; 108) 'a': A 13[107; 108) 'a': A
14[114; 133) 'A { b:...C(1) }': A 14[114; 133) 'A { b:...C(1) }': A
15[121; 122) 'B': B 15[121; 122) 'B': B
16[127; 128) 'C': [unknown] 16[127; 128) 'C': C
17[127; 131) 'C(1)': C 17[127; 131) 'C(1)': C
18[129; 130) '1': i32 18[129; 130) '1': i32
19[139; 140) 'a': A 19[139; 140) 'a': A