aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model_api.rs39
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs29
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs1
-rw-r--r--crates/ra_hir/src/db.rs20
-rw-r--r--crates/ra_hir/src/expr.rs22
-rw-r--r--crates/ra_hir/src/generics.rs66
-rw-r--r--crates/ra_hir/src/ids.rs66
-rw-r--r--crates/ra_hir/src/impl_block.rs31
-rw-r--r--crates/ra_hir/src/nameres/lower.rs13
-rw-r--r--crates/ra_hir/src/query_definitions.rs8
-rw-r--r--crates/ra_hir/src/source_binder.rs19
-rw-r--r--crates/ra_hir/src/ty.rs180
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs4
13 files changed, 297 insertions, 201 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index f59a60c07..905615127 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -16,6 +16,7 @@ use crate::{
16 code_model_impl::def_id_to_ast, 16 code_model_impl::def_id_to_ast,
17 docs::{Documentation, Docs, docs_from_ast}, 17 docs::{Documentation, Docs, docs_from_ast},
18 module_tree::ModuleId, 18 module_tree::ModuleId,
19 ids::FunctionId,
19}; 20};
20 21
21/// hir::Crate describes a single crate. It's the main interface with which 22/// hir::Crate describes a single crate. It's the main interface with which
@@ -49,7 +50,6 @@ pub enum Def {
49 Struct(Struct), 50 Struct(Struct),
50 Enum(Enum), 51 Enum(Enum),
51 EnumVariant(EnumVariant), 52 EnumVariant(EnumVariant),
52 Function(Function),
53 Const(Const), 53 Const(Const),
54 Static(Static), 54 Static(Static),
55 Trait(Trait), 55 Trait(Trait),
@@ -67,6 +67,7 @@ pub struct Module {
67#[derive(Debug, Clone, Copy, PartialEq, Eq)] 67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum ModuleDef { 68pub enum ModuleDef {
69 Module(Module), 69 Module(Module),
70 Function(Function),
70 Def(DefId), 71 Def(DefId),
71} 72}
72 73
@@ -76,6 +77,12 @@ impl Into<ModuleDef> for Module {
76 } 77 }
77} 78}
78 79
80impl Into<ModuleDef> for Function {
81 fn into(self) -> ModuleDef {
82 ModuleDef::Function(self)
83 }
84}
85
79impl Into<ModuleDef> for DefId { 86impl Into<ModuleDef> for DefId {
80 fn into(self) -> ModuleDef { 87 fn into(self) -> ModuleDef {
81 ModuleDef::Def(self) 88 ModuleDef::Def(self)
@@ -225,7 +232,7 @@ impl Struct {
225 } 232 }
226 233
227 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 234 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
228 db.generic_params(self.def_id) 235 db.generic_params(self.def_id.into())
229 } 236 }
230} 237}
231 238
@@ -262,7 +269,7 @@ impl Enum {
262 } 269 }
263 270
264 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 271 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
265 db.generic_params(self.def_id) 272 db.generic_params(self.def_id.into())
266 } 273 }
267} 274}
268 275
@@ -320,9 +327,9 @@ impl Docs for EnumVariant {
320 } 327 }
321} 328}
322 329
323#[derive(Debug, Clone, PartialEq, Eq, Hash)] 330#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
324pub struct Function { 331pub struct Function {
325 pub(crate) def_id: DefId, 332 pub(crate) id: FunctionId,
326} 333}
327 334
328pub use crate::code_model_impl::function::ScopeEntryWithSyntax; 335pub use crate::code_model_impl::function::ScopeEntryWithSyntax;
@@ -359,21 +366,17 @@ impl FnSignature {
359} 366}
360 367
361impl Function { 368impl Function {
362 pub fn def_id(&self) -> DefId {
363 self.def_id
364 }
365
366 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { 369 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) {
367 def_id_to_ast(db, self.def_id) 370 self.id.loc(db).source(db)
368 } 371 }
369 372
370 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { 373 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
371 db.body_syntax_mapping(self.def_id) 374 db.body_syntax_mapping(*self)
372 } 375 }
373 376
374 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { 377 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
375 let scopes = db.fn_scopes(self.def_id); 378 let scopes = db.fn_scopes(*self);
376 let syntax_mapping = db.body_syntax_mapping(self.def_id); 379 let syntax_mapping = db.body_syntax_mapping(*self);
377 ScopesWithSyntaxMapping { 380 ScopesWithSyntaxMapping {
378 scopes, 381 scopes,
379 syntax_mapping, 382 syntax_mapping,
@@ -381,15 +384,15 @@ impl Function {
381 } 384 }
382 385
383 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { 386 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
384 db.fn_signature(self.def_id) 387 db.fn_signature(*self)
385 } 388 }
386 389
387 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { 390 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
388 db.infer(self.def_id) 391 db.infer(*self)
389 } 392 }
390 393
391 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 394 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
392 db.generic_params(self.def_id) 395 db.generic_params((*self).into())
393 } 396 }
394} 397}
395 398
@@ -456,7 +459,7 @@ impl Trait {
456 } 459 }
457 460
458 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 461 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
459 db.generic_params(self.def_id) 462 db.generic_params(self.def_id.into())
460 } 463 }
461} 464}
462 465
@@ -481,7 +484,7 @@ impl Type {
481 } 484 }
482 485
483 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 486 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
484 db.generic_params(self.def_id) 487 db.generic_params(self.def_id.into())
485 } 488 }
486} 489}
487 490
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index c68c6bfbf..d8dafb10e 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -2,41 +2,48 @@ 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, Module, HirFileId,
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, 12 ids::FunctionLoc,
13}; 13};
14 14
15pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; 15pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
16 16
17impl Function { 17impl Function {
18 pub(crate) fn new(def_id: DefId) -> Function { 18 pub(crate) fn from_ast(
19 Function { def_id } 19 db: &impl HirDatabase,
20 module: Module,
21 file_id: HirFileId,
22 ast: &ast::FnDef,
23 ) -> Function {
24 let loc: FunctionLoc = FunctionLoc::from_ast(db, module, file_id, ast);
25 let id = loc.id(db);
26 Function { id }
20 } 27 }
21 28
22 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 29 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
23 db.body_hir(self.def_id) 30 db.body_hir(*self)
24 } 31 }
25 32
26 pub(crate) fn module(&self, db: &impl HirDatabase) -> Module { 33 pub(crate) fn module(&self, db: &impl HirDatabase) -> Module {
27 self.def_id.module(db) 34 self.id.loc(db).module
28 } 35 }
29 36
30 /// The containing impl block, if this is a method. 37 /// The containing impl block, if this is a method.
31 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { 38 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> {
32 self.def_id.impl_block(db) 39 let module_impls = db.impls_in_module(self.module(db));
40 ImplBlock::containing(module_impls, (*self).into())
33 } 41 }
34} 42}
35 43
36impl FnSignature { 44impl FnSignature {
37 pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> { 45 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 46 let (_, node) = func.source(db);
39 let node: TreeArc<ast::FnDef> = def_id_to_ast(db, def_id).1;
40 let name = node 47 let name = node
41 .name() 48 .name()
42 .map(|n| n.as_name()) 49 .map(|n| n.as_name())
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 5d00e905b..b2828c7be 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -135,6 +135,7 @@ impl Module {
135 None => PerNs::none(), 135 None => PerNs::none(),
136 } 136 }
137 } 137 }
138 ModuleDef::Function(_) => PerNs::none(),
138 ModuleDef::Def(def) => { 139 ModuleDef::Def(def) => {
139 match def.resolve(db) { 140 match def.resolve(db) {
140 Def::Enum(e) => { 141 Def::Enum(e) => {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 0898daa3c..97de7da31 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -7,14 +7,14 @@ use crate::{
7 DefId, MacroCallId, Name, HirFileId, 7 DefId, MacroCallId, Name, HirFileId,
8 SourceFileItems, SourceItemId, Crate, Module, HirInterner, 8 SourceFileItems, SourceItemId, Crate, Module, HirInterner,
9 query_definitions, 9 query_definitions,
10 FnSignature, FnScopes, 10 Function, FnSignature, FnScopes,
11 macros::MacroExpansion, 11 macros::MacroExpansion,
12 module_tree::ModuleTree, 12 module_tree::ModuleTree,
13 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, 13 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, 14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef},
15 adt::{StructData, EnumData, EnumVariantData}, 15 adt::{StructData, EnumData, EnumVariantData},
16 impl_block::ModuleImplBlocks, 16 impl_block::ModuleImplBlocks,
17 generics::GenericParams, 17 generics::{GenericParams, GenericDef},
18}; 18};
19 19
20#[salsa::query_group] 20#[salsa::query_group]
@@ -26,7 +26,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
26 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; 26 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
27 27
28 #[salsa::invoke(query_definitions::fn_scopes)] 28 #[salsa::invoke(query_definitions::fn_scopes)]
29 fn fn_scopes(&self, def_id: DefId) -> Arc<FnScopes>; 29 fn fn_scopes(&self, func: Function) -> Arc<FnScopes>;
30 30
31 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 31 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
32 fn struct_data(&self, def_id: DefId) -> Arc<StructData>; 32 fn struct_data(&self, def_id: DefId) -> Arc<StructData>;
@@ -38,10 +38,10 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
38 fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>; 38 fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>;
39 39
40 #[salsa::invoke(crate::ty::infer)] 40 #[salsa::invoke(crate::ty::infer)]
41 fn infer(&self, def_id: DefId) -> Arc<InferenceResult>; 41 fn infer(&self, func: Function) -> Arc<InferenceResult>;
42 42
43 #[salsa::invoke(crate::ty::type_for_def)] 43 #[salsa::invoke(crate::ty::type_for_def)]
44 fn type_for_def(&self, def_id: DefId) -> Ty; 44 fn type_for_def(&self, def: TypableDef) -> Ty;
45 45
46 #[salsa::invoke(crate::ty::type_for_field)] 46 #[salsa::invoke(crate::ty::type_for_field)]
47 fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>; 47 fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>;
@@ -77,14 +77,14 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
77 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 77 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
78 78
79 #[salsa::invoke(crate::expr::body_hir)] 79 #[salsa::invoke(crate::expr::body_hir)]
80 fn body_hir(&self, def_id: DefId) -> Arc<crate::expr::Body>; 80 fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>;
81 81
82 #[salsa::invoke(crate::expr::body_syntax_mapping)] 82 #[salsa::invoke(crate::expr::body_syntax_mapping)]
83 fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; 83 fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>;
84 84
85 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] 85 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
86 fn generic_params(&self, def_id: DefId) -> Arc<GenericParams>; 86 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
87 87
88 #[salsa::invoke(crate::FnSignature::fn_signature_query)] 88 #[salsa::invoke(crate::FnSignature::fn_signature_query)]
89 fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; 89 fn fn_signature(&self, func: Function) -> Arc<FnSignature>;
90} 90}
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..88c53705f 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, AstNode, NameOwner, TypeParamsOwner};
9 9
10use crate::{db::HirDatabase, DefId, Name, AsName}; 10use crate::{db::HirDatabase, DefId, Name, AsName, Function};
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,62 @@ 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 Def(DefId),
29}
30
31impl From<Function> for GenericDef {
32 fn from(func: Function) -> GenericDef {
33 GenericDef::Function(func)
34 }
35}
36
37impl From<DefId> for GenericDef {
38 fn from(def_id: DefId) -> GenericDef {
39 GenericDef::Def(def_id)
40 }
41}
42
25impl GenericParams { 43impl GenericParams {
26 pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> { 44 pub(crate) fn generic_params_query(
27 let (_file_id, node) = def_id.source(db); 45 db: &impl HirDatabase,
46 def: GenericDef,
47 ) -> Arc<GenericParams> {
28 let mut generics = GenericParams::default(); 48 let mut generics = GenericParams::default();
29 if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { 49 match def {
30 for (idx, type_param) in type_param_list.type_params().enumerate() { 50 GenericDef::Function(func) => {
31 let name = type_param 51 let (_, fn_def) = func.source(db);
32 .name() 52 if let Some(type_param_list) = fn_def.type_param_list() {
33 .map(AsName::as_name) 53 generics.fill(type_param_list)
34 .unwrap_or_else(Name::missing); 54 }
35 let param = GenericParam { 55 }
36 idx: idx as u32, 56 GenericDef::Def(def_id) => {
37 name, 57 let (_file_id, node) = def_id.source(db);
38 }; 58 if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) {
39 generics.params.push(param); 59 generics.fill(type_param_list)
60 }
40 } 61 }
41 } 62 }
63
42 Arc::new(generics) 64 Arc::new(generics)
43 } 65 }
44 66
67 fn fill(&mut self, params: &ast::TypeParamList) {
68 for (idx, type_param) in params.type_params().enumerate() {
69 let name = type_param
70 .name()
71 .map(AsName::as_name)
72 .unwrap_or_else(Name::missing);
73 let param = GenericParam {
74 idx: idx as u32,
75 name,
76 };
77 self.params.push(param);
78 }
79 }
80
45 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 81 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
46 self.params.iter().find(|p| &p.name == name) 82 self.params.iter().find(|p| &p.name == name)
47 } 83 }
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 73f1379f1..913341bd5 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,9 +1,11 @@
1use std::marker::PhantomData;
2
1use ra_db::{LocationIntener, FileId}; 3use ra_db::{LocationIntener, FileId};
2use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; 4use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
3use ra_arena::{Arena, RawId, impl_arena_id}; 5use ra_arena::{Arena, RawId, impl_arena_id};
4 6
5use crate::{ 7use crate::{
6 HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, 8 HirDatabase, Def, Struct, Enum, EnumVariant, Crate,
7 Module, Trait, Type, Static, Const, 9 Module, Trait, Type, Static, Const,
8}; 10};
9 11
@@ -129,15 +131,56 @@ impl MacroCallLoc {
129 } 131 }
130} 132}
131 133
134#[derive(Debug, PartialEq, Eq, Hash)]
135pub struct ItemLoc<N: AstNode> {
136 pub(crate) module: Module,
137 raw: SourceItemId,
138 _ty: PhantomData<N>,
139}
140
141impl<N: AstNode> ItemLoc<N> {
142 pub(crate) fn from_ast(
143 db: &impl HirDatabase,
144 module: Module,
145 file_id: HirFileId,
146 ast: &N,
147 ) -> ItemLoc<N> {
148 let items = db.file_items(file_id);
149 let raw = SourceItemId {
150 file_id,
151 item_id: Some(items.id_of(file_id, ast.syntax())),
152 };
153 ItemLoc {
154 module,
155 raw,
156 _ty: PhantomData,
157 }
158 }
159
160 pub(crate) fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) {
161 let syntax = db.file_item(self.raw);
162 let ast = N::cast(&syntax)
163 .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", self.raw))
164 .to_owned();
165 (self.raw.file_id, ast)
166 }
167}
168
169impl<N: AstNode> Clone for ItemLoc<N> {
170 fn clone(&self) -> ItemLoc<N> {
171 ItemLoc {
172 module: self.module,
173 raw: self.raw,
174 _ty: PhantomData,
175 }
176 }
177}
178
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 179#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
133pub struct FunctionId(RawId); 180pub struct FunctionId(RawId);
134impl_arena_id!(FunctionId); 181impl_arena_id!(FunctionId);
135 182
136#[derive(Clone, Debug, PartialEq, Eq, Hash)] 183pub(crate) type FunctionLoc = ItemLoc<ast::FnDef>;
137pub struct FunctionLoc {
138 pub(crate) module: Module,
139 pub(crate) source_item_id: SourceItemId,
140}
141 184
142impl FunctionId { 185impl FunctionId {
143 pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> FunctionLoc { 186 pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> FunctionLoc {
@@ -196,10 +239,7 @@ impl DefId {
196 pub fn resolve(self, db: &impl HirDatabase) -> Def { 239 pub fn resolve(self, db: &impl HirDatabase) -> Def {
197 let loc = self.loc(db); 240 let loc = self.loc(db);
198 match loc.kind { 241 match loc.kind {
199 DefKind::Function => { 242 DefKind::Function => unreachable!(),
200 let function = Function::new(self);
201 Def::Function(function)
202 }
203 DefKind::Struct => { 243 DefKind::Struct => {
204 let struct_def = Struct::new(self); 244 let struct_def = Struct::new(self);
205 Def::Struct(struct_def) 245 Def::Struct(struct_def)
@@ -243,12 +283,6 @@ impl DefId {
243 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { 283 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
244 self.module(db).krate(db) 284 self.module(db).krate(db)
245 } 285 }
246
247 /// Returns the containing impl block, if this is an impl item.
248 pub fn impl_block(self, db: &impl HirDatabase) -> Option<ImplBlock> {
249 let module_impls = db.impls_in_module(self.loc(db).module);
250 ImplBlock::containing(module_impls, self)
251 }
252} 286}
253 287
254impl DefLoc { 288impl DefLoc {
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index ba8b84da2..29becd317 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -6,7 +6,7 @@ use ra_syntax::ast::{self, AstNode};
6 6
7use crate::{ 7use crate::{
8 DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, 8 DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
9 Function, HirFileId, HirInterner, 9 Function, HirFileId,
10 db::HirDatabase, 10 db::HirDatabase,
11 type_ref::TypeRef, 11 type_ref::TypeRef,
12}; 12};
@@ -22,9 +22,9 @@ pub struct ImplBlock {
22impl ImplBlock { 22impl ImplBlock {
23 pub(crate) fn containing( 23 pub(crate) fn containing(
24 module_impl_blocks: Arc<ModuleImplBlocks>, 24 module_impl_blocks: Arc<ModuleImplBlocks>,
25 def_id: DefId, 25 item: ImplItem,
26 ) -> Option<ImplBlock> { 26 ) -> Option<ImplBlock> {
27 let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?; 27 let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
28 Some(ImplBlock { 28 Some(ImplBlock {
29 module_impl_blocks, 29 module_impl_blocks,
30 impl_id, 30 impl_id,
@@ -64,7 +64,7 @@ pub struct ImplData {
64 64
65impl ImplData { 65impl ImplData {
66 pub(crate) fn from_ast( 66 pub(crate) fn from_ast(
67 db: &impl AsRef<HirInterner>, 67 db: &impl HirDatabase,
68 file_id: HirFileId, 68 file_id: HirFileId,
69 file_items: &SourceFileItems, 69 file_items: &SourceFileItems,
70 module: Module, 70 module: Module,
@@ -93,7 +93,9 @@ impl ImplData {
93 }; 93 };
94 let def_id = def_loc.id(db); 94 let def_id = def_loc.id(db);
95 match item_node.kind() { 95 match item_node.kind() {
96 ast::ImplItemKind::FnDef(..) => ImplItem::Method(Function::new(def_id)), 96 ast::ImplItemKind::FnDef(it) => {
97 ImplItem::Method(Function::from_ast(db, module, file_id, it))
98 }
97 ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id), 99 ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id),
98 ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id), 100 ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id),
99 } 101 }
@@ -122,7 +124,8 @@ impl ImplData {
122 } 124 }
123} 125}
124 126
125#[derive(Debug, Clone, PartialEq, Eq)] 127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128//TODO: rename to ImplDef?
126pub enum ImplItem { 129pub enum ImplItem {
127 Method(Function), 130 Method(Function),
128 // these don't have their own types yet 131 // these don't have their own types yet
@@ -131,13 +134,9 @@ pub enum ImplItem {
131 // Existential 134 // Existential
132} 135}
133 136
134impl ImplItem { 137impl From<Function> for ImplItem {
135 pub fn def_id(&self) -> DefId { 138 fn from(func: Function) -> ImplItem {
136 match self { 139 ImplItem::Method(func)
137 ImplItem::Method(f) => f.def_id(),
138 ImplItem::Const(def_id) => *def_id,
139 ImplItem::Type(def_id) => *def_id,
140 }
141 } 140 }
142} 141}
143 142
@@ -153,7 +152,7 @@ impl_arena_id!(ImplId);
153#[derive(Debug, PartialEq, Eq)] 152#[derive(Debug, PartialEq, Eq)]
154pub struct ModuleImplBlocks { 153pub struct ModuleImplBlocks {
155 pub(crate) impls: Arena<ImplId, ImplData>, 154 pub(crate) impls: Arena<ImplId, ImplData>,
156 impls_by_def: FxHashMap<DefId, ImplId>, 155 impls_by_def: FxHashMap<ImplItem, ImplId>,
157} 156}
158 157
159impl ModuleImplBlocks { 158impl ModuleImplBlocks {
@@ -181,8 +180,8 @@ impl ModuleImplBlocks {
181 let impl_block = 180 let impl_block =
182 ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast); 181 ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast);
183 let id = self.impls.alloc(impl_block); 182 let id = self.impls.alloc(impl_block);
184 for impl_item in &self.impls[id].items { 183 for &impl_item in &self.impls[id].items {
185 self.impls_by_def.insert(impl_item.def_id(), id); 184 self.impls_by_def.insert(impl_item, id);
186 } 185 }
187 } 186 }
188 } 187 }
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 6f003bd66..1f8adc7eb 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -9,7 +9,7 @@ use rustc_hash::FxHashMap;
9 9
10use crate::{ 10use crate::{
11 SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, 11 SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
12 HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, 12 HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function,
13 ModuleDef, Module, 13 ModuleDef, Module,
14}; 14};
15 15
@@ -149,7 +149,14 @@ impl LoweredModule {
149 let name = match item.kind() { 149 let name = match item.kind() {
150 ast::ModuleItemKind::StructDef(it) => it.name(), 150 ast::ModuleItemKind::StructDef(it) => it.name(),
151 ast::ModuleItemKind::EnumDef(it) => it.name(), 151 ast::ModuleItemKind::EnumDef(it) => it.name(),
152 ast::ModuleItemKind::FnDef(it) => it.name(), 152 ast::ModuleItemKind::FnDef(it) => {
153 if let Some(name) = it.name() {
154 let func = Function::from_ast(db, module, file_id, it);
155 self.declarations
156 .insert(name.as_name(), PerNs::values(func.into()));
157 }
158 return;
159 }
153 ast::ModuleItemKind::TraitDef(it) => it.name(), 160 ast::ModuleItemKind::TraitDef(it) => it.name(),
154 ast::ModuleItemKind::TypeDef(it) => it.name(), 161 ast::ModuleItemKind::TypeDef(it) => it.name(),
155 ast::ModuleItemKind::ImplBlock(_) => { 162 ast::ModuleItemKind::ImplBlock(_) => {
@@ -218,7 +225,7 @@ fn assign_def_id(
218impl DefKind { 225impl DefKind {
219 fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> { 226 fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
220 match kind { 227 match kind {
221 SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), 228 SyntaxKind::FN_DEF => unreachable!(),
222 SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), 229 SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
223 SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), 230 SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
224 SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), 231 SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index a8ed887b3..cf8c7e435 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -10,14 +10,14 @@ use ra_syntax::{
10use ra_db::{CrateId}; 10use ra_db::{CrateId};
11 11
12use crate::{ 12use crate::{
13 SourceFileItems, SourceItemId, DefId, HirFileId, 13 SourceFileItems, SourceItemId, HirFileId,
14 FnScopes, Module, 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}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index c3bd31d6b..d1bf163d1 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -14,7 +14,7 @@ use ra_syntax::{
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, SourceItemId, ModuleDef, 16 HirDatabase, Function, SourceItemId, ModuleDef,
17 DefKind, DefLoc, AsName, Module, 17 AsName, Module,
18}; 18};
19 19
20/// Locates the module by `FileId`. Picks topmost module in the file. 20/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -105,29 +105,18 @@ pub fn function_from_source(
105 fn_def: &ast::FnDef, 105 fn_def: &ast::FnDef,
106) -> Option<Function> { 106) -> Option<Function> {
107 let module = module_from_child_node(db, file_id, fn_def.syntax())?; 107 let module = module_from_child_node(db, file_id, fn_def.syntax())?;
108 let res = function_from_module(db, &module, fn_def); 108 let res = function_from_module(db, module, fn_def);
109 Some(res) 109 Some(res)
110} 110}
111 111
112pub fn function_from_module( 112pub fn function_from_module(
113 db: &impl HirDatabase, 113 db: &impl HirDatabase,
114 module: &Module, 114 module: Module,
115 fn_def: &ast::FnDef, 115 fn_def: &ast::FnDef,
116) -> Function { 116) -> Function {
117 let (file_id, _) = module.definition_source(db); 117 let (file_id, _) = module.definition_source(db);
118 let file_id = file_id.into(); 118 let file_id = file_id.into();
119 let file_items = db.file_items(file_id); 119 Function::from_ast(db, module, file_id, fn_def)
120 let item_id = file_items.id_of(file_id, fn_def.syntax());
121 let source_item_id = SourceItemId {
122 file_id,
123 item_id: Some(item_id),
124 };
125 let def_loc = DefLoc {
126 module: module.clone(),
127 kind: DefKind::Function,
128 source_item_id,
129 };
130 Function::new(def_loc.id(db))
131} 120}
132 121
133pub fn function_from_child_node( 122pub fn function_from_child_node(
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 4c96579ee..f9cdbcab3 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -382,7 +382,8 @@ impl Ty {
382 382
383 // Resolve in module (in type namespace) 383 // Resolve in module (in type namespace)
384 let resolved = match module.resolve_path(db, path).take_types() { 384 let resolved = match module.resolve_path(db, path).take_types() {
385 Some(ModuleDef::Def(r)) => r, 385 Some(ModuleDef::Def(r)) => r.into(),
386 Some(ModuleDef::Function(f)) => f.into(),
386 None | Some(ModuleDef::Module(_)) => return Ty::Unknown, 387 None | Some(ModuleDef::Module(_)) => return Ty::Unknown,
387 }; 388 };
388 let ty = db.type_for_def(resolved); 389 let ty = db.type_for_def(resolved);
@@ -399,36 +400,38 @@ impl Ty {
399 impl_block: Option<&ImplBlock>, 400 impl_block: Option<&ImplBlock>,
400 outer_generics: &GenericParams, 401 outer_generics: &GenericParams,
401 path: &Path, 402 path: &Path,
402 resolved: DefId, 403 resolved: TypableDef,
403 ) -> Substs { 404 ) -> Substs {
404 let mut substs = Vec::new(); 405 let mut substs = Vec::new();
405 let def = resolved.resolve(db);
406 let last = path 406 let last = path
407 .segments 407 .segments
408 .last() 408 .last()
409 .expect("path should have at least one segment"); 409 .expect("path should have at least one segment");
410 let (def_generics, segment) = match def { 410 let (def_generics, segment) = match resolved {
411 Def::Struct(s) => (s.generic_params(db), last), 411 TypableDef::Function(func) => (func.generic_params(db), last),
412 Def::Enum(e) => (e.generic_params(db), last), 412 TypableDef::Def(def_id) => match def_id.resolve(db) {
413 Def::Function(f) => (f.generic_params(db), last), 413 Def::Struct(s) => (s.generic_params(db), last),
414 Def::Trait(t) => (t.generic_params(db), last), 414 Def::Enum(e) => (e.generic_params(db), last),
415 Def::EnumVariant(ev) => { 415 Def::Trait(t) => (t.generic_params(db), last),
416 // the generic args for an enum variant may be either specified 416 Def::EnumVariant(ev) => {
417 // on the segment referring to the enum, or on the segment 417 // the generic args for an enum variant may be either specified
418 // referring to the variant. So `Option::<T>::None` and 418 // on the segment referring to the enum, or on the segment
419 // `Option::None::<T>` are both allowed (though the former is 419 // referring to the variant. So `Option::<T>::None` and
420 // preferred). See also `def_ids_for_path_segments` in rustc. 420 // `Option::None::<T>` are both allowed (though the former is
421 let len = path.segments.len(); 421 // preferred). See also `def_ids_for_path_segments` in rustc.
422 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { 422 let len = path.segments.len();
423 // Option::<T>::None 423 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some()
424 &path.segments[len - 2] 424 {
425 } else { 425 // Option::<T>::None
426 // Option::None::<T> 426 &path.segments[len - 2]
427 last 427 } else {
428 }; 428 // Option::None::<T>
429 (ev.parent_enum(db).generic_params(db), segment) 429 last
430 } 430 };
431 _ => return Substs::empty(), 431 (ev.parent_enum(db).generic_params(db), segment)
432 }
433 _ => return Substs::empty(),
434 },
432 }; 435 };
433 // substs_from_path 436 // substs_from_path
434 if let Some(generic_args) = &segment.args_and_bindings { 437 if let Some(generic_args) = &segment.args_and_bindings {
@@ -660,21 +663,40 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T
660 type_for_enum(db, enum_parent) 663 type_for_enum(db, enum_parent)
661} 664}
662 665
663pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { 666#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
664 let def = def_id.resolve(db); 667pub enum TypableDef {
668 Function(Function),
669 Def(DefId),
670}
671
672impl From<Function> for TypableDef {
673 fn from(func: Function) -> TypableDef {
674 TypableDef::Function(func)
675 }
676}
677
678impl From<DefId> for TypableDef {
679 fn from(func: DefId) -> TypableDef {
680 TypableDef::Def(func)
681 }
682}
683
684pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
665 match def { 685 match def {
666 Def::Function(f) => type_for_fn(db, f), 686 TypableDef::Function(f) => type_for_fn(db, f),
667 Def::Struct(s) => type_for_struct(db, s), 687 TypableDef::Def(def_id) => match def_id.resolve(db) {
668 Def::Enum(e) => type_for_enum(db, e), 688 Def::Struct(s) => type_for_struct(db, s),
669 Def::EnumVariant(ev) => type_for_enum_variant(db, ev), 689 Def::Enum(e) => type_for_enum(db, e),
670 _ => { 690 Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
671 log::debug!( 691 _ => {
672 "trying to get type for item of unknown type {:?} {:?}", 692 log::debug!(
673 def_id, 693 "trying to get type for item of unknown type {:?} {:?}",
674 def 694 def_id,
675 ); 695 def
676 Ty::Unknown 696 );
677 } 697 Ty::Unknown
698 }
699 },
678 } 700 }
679} 701}
680 702
@@ -694,28 +716,23 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
694 ), 716 ),
695 }; 717 };
696 let module = def_id.module(db); 718 let module = def_id.module(db);
697 let impl_block = def_id.impl_block(db); 719 // We can't have an impl block ere, right?
720 // let impl_block = def_id.impl_block(db);
698 let type_ref = variant_data.get_field_type_ref(&field)?; 721 let type_ref = variant_data.get_field_type_ref(&field)?;
699 Some(Ty::from_hir( 722 Some(Ty::from_hir(db, &module, None, &generics, &type_ref))
700 db,
701 &module,
702 impl_block.as_ref(),
703 &generics,
704 &type_ref,
705 ))
706} 723}
707 724
708/// The result of type inference: A mapping from expressions and patterns to types. 725/// The result of type inference: A mapping from expressions and patterns to types.
709#[derive(Clone, PartialEq, Eq, Debug)] 726#[derive(Clone, PartialEq, Eq, Debug)]
710pub struct InferenceResult { 727pub struct InferenceResult {
711 /// For each method call expr, record the function it resolved to. 728 /// For each method call expr, record the function it resolved to.
712 method_resolutions: FxHashMap<ExprId, DefId>, 729 method_resolutions: FxHashMap<ExprId, Function>,
713 type_of_expr: ArenaMap<ExprId, Ty>, 730 type_of_expr: ArenaMap<ExprId, Ty>,
714 type_of_pat: ArenaMap<PatId, Ty>, 731 type_of_pat: ArenaMap<PatId, Ty>,
715} 732}
716 733
717impl InferenceResult { 734impl InferenceResult {
718 pub fn method_resolution(&self, expr: ExprId) -> Option<DefId> { 735 pub fn method_resolution(&self, expr: ExprId) -> Option<Function> {
719 self.method_resolutions.get(&expr).map(|it| *it) 736 self.method_resolutions.get(&expr).map(|it| *it)
720 } 737 }
721} 738}
@@ -745,7 +762,7 @@ struct InferenceContext<'a, D: HirDatabase> {
745 module: Module, 762 module: Module,
746 impl_block: Option<ImplBlock>, 763 impl_block: Option<ImplBlock>,
747 var_unification_table: InPlaceUnificationTable<TypeVarId>, 764 var_unification_table: InPlaceUnificationTable<TypeVarId>,
748 method_resolutions: FxHashMap<ExprId, DefId>, 765 method_resolutions: FxHashMap<ExprId, Function>,
749 type_of_expr: ArenaMap<ExprId, Ty>, 766 type_of_expr: ArenaMap<ExprId, Ty>,
750 type_of_pat: ArenaMap<PatId, Ty>, 767 type_of_pat: ArenaMap<PatId, Ty>,
751 /// The return type of the function being inferred. 768 /// The return type of the function being inferred.
@@ -871,8 +888,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
871 self.type_of_expr.insert(expr, ty); 888 self.type_of_expr.insert(expr, ty);
872 } 889 }
873 890
874 fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) { 891 fn write_method_resolution(&mut self, expr: ExprId, func: Function) {
875 self.method_resolutions.insert(expr, def_id); 892 self.method_resolutions.insert(expr, func);
876 } 893 }
877 894
878 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { 895 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
@@ -1060,7 +1077,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1060 1077
1061 // resolve in module 1078 // resolve in module
1062 let resolved = match self.module.resolve_path(self.db, &path).take_values()? { 1079 let resolved = match self.module.resolve_path(self.db, &path).take_values()? {
1063 ModuleDef::Def(it) => it, 1080 ModuleDef::Def(it) => it.into(),
1081 ModuleDef::Function(func) => func.into(),
1064 ModuleDef::Module(_) => return None, 1082 ModuleDef::Module(_) => return None,
1065 }; 1083 };
1066 let ty = self.db.type_for_def(resolved); 1084 let ty = self.db.type_for_def(resolved);
@@ -1073,8 +1091,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1073 Some(path) => path, 1091 Some(path) => path,
1074 None => return (Ty::Unknown, None), 1092 None => return (Ty::Unknown, None),
1075 }; 1093 };
1076 let def_id = match self.module.resolve_path(self.db, &path).take_types() { 1094 let def = match self.module.resolve_path(self.db, &path).take_types() {
1077 Some(ModuleDef::Def(def_id)) => def_id, 1095 Some(ModuleDef::Def(def_id)) => def_id.into(),
1096 Some(ModuleDef::Function(func)) => func.into(),
1078 _ => return (Ty::Unknown, None), 1097 _ => return (Ty::Unknown, None),
1079 }; 1098 };
1080 // TODO remove the duplication between here and `Ty::from_path`? 1099 // TODO remove the duplication between here and `Ty::from_path`?
@@ -1086,20 +1105,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1086 self.impl_block.as_ref(), 1105 self.impl_block.as_ref(),
1087 &generics, 1106 &generics,
1088 path, 1107 path,
1089 def_id, 1108 def,
1090 ); 1109 );
1091 match def_id.resolve(self.db) { 1110 match def {
1092 Def::Struct(s) => { 1111 TypableDef::Def(def_id) => match def_id.resolve(self.db) {
1093 let ty = type_for_struct(self.db, s); 1112 Def::Struct(s) => {
1094 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1113 let ty = type_for_struct(self.db, s);
1095 (ty, Some(def_id)) 1114 let ty = self.insert_type_vars(ty.apply_substs(substs));
1096 } 1115 (ty, Some(def_id))
1097 Def::EnumVariant(ev) => { 1116 }
1098 let ty = type_for_enum_variant(self.db, ev); 1117 Def::EnumVariant(ev) => {
1099 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1118 let ty = type_for_enum_variant(self.db, ev);
1100 (ty, Some(def_id)) 1119 let ty = self.insert_type_vars(ty.apply_substs(substs));
1101 } 1120 (ty, Some(def_id))
1102 _ => (Ty::Unknown, None), 1121 }
1122 _ => (Ty::Unknown, None),
1123 },
1124 TypableDef::Function(_) => (Ty::Unknown, None),
1103 } 1125 }
1104 } 1126 }
1105 1127
@@ -1216,7 +1238,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1216 .resolve_path(self.db, &path) 1238 .resolve_path(self.db, &path)
1217 .take_values() 1239 .take_values()
1218 .and_then(|module_def| match module_def { 1240 .and_then(|module_def| match module_def {
1219 ModuleDef::Def(it) => Some(it), 1241 ModuleDef::Def(it) => Some(it.into()),
1242 ModuleDef::Function(func) => Some(func.into()),
1220 ModuleDef::Module(_) => None, 1243 ModuleDef::Module(_) => None,
1221 }) 1244 })
1222 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), 1245 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)),
@@ -1339,9 +1362,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1339 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 1362 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
1340 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 1363 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
1341 let method_ty = match resolved { 1364 let method_ty = match resolved {
1342 Some(def_id) => { 1365 Some(func) => {
1343 self.write_method_resolution(expr, def_id); 1366 self.write_method_resolution(expr, func);
1344 self.db.type_for_def(def_id) 1367 self.db.type_for_def(func.into())
1345 } 1368 }
1346 None => Ty::Unknown, 1369 None => Ty::Unknown,
1347 }; 1370 };
@@ -1610,16 +1633,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1610 } 1633 }
1611} 1634}
1612 1635
1613pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> { 1636pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
1614 db.check_canceled(); 1637 db.check_canceled();
1615 let function = Function::new(def_id); // TODO: consts also need inference 1638 let body = func.body(db);
1616 let body = function.body(db); 1639 let scopes = db.fn_scopes(func);
1617 let scopes = db.fn_scopes(def_id); 1640 let module = func.module(db);
1618 let module = function.module(db); 1641 let impl_block = func.impl_block(db);
1619 let impl_block = function.impl_block(db);
1620 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1642 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
1621 1643
1622 let signature = function.signature(db); 1644 let signature = func.signature(db);
1623 ctx.collect_fn_signature(&signature); 1645 ctx.collect_fn_signature(&signature);
1624 1646
1625 ctx.infer_body(); 1647 ctx.infer_body();
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index a5567a78f..0084b24dc 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -118,11 +118,11 @@ impl Ty {
118 // TODO: cache this as a query? 118 // TODO: cache this as a query?
119 // - if so, what signature? (TyFingerprint, Name)? 119 // - if so, what signature? (TyFingerprint, Name)?
120 // - 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?
121 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> {
122 self.iterate_methods(db, |f| { 122 self.iterate_methods(db, |f| {
123 let sig = f.signature(db); 123 let sig = f.signature(db);
124 if sig.name() == name && sig.has_self_param() { 124 if sig.name() == name && sig.has_self_param() {
125 Some(f.def_id()) 125 Some(f)
126 } else { 126 } else {
127 None 127 None
128 } 128 }