aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model_api.rs30
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs4
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs13
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs15
-rw-r--r--crates/ra_hir/src/db.rs25
-rw-r--r--crates/ra_hir/src/expr.rs4
-rw-r--r--crates/ra_hir/src/expr/scope.rs (renamed from crates/ra_hir/src/code_model_impl/function/scope.rs)31
-rw-r--r--crates/ra_hir/src/impl_block.rs57
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/module_tree.rs11
-rw-r--r--crates/ra_hir/src/nameres.rs33
-rw-r--r--crates/ra_hir/src/nameres/tests.rs14
-rw-r--r--crates/ra_hir/src/query_definitions.rs42
-rw-r--r--crates/ra_hir/src/source_binder.rs29
-rw-r--r--crates/ra_hir/src/ty.rs180
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap24
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap46
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap10
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap26
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap37
-rw-r--r--crates/ra_hir/src/ty/tests.rs28
24 files changed, 471 insertions, 214 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 191104890..9405aa8ad 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -10,12 +10,13 @@ use crate::{
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},
14 adt::{EnumVariantId, StructFieldId, VariantDef}, 14 adt::{EnumVariantId, StructFieldId, VariantDef},
15 generics::GenericParams, 15 generics::GenericParams,
16 docs::{Documentation, Docs, docs_from_ast}, 16 docs::{Documentation, Docs, docs_from_ast},
17 module_tree::ModuleId, 17 module_tree::ModuleId,
18 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, 18 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId},
19 impl_block::ImplId,
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
@@ -51,7 +52,7 @@ pub enum Def {
51 52
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 53#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53pub struct Module { 54pub struct Module {
54 pub(crate) krate: CrateId, 55 pub(crate) krate: Crate,
55 pub(crate) module_id: ModuleId, 56 pub(crate) module_id: ModuleId,
56} 57}
57 58
@@ -126,9 +127,14 @@ impl Module {
126 self.import_source_impl(db, import) 127 self.import_source_impl(db, import)
127 } 128 }
128 129
130 /// Returns the syntax of the impl block in this module
131 pub fn impl_source(&self, db: &impl HirDatabase, impl_id: ImplId) -> TreeArc<ast::ImplBlock> {
132 self.impl_source_impl(db, impl_id)
133 }
134
129 /// Returns the crate this module is part of. 135 /// Returns the crate this module is part of.
130 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { 136 pub fn krate(&self, _db: &impl HirDatabase) -> Option<Crate> {
131 self.krate_impl(db) 137 Some(self.krate)
132 } 138 }
133 139
134 /// Topmost parent of this module. Every module has a `crate_root`, but some 140 /// Topmost parent of this module. Every module has a `crate_root`, but some
@@ -272,6 +278,10 @@ impl Struct {
272 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 278 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
273 db.generic_params((*self).into()) 279 db.generic_params((*self).into())
274 } 280 }
281
282 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
283 db.type_for_def((*self).into())
284 }
275} 285}
276 286
277impl Docs for Struct { 287impl Docs for Struct {
@@ -317,6 +327,10 @@ impl Enum {
317 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 327 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
318 db.generic_params((*self).into()) 328 db.generic_params((*self).into())
319 } 329 }
330
331 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
332 db.type_for_def((*self).into())
333 }
320} 334}
321 335
322impl Docs for Enum { 336impl Docs for Enum {
@@ -382,7 +396,7 @@ pub struct Function {
382 pub(crate) id: FunctionId, 396 pub(crate) id: FunctionId,
383} 397}
384 398
385pub use crate::code_model_impl::function::ScopeEntryWithSyntax; 399pub use crate::expr::ScopeEntryWithSyntax;
386 400
387/// The declared signature of a function. 401/// The declared signature of a function.
388#[derive(Debug, Clone, PartialEq, Eq)] 402#[derive(Debug, Clone, PartialEq, Eq)]
@@ -424,12 +438,16 @@ impl Function {
424 self.id.module(db) 438 self.id.module(db)
425 } 439 }
426 440
441 pub fn name(&self, db: &impl HirDatabase) -> Name {
442 self.signature(db).name.clone()
443 }
444
427 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { 445 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
428 db.body_syntax_mapping(*self) 446 db.body_syntax_mapping(*self)
429 } 447 }
430 448
431 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { 449 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
432 let scopes = db.fn_scopes(*self); 450 let scopes = db.expr_scopes(*self);
433 let syntax_mapping = db.body_syntax_mapping(*self); 451 let syntax_mapping = db.body_syntax_mapping(*self);
434 ScopesWithSyntaxMapping { 452 ScopesWithSyntaxMapping {
435 scopes, 453 scopes,
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index e0dd4d629..422643996 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -1,5 +1,3 @@
1mod scope;
2
3use std::sync::Arc; 1use std::sync::Arc;
4 2
5use ra_syntax::ast::{self, NameOwner}; 3use ra_syntax::ast::{self, NameOwner};
@@ -11,8 +9,6 @@ use crate::{
11 impl_block::ImplBlock, 9 impl_block::ImplBlock,
12}; 10};
13 11
14pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
15
16impl Function { 12impl Function {
17 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { 13 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
18 db.body_hir(*self) 14 db.body_hir(*self)
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs
index cdd30b402..86f29d959 100644
--- a/crates/ra_hir/src/code_model_impl/krate.rs
+++ b/crates/ra_hir/src/code_model_impl/krate.rs
@@ -1,31 +1,28 @@
1use ra_db::CrateId;
2
3use crate::{ 1use crate::{
4 Crate, CrateDependency, AsName, Module, 2 Crate, CrateDependency, AsName, Module,
5 db::HirDatabase, 3 db::HirDatabase,
6}; 4};
7 5
8impl Crate { 6impl Crate {
9 pub(crate) fn new(crate_id: CrateId) -> Crate {
10 Crate { crate_id }
11 }
12 pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> { 7 pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> {
13 let crate_graph = db.crate_graph(); 8 let crate_graph = db.crate_graph();
14 crate_graph 9 crate_graph
15 .dependencies(self.crate_id) 10 .dependencies(self.crate_id)
16 .map(|dep| { 11 .map(|dep| {
17 let krate = Crate::new(dep.crate_id()); 12 let krate = Crate {
13 crate_id: dep.crate_id(),
14 };
18 let name = dep.as_name(); 15 let name = dep.as_name();
19 CrateDependency { krate, name } 16 CrateDependency { krate, name }
20 }) 17 })
21 .collect() 18 .collect()
22 } 19 }
23 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> { 20 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> {
24 let module_tree = db.module_tree(self.crate_id); 21 let module_tree = db.module_tree(*self);
25 let module_id = module_tree.modules().next()?; 22 let module_id = module_tree.modules().next()?;
26 23
27 let module = Module { 24 let module = Module {
28 krate: self.crate_id, 25 krate: *self,
29 module_id, 26 module_id,
30 }; 27 };
31 Some(module) 28 Some(module)
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 418d59c91..4a3901b8b 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -3,8 +3,9 @@ use ra_syntax::{ast, SyntaxNode, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Problem, 5 Module, ModuleSource, Problem,
6 Crate, Name, 6 Name,
7 module_tree::ModuleId, 7 module_tree::ModuleId,
8 impl_block::ImplId,
8 nameres::{lower::ImportId}, 9 nameres::{lower::ImportId},
9 db::HirDatabase, 10 db::HirDatabase,
10}; 11};
@@ -51,13 +52,19 @@ impl Module {
51 db: &impl HirDatabase, 52 db: &impl HirDatabase,
52 import: ImportId, 53 import: ImportId,
53 ) -> TreeArc<ast::PathSegment> { 54 ) -> TreeArc<ast::PathSegment> {
54 let source_map = db.lower_module_source_map(self.clone()); 55 let source_map = db.lower_module_source_map(*self);
55 let (_, source) = self.definition_source(db); 56 let (_, source) = self.definition_source(db);
56 source_map.get(&source, import) 57 source_map.get(&source, import)
57 } 58 }
58 59
59 pub(crate) fn krate_impl(&self, _db: &impl HirDatabase) -> Option<Crate> { 60 pub(crate) fn impl_source_impl(
60 Some(Crate::new(self.krate)) 61 &self,
62 db: &impl HirDatabase,
63 impl_id: ImplId,
64 ) -> TreeArc<ast::ImplBlock> {
65 let source_map = db.impls_in_module_source_map(*self);
66 let (_, source) = self.definition_source(db);
67 source_map.get(&source, impl_id)
61 } 68 }
62 69
63 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { 70 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 3f76b769d..189649841 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,20 +1,20 @@
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::{SourceDatabase, CrateId, salsa}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
7 MacroCallId, HirFileId, 7 MacroCallId, HirFileId,
8 SourceFileItems, SourceItemId, Crate, Module, HirInterner, 8 SourceFileItems, SourceItemId, Crate, Module, HirInterner,
9 query_definitions, 9 query_definitions,
10 Function, FnSignature, FnScopes, 10 Function, FnSignature, ExprScopes,
11 Struct, Enum, StructField, 11 Struct, Enum, StructField,
12 macros::MacroExpansion, 12 macros::MacroExpansion,
13 module_tree::ModuleTree, 13 module_tree::ModuleTree,
14 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, 14 nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
15 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, 15 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef},
16 adt::{StructData, EnumData}, 16 adt::{StructData, EnumData},
17 impl_block::ModuleImplBlocks, 17 impl_block::{ModuleImplBlocks, ImplSourceMap},
18 generics::{GenericParams, GenericDef}, 18 generics::{GenericParams, GenericDef},
19 ids::SourceFileItemId, 19 ids::SourceFileItemId,
20}; 20};
@@ -27,8 +27,8 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> {
27 #[salsa::invoke(crate::macros::expand_macro_invocation)] 27 #[salsa::invoke(crate::macros::expand_macro_invocation)]
28 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; 28 fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
29 29
30 #[salsa::invoke(query_definitions::fn_scopes)] 30 #[salsa::invoke(ExprScopes::expr_scopes_query)]
31 fn fn_scopes(&self, func: Function) -> Arc<FnScopes>; 31 fn expr_scopes(&self, func: Function) -> Arc<ExprScopes>;
32 32
33 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 33 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
34 fn struct_data(&self, s: Struct) -> Arc<StructData>; 34 fn struct_data(&self, s: Struct) -> Arc<StructData>;
@@ -67,15 +67,24 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> {
67 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] 67 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)]
68 fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>; 68 fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>;
69 69
70 #[salsa::invoke(query_definitions::item_map)] 70 #[salsa::invoke(crate::nameres::ItemMap::item_map_query)]
71 fn item_map(&self, crate_id: CrateId) -> Arc<ItemMap>; 71 fn item_map(&self, krate: Crate) -> Arc<ItemMap>;
72 72
73 #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] 73 #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)]
74 fn module_tree(&self, crate_id: CrateId) -> Arc<ModuleTree>; 74 fn module_tree(&self, krate: Crate) -> Arc<ModuleTree>;
75
76 #[salsa::invoke(crate::impl_block::impls_in_module_with_source_map_query)]
77 fn impls_in_module_with_source_map(
78 &self,
79 module: Module,
80 ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>);
75 81
76 #[salsa::invoke(crate::impl_block::impls_in_module)] 82 #[salsa::invoke(crate::impl_block::impls_in_module)]
77 fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; 83 fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>;
78 84
85 #[salsa::invoke(crate::impl_block::impls_in_module_source_map_query)]
86 fn impls_in_module_source_map(&self, module: Module) -> Arc<ImplSourceMap>;
87
79 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 88 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
80 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 89 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
81 90
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index f2d9af2ba..37aa24677 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -16,6 +16,10 @@ use crate::{
16}; 16};
17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; 17use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
20
21mod scope;
22
19#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct ExprId(RawId); 24pub struct ExprId(RawId);
21impl_arena_id!(ExprId); 25impl_arena_id!(ExprId);
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/expr/scope.rs
index c5d1de5eb..f8b5ba581 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -9,14 +9,18 @@ use ra_syntax::{
9}; 9};
10use ra_arena::{Arena, RawId, impl_arena_id}; 10use ra_arena::{Arena, RawId, impl_arena_id};
11 11
12use crate::{Name, AsName, expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}}; 12use crate::{
13 Name, AsName, Function,
14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping},
15 db::HirDatabase,
16};
13 17
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub struct ScopeId(RawId); 19pub struct ScopeId(RawId);
16impl_arena_id!(ScopeId); 20impl_arena_id!(ScopeId);
17 21
18#[derive(Debug, PartialEq, Eq)] 22#[derive(Debug, PartialEq, Eq)]
19pub struct FnScopes { 23pub struct ExprScopes {
20 body: Arc<Body>, 24 body: Arc<Body>,
21 scopes: Arena<ScopeId, ScopeData>, 25 scopes: Arena<ScopeId, ScopeData>,
22 scope_for: FxHashMap<ExprId, ScopeId>, 26 scope_for: FxHashMap<ExprId, ScopeId>,
@@ -34,9 +38,16 @@ pub struct ScopeData {
34 entries: Vec<ScopeEntry>, 38 entries: Vec<ScopeEntry>,
35} 39}
36 40
37impl FnScopes { 41impl ExprScopes {
38 pub(crate) fn new(body: Arc<Body>) -> FnScopes { 42 // TODO: This should take something more general than Function
39 let mut scopes = FnScopes { 43 pub(crate) fn expr_scopes_query(db: &impl HirDatabase, function: Function) -> Arc<ExprScopes> {
44 let body = db.body_hir(function);
45 let res = ExprScopes::new(body);
46 Arc::new(res)
47 }
48
49 fn new(body: Arc<Body>) -> ExprScopes {
50 let mut scopes = ExprScopes {
40 body: body.clone(), 51 body: body.clone(),
41 scopes: Arena::default(), 52 scopes: Arena::default(),
42 scope_for: FxHashMap::default(), 53 scope_for: FxHashMap::default(),
@@ -119,7 +130,7 @@ impl FnScopes {
119#[derive(Debug, Clone, PartialEq, Eq)] 130#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct ScopesWithSyntaxMapping { 131pub struct ScopesWithSyntaxMapping {
121 pub syntax_mapping: Arc<BodySyntaxMapping>, 132 pub syntax_mapping: Arc<BodySyntaxMapping>,
122 pub scopes: Arc<FnScopes>, 133 pub scopes: Arc<ExprScopes>,
123} 134}
124 135
125#[derive(Debug, Clone, PartialEq, Eq)] 136#[derive(Debug, Clone, PartialEq, Eq)]
@@ -249,7 +260,7 @@ fn compute_block_scopes(
249 statements: &[Statement], 260 statements: &[Statement],
250 tail: Option<ExprId>, 261 tail: Option<ExprId>,
251 body: &Body, 262 body: &Body,
252 scopes: &mut FnScopes, 263 scopes: &mut ExprScopes,
253 mut scope: ScopeId, 264 mut scope: ScopeId,
254) { 265) {
255 for stmt in statements { 266 for stmt in statements {
@@ -275,7 +286,7 @@ fn compute_block_scopes(
275 } 286 }
276} 287}
277 288
278fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut FnScopes, scope: ScopeId) { 289fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
279 scopes.set_scope(expr, scope); 290 scopes.set_scope(expr, scope);
280 match &body[expr] { 291 match &body[expr] {
281 Expr::Block { statements, tail } => { 292 Expr::Block { statements, tail } => {
@@ -344,7 +355,7 @@ mod tests {
344 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 355 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
345 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 356 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
346 let body_hir = expr::collect_fn_body_syntax(fn_def); 357 let body_hir = expr::collect_fn_body_syntax(fn_def);
347 let scopes = FnScopes::new(Arc::clone(body_hir.body())); 358 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
348 let scopes = ScopesWithSyntaxMapping { 359 let scopes = ScopesWithSyntaxMapping {
349 scopes: Arc::new(scopes), 360 scopes: Arc::new(scopes),
350 syntax_mapping: Arc::new(body_hir), 361 syntax_mapping: Arc::new(body_hir),
@@ -444,7 +455,7 @@ mod tests {
444 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 455 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
445 456
446 let body_hir = expr::collect_fn_body_syntax(fn_def); 457 let body_hir = expr::collect_fn_body_syntax(fn_def);
447 let scopes = FnScopes::new(Arc::clone(body_hir.body())); 458 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
448 let scopes = ScopesWithSyntaxMapping { 459 let scopes = ScopesWithSyntaxMapping {
449 scopes: Arc::new(scopes), 460 scopes: Arc::new(scopes),
450 syntax_mapping: Arc::new(body_hir), 461 syntax_mapping: Arc::new(body_hir),
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 222e47349..5fc26324a 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -1,8 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
3 3
4use ra_arena::{Arena, RawId, impl_arena_id}; 4use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::{
6 AstPtr, SourceFile, TreeArc,
7ast::{self, AstNode}};
6 8
7use crate::{ 9use crate::{
8 Const, Type, 10 Const, Type,
@@ -14,6 +16,26 @@ use crate::{
14 16
15use crate::code_model_api::{Module, ModuleSource}; 17use crate::code_model_api::{Module, ModuleSource};
16 18
19#[derive(Debug, Default, PartialEq, Eq)]
20pub struct ImplSourceMap {
21 map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
22}
23
24impl ImplSourceMap {
25 fn insert(&mut self, impl_id: ImplId, impl_block: &ast::ImplBlock) {
26 self.map.insert(impl_id, AstPtr::new(impl_block))
27 }
28
29 pub fn get(&self, source: &ModuleSource, impl_id: ImplId) -> TreeArc<ast::ImplBlock> {
30 let file = match source {
31 ModuleSource::SourceFile(file) => &*file,
32 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
33 };
34
35 self.map[impl_id].to_node(file).to_owned()
36 }
37}
38
17#[derive(Debug, Clone, PartialEq, Eq)] 39#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct ImplBlock { 40pub struct ImplBlock {
19 module_impl_blocks: Arc<ModuleImplBlocks>, 41 module_impl_blocks: Arc<ModuleImplBlocks>,
@@ -39,6 +61,10 @@ impl ImplBlock {
39 } 61 }
40 } 62 }
41 63
64 pub fn id(&self) -> ImplId {
65 self.impl_id
66 }
67
42 fn impl_data(&self) -> &ImplData { 68 fn impl_data(&self) -> &ImplData {
43 &self.module_impl_blocks.impls[self.impl_id] 69 &self.module_impl_blocks.impls[self.impl_id]
44 } 70 }
@@ -148,7 +174,7 @@ impl ModuleImplBlocks {
148 } 174 }
149 } 175 }
150 176
151 fn collect(&mut self, db: &impl HirDatabase, module: Module) { 177 fn collect(&mut self, db: &impl HirDatabase, module: Module, source_map: &mut ImplSourceMap) {
152 let (file_id, module_source) = module.definition_source(db); 178 let (file_id, module_source) = module.definition_source(db);
153 let file_id: HirFileId = file_id.into(); 179 let file_id: HirFileId = file_id.into();
154 let node = match &module_source { 180 let node = match &module_source {
@@ -165,12 +191,31 @@ impl ModuleImplBlocks {
165 for &impl_item in &self.impls[id].items { 191 for &impl_item in &self.impls[id].items {
166 self.impls_by_def.insert(impl_item, id); 192 self.impls_by_def.insert(impl_item, id);
167 } 193 }
194
195 source_map.insert(id, impl_block_ast);
168 } 196 }
169 } 197 }
170} 198}
171 199
172pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> { 200pub(crate) fn impls_in_module_with_source_map_query(
201 db: &impl HirDatabase,
202 module: Module,
203) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
204 let mut source_map = ImplSourceMap::default();
205
173 let mut result = ModuleImplBlocks::new(); 206 let mut result = ModuleImplBlocks::new();
174 result.collect(db, module); 207 result.collect(db, module, &mut source_map);
175 Arc::new(result) 208
209 (Arc::new(result), Arc::new(source_map))
210}
211
212pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> {
213 db.impls_in_module_with_source_map(module).0
214}
215
216pub(crate) fn impls_in_module_source_map_query(
217 db: &impl HirDatabase,
218 module: Module,
219) -> Arc<ImplSourceMap> {
220 db.impls_in_module_with_source_map(module).1
176} 221}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index eaf8565ee..0b9ee63bf 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -57,9 +57,9 @@ pub use self::{
57 nameres::{ItemMap, PerNs, Namespace, Resolution}, 57 nameres::{ItemMap, PerNs, Namespace, Resolution},
58 ty::Ty, 58 ty::Ty,
59 impl_block::{ImplBlock, ImplItem}, 59 impl_block::{ImplBlock, ImplItem},
60 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
61 docs::{Docs, Documentation}, 60 docs::{Docs, Documentation},
62 adt::AdtDef, 61 adt::AdtDef,
62 expr::{ExprScopes, ScopesWithSyntaxMapping},
63}; 63};
64 64
65pub use self::code_model_api::{ 65pub use self::code_model_api::{
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index 893c375b5..1f327eeb2 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
2 2
3use arrayvec::ArrayVec; 3use arrayvec::ArrayVec;
4use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
5use ra_db::{FileId, SourceRoot, CrateId}; 5use ra_db::{FileId, SourceRoot};
6use ra_syntax::{ 6use ra_syntax::{
7 SyntaxNode, TreeArc, 7 SyntaxNode, TreeArc,
8 algo::generate, 8 algo::generate,
@@ -13,6 +13,7 @@ use test_utils::tested_by;
13 13
14use crate::{ 14use crate::{
15 Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, 15 Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource,
16 Crate,
16 ids::SourceFileItemId, 17 ids::SourceFileItemId,
17}; 18};
18 19
@@ -132,10 +133,10 @@ struct LinkData {
132} 133}
133 134
134impl ModuleTree { 135impl ModuleTree {
135 pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ModuleTree> { 136 pub(crate) fn module_tree_query(db: &impl HirDatabase, krate: Crate) -> Arc<ModuleTree> {
136 db.check_canceled(); 137 db.check_canceled();
137 let mut res = ModuleTree::default(); 138 let mut res = ModuleTree::default();
138 res.init_crate(db, crate_id); 139 res.init_crate(db, krate);
139 Arc::new(res) 140 Arc::new(res)
140 } 141 }
141 142
@@ -155,9 +156,9 @@ impl ModuleTree {
155 Some(res) 156 Some(res)
156 } 157 }
157 158
158 fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) { 159 fn init_crate(&mut self, db: &impl HirDatabase, krate: Crate) {
159 let crate_graph = db.crate_graph(); 160 let crate_graph = db.crate_graph();
160 let file_id = crate_graph.crate_root(crate_id); 161 let file_id = crate_graph.crate_root(krate.crate_id);
161 let source_root_id = db.file_source_root(file_id); 162 let source_root_id = db.file_source_root(file_id);
162 163
163 let source_root = db.source_root(source_root_id); 164 let source_root = db.source_root(source_root_id);
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 97ce6c946..4573a72ba 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -16,9 +16,8 @@
16//! structure itself is modified. 16//! structure itself is modified.
17pub(crate) mod lower; 17pub(crate) mod lower;
18 18
19use std::sync::Arc; 19use std::{time, sync::Arc};
20 20
21use ra_db::CrateId;
22use ra_arena::map::ArenaMap; 21use ra_arena::map::ArenaMap;
23use test_utils::tested_by; 22use test_utils::tested_by;
24use rustc_hash::{FxHashMap, FxHashSet}; 23use rustc_hash::{FxHashMap, FxHashSet};
@@ -156,10 +155,10 @@ impl<T> PerNs<T> {
156 } 155 }
157} 156}
158 157
159pub(crate) struct Resolver<'a, DB> { 158struct Resolver<'a, DB> {
160 db: &'a DB, 159 db: &'a DB,
161 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, 160 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
162 krate: CrateId, 161 krate: Crate,
163 module_tree: Arc<ModuleTree>, 162 module_tree: Arc<ModuleTree>,
164 processed_imports: FxHashSet<(ModuleId, ImportId)>, 163 processed_imports: FxHashSet<(ModuleId, ImportId)>,
165 result: ItemMap, 164 result: ItemMap,
@@ -169,10 +168,10 @@ impl<'a, DB> Resolver<'a, DB>
169where 168where
170 DB: HirDatabase, 169 DB: HirDatabase,
171{ 170{
172 pub(crate) fn new( 171 fn new(
173 db: &'a DB, 172 db: &'a DB,
174 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, 173 input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>,
175 krate: CrateId, 174 krate: Crate,
176 ) -> Resolver<'a, DB> { 175 ) -> Resolver<'a, DB> {
177 let module_tree = db.module_tree(krate); 176 let module_tree = db.module_tree(krate);
178 Resolver { 177 Resolver {
@@ -219,7 +218,7 @@ where
219 let crate_graph = self.db.crate_graph(); 218 let crate_graph = self.db.crate_graph();
220 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) 219 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file())
221 { 220 {
222 let krate = Crate::new(crate_id); 221 let krate = Crate { crate_id };
223 for dep in krate.dependencies(self.db) { 222 for dep in krate.dependencies(self.db) {
224 if let Some(module) = dep.krate.root_module(self.db) { 223 if let Some(module) = dep.krate.root_module(self.db) {
225 let def = module.into(); 224 let def = module.into();
@@ -331,6 +330,26 @@ enum ReachedFixedPoint {
331} 330}
332 331
333impl ItemMap { 332impl ItemMap {
333 pub(crate) fn item_map_query(db: &impl HirDatabase, krate: Crate) -> Arc<ItemMap> {
334 let start = time::Instant::now();
335 let module_tree = db.module_tree(krate);
336 let input = module_tree
337 .modules()
338 .map(|module_id| {
339 (
340 module_id,
341 db.lower_module_module(Module { krate, module_id }),
342 )
343 })
344 .collect::<FxHashMap<_, _>>();
345
346 let resolver = Resolver::new(db, &input, krate);
347 let res = resolver.resolve();
348 let elapsed = start.elapsed();
349 log::info!("item_map: {:?}", elapsed);
350 Arc::new(res)
351 }
352
334 pub(crate) fn resolve_path( 353 pub(crate) fn resolve_path(
335 &self, 354 &self,
336 db: &impl HirDatabase, 355 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 3d420467c..9c5ca097e 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -16,7 +16,7 @@ fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
16 let module = crate::source_binder::module_from_position(&db, pos).unwrap(); 16 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
17 let krate = module.krate(&db).unwrap(); 17 let krate = module.krate(&db).unwrap();
18 let module_id = module.module_id; 18 let module_id = module.module_id;
19 (db.item_map(krate.crate_id), module_id) 19 (db.item_map(krate), module_id)
20} 20}
21 21
22/// Sets the crate root to the file of the cursor marker 22/// Sets the crate root to the file of the cursor marker
@@ -30,7 +30,7 @@ fn item_map_custom_crate_root(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
30 let module = crate::source_binder::module_from_position(&db, pos).unwrap(); 30 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
31 let krate = module.krate(&db).unwrap(); 31 let krate = module.krate(&db).unwrap();
32 let module_id = module.module_id; 32 let module_id = module.module_id;
33 (db.item_map(krate.crate_id), module_id) 33 (db.item_map(krate), module_id)
34} 34}
35 35
36fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { 36fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
@@ -297,7 +297,7 @@ fn item_map_across_crates() {
297 297
298 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 298 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
299 let krate = module.krate(&db).unwrap(); 299 let krate = module.krate(&db).unwrap();
300 let item_map = db.item_map(krate.crate_id); 300 let item_map = db.item_map(krate);
301 301
302 check_module_item_map( 302 check_module_item_map(
303 &item_map, 303 &item_map,
@@ -349,7 +349,7 @@ fn import_across_source_roots() {
349 349
350 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 350 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
351 let krate = module.krate(&db).unwrap(); 351 let krate = module.krate(&db).unwrap();
352 let item_map = db.item_map(krate.crate_id); 352 let item_map = db.item_map(krate);
353 353
354 check_module_item_map( 354 check_module_item_map(
355 &item_map, 355 &item_map,
@@ -391,7 +391,7 @@ fn reexport_across_crates() {
391 391
392 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); 392 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
393 let krate = module.krate(&db).unwrap(); 393 let krate = module.krate(&db).unwrap();
394 let item_map = db.item_map(krate.crate_id); 394 let item_map = db.item_map(krate);
395 395
396 check_module_item_map( 396 check_module_item_map(
397 &item_map, 397 &item_map,
@@ -409,7 +409,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
409 let krate = module.krate(&db).unwrap(); 409 let krate = module.krate(&db).unwrap();
410 { 410 {
411 let events = db.log_executed(|| { 411 let events = db.log_executed(|| {
412 db.item_map(krate.crate_id); 412 db.item_map(krate);
413 }); 413 });
414 assert!(format!("{:?}", events).contains("item_map")) 414 assert!(format!("{:?}", events).contains("item_map"))
415 } 415 }
@@ -417,7 +417,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
417 417
418 { 418 {
419 let events = db.log_executed(|| { 419 let events = db.log_executed(|| {
420 db.item_map(krate.crate_id); 420 db.item_map(krate);
421 }); 421 });
422 assert!( 422 assert!(
423 !format!("{:?}", events).contains("item_map"), 423 !format!("{:?}", events).contains("item_map"),
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index bf9ac0dfb..734a98282 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -1,25 +1,14 @@
1use std::{ 1use std::sync::Arc;
2 sync::Arc,
3 time::Instant,
4};
5 2
6use rustc_hash::FxHashMap; 3use ra_syntax::{
7use ra_syntax::{SyntaxNode, TreeArc}; 4 SyntaxNode, TreeArc,
8use ra_db::{CrateId}; 5};
9 6
10use crate::{ 7use crate::{
11 SourceFileItems, SourceItemId, HirFileId, 8 SourceFileItems, SourceItemId, HirFileId,
12 Function, FnScopes, Module,
13 db::HirDatabase, 9 db::HirDatabase,
14 nameres::{ItemMap, Resolver},
15}; 10};
16 11
17pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> {
18 let body = db.body_hir(func);
19 let res = FnScopes::new(body);
20 Arc::new(res)
21}
22
23pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { 12pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> {
24 let source_file = db.hir_parse(file_id); 13 let source_file = db.hir_parse(file_id);
25 let res = SourceFileItems::new(file_id, &source_file); 14 let res = SourceFileItems::new(file_id, &source_file);
@@ -35,26 +24,3 @@ pub(super) fn file_item(
35 .to_node(&source_file) 24 .to_node(&source_file)
36 .to_owned() 25 .to_owned()
37} 26}
38
39pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> {
40 let start = Instant::now();
41 let module_tree = db.module_tree(crate_id);
42 let input = module_tree
43 .modules()
44 .map(|module_id| {
45 (
46 module_id,
47 db.lower_module_module(Module {
48 krate: crate_id,
49 module_id,
50 }),
51 )
52 })
53 .collect::<FxHashMap<_, _>>();
54
55 let resolver = Resolver::new(db, &input, crate_id);
56 let res = resolver.resolve();
57 let elapsed = start.elapsed();
58 log::info!("item_map: {:?}", elapsed);
59 Arc::new(res)
60}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index f523f0647..d1eaccf23 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,8 +13,8 @@ use ra_syntax::{
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, ModuleDef, 16 HirDatabase, Function, ModuleDef, Struct, Enum,
17 AsName, Module, HirFileId, 17 AsName, Module, HirFileId, Crate,
18 ids::{LocationCtx, SourceFileItemId}, 18 ids::{LocationCtx, SourceFileItemId},
19}; 19};
20 20
@@ -83,7 +83,8 @@ fn module_from_source(
83 let source_root_id = db.file_source_root(file_id.as_original_file()); 83 let source_root_id = db.file_source_root(file_id.as_original_file());
84 db.source_root_crates(source_root_id) 84 db.source_root_crates(source_root_id)
85 .iter() 85 .iter()
86 .find_map(|&krate| { 86 .map(|&crate_id| Crate { crate_id })
87 .find_map(|krate| {
87 let module_tree = db.module_tree(krate); 88 let module_tree = db.module_tree(krate);
88 let module_id = module_tree.find_module_by_source(file_id, decl_id)?; 89 let module_id = module_tree.find_module_by_source(file_id, decl_id)?;
89 Some(Module { krate, module_id }) 90 Some(Module { krate, module_id })
@@ -128,6 +129,28 @@ pub fn function_from_child_node(
128 function_from_source(db, file_id, fn_def) 129 function_from_source(db, file_id, fn_def)
129} 130}
130 131
132pub fn struct_from_module(
133 db: &impl HirDatabase,
134 module: Module,
135 struct_def: &ast::StructDef,
136) -> Struct {
137 let (file_id, _) = module.definition_source(db);
138 let file_id = file_id.into();
139 let ctx = LocationCtx::new(db, module, file_id);
140 Struct {
141 id: ctx.to_def(struct_def),
142 }
143}
144
145pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
146 let (file_id, _) = module.definition_source(db);
147 let file_id = file_id.into();
148 let ctx = LocationCtx::new(db, module, file_id);
149 Enum {
150 id: ctx.to_def(enum_def),
151 }
152}
153
131pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { 154pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> {
132 let module = match module_from_file_id(db, file_id) { 155 let module = match module_from_file_id(db, file_id) {
133 Some(it) => it, 156 Some(it) => it,
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index e2c7884b5..60c231e82 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -20,6 +20,7 @@ mod tests;
20pub(crate) mod method_resolution; 20pub(crate) mod method_resolution;
21 21
22use std::borrow::Cow; 22use std::borrow::Cow;
23use std::iter::repeat;
23use std::ops::Index; 24use std::ops::Index;
24use std::sync::Arc; 25use std::sync::Arc;
25use std::{fmt, mem}; 26use std::{fmt, mem};
@@ -33,7 +34,7 @@ use test_utils::tested_by;
33 34
34use crate::{ 35use crate::{
35 Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, 36 Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock,
36 FnSignature, FnScopes, ModuleDef, AdtDef, 37 FnSignature, ExprScopes, ModuleDef, AdtDef,
37 db::HirDatabase, 38 db::HirDatabase,
38 type_ref::{TypeRef, Mutability}, 39 type_ref::{TypeRef, Mutability},
39 name::KnownName, 40 name::KnownName,
@@ -185,7 +186,7 @@ pub enum Ty {
185 186
186 /// Structures, enumerations and unions. 187 /// Structures, enumerations and unions.
187 Adt { 188 Adt {
188 /// The DefId of the struct/enum. 189 /// The definition of the struct/enum.
189 def_id: AdtDef, 190 def_id: AdtDef,
190 /// The name, for displaying. 191 /// The name, for displaying.
191 name: Name, 192 name: Name,
@@ -209,6 +210,27 @@ pub enum Ty {
209 /// `&'a mut T` or `&'a T`. 210 /// `&'a mut T` or `&'a T`.
210 Ref(Arc<Ty>, Mutability), 211 Ref(Arc<Ty>, Mutability),
211 212
213 /// The anonymous type of a function declaration/definition. Each
214 /// function has a unique type, which is output (for a function
215 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
216 ///
217 /// For example the type of `bar` here:
218 ///
219 /// ```rust
220 /// fn foo() -> i32 { 1 }
221 /// let bar = foo; // bar: fn() -> i32 {foo}
222 /// ```
223 FnDef {
224 // Function definition
225 def: Function,
226 /// For display
227 name: Name,
228 /// Parameters and return type
229 sig: Arc<FnSig>,
230 /// Substitutions for the generic parameters of the type
231 substs: Substs,
232 },
233
212 /// A pointer to a function. Written as `fn() -> i32`. 234 /// A pointer to a function. Written as `fn() -> i32`.
213 /// 235 ///
214 /// For example the type of `bar` here: 236 /// For example the type of `bar` here:
@@ -448,12 +470,12 @@ impl Ty {
448 } 470 }
449 // add placeholders for args that were not provided 471 // add placeholders for args that were not provided
450 // TODO: handle defaults 472 // TODO: handle defaults
451 for _ in segment 473 let supplied_params = segment
452 .args_and_bindings 474 .args_and_bindings
453 .as_ref() 475 .as_ref()
454 .map(|ga| ga.args.len()) 476 .map(|ga| ga.args.len())
455 .unwrap_or(0)..def_generics.params.len() 477 .unwrap_or(0);
456 { 478 for _ in supplied_params..def_generics.params.len() {
457 substs.push(Ty::Unknown); 479 substs.push(Ty::Unknown);
458 } 480 }
459 assert_eq!(substs.len(), def_generics.params.len()); 481 assert_eq!(substs.len(), def_generics.params.len());
@@ -485,6 +507,19 @@ impl Ty {
485 } 507 }
486 sig_mut.output.walk_mut(f); 508 sig_mut.output.walk_mut(f);
487 } 509 }
510 Ty::FnDef { substs, sig, .. } => {
511 let sig_mut = Arc::make_mut(sig);
512 for input in &mut sig_mut.input {
513 input.walk_mut(f);
514 }
515 sig_mut.output.walk_mut(f);
516 // Without an Arc::make_mut_slice, we can't avoid the clone here:
517 let mut v: Vec<_> = substs.0.iter().cloned().collect();
518 for t in &mut v {
519 t.walk_mut(f);
520 }
521 substs.0 = v.into();
522 }
488 Ty::Adt { substs, .. } => { 523 Ty::Adt { substs, .. } => {
489 // Without an Arc::make_mut_slice, we can't avoid the clone here: 524 // Without an Arc::make_mut_slice, we can't avoid the clone here:
490 let mut v: Vec<_> = substs.0.iter().cloned().collect(); 525 let mut v: Vec<_> = substs.0.iter().cloned().collect();
@@ -524,6 +559,12 @@ impl Ty {
524 name, 559 name,
525 substs, 560 substs,
526 }, 561 },
562 Ty::FnDef { def, name, sig, .. } => Ty::FnDef {
563 def,
564 name,
565 sig,
566 substs,
567 },
527 _ => self, 568 _ => self,
528 } 569 }
529 } 570 }
@@ -551,7 +592,7 @@ impl Ty {
551 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 592 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
552 fn substs(&self) -> Option<Substs> { 593 fn substs(&self) -> Option<Substs> {
553 match self { 594 match self {
554 Ty::Adt { substs, .. } => Some(substs.clone()), 595 Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()),
555 _ => None, 596 _ => None,
556 } 597 }
557 } 598 }
@@ -586,6 +627,22 @@ impl fmt::Display for Ty {
586 .to_fmt(f)?; 627 .to_fmt(f)?;
587 write!(f, " -> {}", sig.output) 628 write!(f, " -> {}", sig.output)
588 } 629 }
630 Ty::FnDef {
631 name, substs, sig, ..
632 } => {
633 write!(f, "fn {}", name)?;
634 if substs.0.len() > 0 {
635 join(substs.0.iter())
636 .surround_with("<", ">")
637 .separator(", ")
638 .to_fmt(f)?;
639 }
640 join(sig.input.iter())
641 .surround_with("(", ")")
642 .separator(", ")
643 .to_fmt(f)?;
644 write!(f, " -> {}", sig.output)
645 }
589 Ty::Adt { name, substs, .. } => { 646 Ty::Adt { name, substs, .. } => {
590 write!(f, "{}", name)?; 647 write!(f, "{}", name)?;
591 if substs.0.len() > 0 { 648 if substs.0.len() > 0 {
@@ -607,11 +664,11 @@ impl fmt::Display for Ty {
607 664
608/// Compute the declared type of a function. This should not need to look at the 665/// Compute the declared type of a function. This should not need to look at the
609/// function body. 666/// function body.
610fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { 667fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
611 let signature = f.signature(db); 668 let signature = def.signature(db);
612 let module = f.module(db); 669 let module = def.module(db);
613 let impl_block = f.impl_block(db); 670 let impl_block = def.impl_block(db);
614 let generics = f.generic_params(db); 671 let generics = def.generic_params(db);
615 let input = signature 672 let input = signature
616 .params() 673 .params()
617 .iter() 674 .iter()
@@ -624,8 +681,15 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
624 &generics, 681 &generics,
625 signature.ret_type(), 682 signature.ret_type(),
626 ); 683 );
627 let sig = FnSig { input, output }; 684 let sig = Arc::new(FnSig { input, output });
628 Ty::FnPtr(Arc::new(sig)) 685 let substs = make_substs(&generics);
686 let name = def.name(db);
687 Ty::FnDef {
688 def,
689 sig,
690 name,
691 substs,
692 }
629} 693}
630 694
631fn make_substs(generics: &GenericParams) -> Substs { 695fn make_substs(generics: &GenericParams) -> Substs {
@@ -750,7 +814,7 @@ impl Index<PatId> for InferenceResult {
750struct InferenceContext<'a, D: HirDatabase> { 814struct InferenceContext<'a, D: HirDatabase> {
751 db: &'a D, 815 db: &'a D,
752 body: Arc<Body>, 816 body: Arc<Body>,
753 scopes: Arc<FnScopes>, 817 scopes: Arc<ExprScopes>,
754 module: Module, 818 module: Module,
755 impl_block: Option<ImplBlock>, 819 impl_block: Option<ImplBlock>,
756 var_unification_table: InPlaceUnificationTable<TypeVarId>, 820 var_unification_table: InPlaceUnificationTable<TypeVarId>,
@@ -844,7 +908,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
844 fn new( 908 fn new(
845 db: &'a D, 909 db: &'a D,
846 body: Arc<Body>, 910 body: Arc<Body>,
847 scopes: Arc<FnScopes>, 911 scopes: Arc<ExprScopes>,
848 module: Module, 912 module: Module,
849 impl_block: Option<ImplBlock>, 913 impl_block: Option<ImplBlock>,
850 ) -> Self { 914 ) -> Self {
@@ -1102,7 +1166,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1102 .into(); 1166 .into();
1103 let typable = typable?; 1167 let typable = typable?;
1104 let ty = self.db.type_for_def(typable); 1168 let ty = self.db.type_for_def(typable);
1169 let generics = GenericParams::default();
1170 let substs = Ty::substs_from_path(
1171 self.db,
1172 &self.module,
1173 self.impl_block.as_ref(),
1174 &generics,
1175 path,
1176 typable,
1177 );
1178 let ty = ty.apply_substs(substs);
1105 let ty = self.insert_type_vars(ty); 1179 let ty = self.insert_type_vars(ty);
1180
1106 Some(ty) 1181 Some(ty)
1107 } 1182 }
1108 1183
@@ -1142,7 +1217,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1142 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1217 let ty = self.insert_type_vars(ty.apply_substs(substs));
1143 (ty, Some(var.into())) 1218 (ty, Some(var.into()))
1144 } 1219 }
1145 TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), 1220 TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None),
1146 } 1221 }
1147 } 1222 }
1148 1223
@@ -1196,9 +1271,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1196 Ty::Tuple(ref tuple_args) => &**tuple_args, 1271 Ty::Tuple(ref tuple_args) => &**tuple_args,
1197 _ => &[], 1272 _ => &[],
1198 }; 1273 };
1199 let expectations_iter = expectations 1274 let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown));
1200 .into_iter()
1201 .chain(std::iter::repeat(&Ty::Unknown));
1202 1275
1203 let inner_tys = args 1276 let inner_tys = args
1204 .iter() 1277 .iter()
@@ -1332,18 +1405,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1332 Expr::Call { callee, args } => { 1405 Expr::Call { callee, args } => {
1333 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 1406 let callee_ty = self.infer_expr(*callee, &Expectation::none());
1334 let (param_tys, ret_ty) = match &callee_ty { 1407 let (param_tys, ret_ty) = match &callee_ty {
1335 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), 1408 Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
1409 Ty::FnDef { substs, sig, .. } => {
1410 let ret_ty = sig.output.clone().subst(&substs);
1411 let param_tys = sig
1412 .input
1413 .iter()
1414 .map(|ty| ty.clone().subst(&substs))
1415 .collect();
1416 (param_tys, ret_ty)
1417 }
1336 _ => { 1418 _ => {
1337 // not callable 1419 // not callable
1338 // TODO report an error? 1420 // TODO report an error?
1339 (&[][..], Ty::Unknown) 1421 (Vec::new(), Ty::Unknown)
1340 } 1422 }
1341 }; 1423 };
1342 for (i, arg) in args.iter().enumerate() { 1424 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1343 self.infer_expr( 1425 for (arg, param) in args.iter().zip(param_iter) {
1344 *arg, 1426 self.infer_expr(*arg, &Expectation::has_type(param));
1345 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
1346 );
1347 } 1427 }
1348 ret_ty 1428 ret_ty
1349 } 1429 }
@@ -1365,21 +1445,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1365 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1445 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
1366 Ty::FnPtr(sig) => { 1446 Ty::FnPtr(sig) => {
1367 if sig.input.len() > 0 { 1447 if sig.input.len() > 0 {
1368 (&sig.input[0], &sig.input[1..], sig.output.clone()) 1448 (
1449 sig.input[0].clone(),
1450 sig.input[1..].iter().cloned().collect(),
1451 sig.output.clone(),
1452 )
1453 } else {
1454 (Ty::Unknown, Vec::new(), sig.output.clone())
1455 }
1456 }
1457 Ty::FnDef { substs, sig, .. } => {
1458 let ret_ty = sig.output.clone().subst(&substs);
1459
1460 if sig.input.len() > 0 {
1461 let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs));
1462 let receiver_ty = arg_iter.next().unwrap();
1463 (receiver_ty, arg_iter.collect(), ret_ty)
1369 } else { 1464 } else {
1370 (&Ty::Unknown, &[][..], sig.output.clone()) 1465 (Ty::Unknown, Vec::new(), ret_ty)
1371 } 1466 }
1372 } 1467 }
1373 _ => (&Ty::Unknown, &[][..], Ty::Unknown), 1468 _ => (Ty::Unknown, Vec::new(), Ty::Unknown),
1374 }; 1469 };
1375 // TODO we would have to apply the autoderef/autoref steps here 1470 // TODO we would have to apply the autoderef/autoref steps here
1376 // to get the correct receiver type to unify... 1471 // to get the correct receiver type to unify...
1377 self.unify(expected_receiver_ty, &receiver_ty); 1472 self.unify(&expected_receiver_ty, &receiver_ty);
1378 for (i, arg) in args.iter().enumerate() { 1473 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1379 self.infer_expr( 1474 for (arg, param) in args.iter().zip(param_iter) {
1380 *arg, 1475 self.infer_expr(*arg, &Expectation::has_type(param));
1381 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
1382 );
1383 } 1476 }
1384 ret_ty 1477 ret_ty
1385 } 1478 }
@@ -1505,9 +1598,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1505 _ => Ty::Unknown, 1598 _ => Ty::Unknown,
1506 } 1599 }
1507 } 1600 }
1508 UnaryOp::Not if inner_ty == Ty::Bool => Ty::Bool, 1601 UnaryOp::Not => {
1509 // TODO: resolve ops::Not trait for inner_ty 1602 match inner_ty {
1510 UnaryOp::Not => Ty::Unknown, 1603 Ty::Bool | Ty::Int(_) | Ty::Infer(InferTy::IntVar(..)) => inner_ty,
1604 // TODO: resolve ops::Not trait for inner_ty
1605 _ => Ty::Unknown,
1606 }
1607 }
1511 } 1608 }
1512 } 1609 }
1513 Expr::BinaryOp { lhs, rhs, op } => match op { 1610 Expr::BinaryOp { lhs, rhs, op } => match op {
@@ -1619,10 +1716,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1619 1716
1620 self.infer_pat(*pat, &ty); 1717 self.infer_pat(*pat, &ty);
1621 } 1718 }
1622 self.return_ty = { 1719 self.return_ty = self.make_ty(signature.ret_type());
1623 let ty = self.make_ty(signature.ret_type());
1624 ty
1625 };
1626 } 1720 }
1627 1721
1628 fn infer_body(&mut self) { 1722 fn infer_body(&mut self) {
@@ -1636,7 +1730,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1636pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 1730pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
1637 db.check_canceled(); 1731 db.check_canceled();
1638 let body = func.body(db); 1732 let body = func.body(db);
1639 let scopes = db.fn_scopes(func); 1733 let scopes = db.expr_scopes(func);
1640 let module = func.module(db); 1734 let module = func.module(db);
1641 let impl_block = func.impl_block(db); 1735 let impl_block = func.impl_block(db);
1642 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1736 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 9a571c2aa..37bc3f38c 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -44,7 +44,7 @@ impl CrateImplBlocks {
44 &'a self, 44 &'a self,
45 db: &'a impl HirDatabase, 45 db: &'a impl HirDatabase,
46 ty: &Ty, 46 ty: &Ty,
47 ) -> impl Iterator<Item = ImplBlock> + 'a { 47 ) -> impl Iterator<Item = (Module, ImplBlock)> + 'a {
48 let fingerprint = TyFingerprint::for_impl(ty); 48 let fingerprint = TyFingerprint::for_impl(ty);
49 fingerprint 49 fingerprint
50 .and_then(|f| self.impls.get(&f)) 50 .and_then(|f| self.impls.get(&f))
@@ -52,11 +52,11 @@ impl CrateImplBlocks {
52 .flat_map(|i| i.iter()) 52 .flat_map(|i| i.iter())
53 .map(move |(module_id, impl_id)| { 53 .map(move |(module_id, impl_id)| {
54 let module = Module { 54 let module = Module {
55 krate: self.krate.crate_id, 55 krate: self.krate,
56 module_id: *module_id, 56 module_id: *module_id,
57 }; 57 };
58 let module_impl_blocks = db.impls_in_module(module); 58 let module_impl_blocks = db.impls_in_module(module);
59 ImplBlock::from_id(module_impl_blocks, *impl_id) 59 (module, ImplBlock::from_id(module_impl_blocks, *impl_id))
60 }) 60 })
61 } 61 }
62 62
@@ -152,7 +152,7 @@ impl Ty {
152 }; 152 };
153 let impls = db.impls_in_crate(krate); 153 let impls = db.impls_in_crate(krate);
154 154
155 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) { 155 for (_, impl_block) in impls.lookup_impl_blocks(db, &derefed_ty) {
156 for item in impl_block.items() { 156 for item in impl_block.items() {
157 match item { 157 match item {
158 ImplItem::Method(f) => { 158 ImplItem::Method(f) => {
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
index 5c74bd8c7..f5840a934 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_backwards.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-26T17:46:03.842478456+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[14; 15) 'x': u32 7[14; 15) 'x': u32
8[22; 24) '{}': () 8[22; 24) '{}': ()
@@ -10,7 +10,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
10[88; 89) 'a': u32 10[88; 89) 'a': u32
11[92; 108) 'unknow...nction': [unknown] 11[92; 108) 'unknow...nction': [unknown]
12[92; 110) 'unknow...tion()': u32 12[92; 110) 'unknow...tion()': u32
13[116; 125) 'takes_u32': fn(u32) -> () 13[116; 125) 'takes_u32': fn takes_u32(u32) -> ()
14[116; 128) 'takes_u32(a)': () 14[116; 128) 'takes_u32(a)': ()
15[126; 127) 'a': u32 15[126; 127) 'a': u32
16[138; 139) 'b': i32 16[138; 139) 'b': i32
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
index c506bcadd..b9dda2bc0 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_binary_op.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-26T17:46:03.853259898+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[6; 7) 'x': bool 7[6; 7) 'x': bool
8[22; 34) '{ 0i32 }': i32 8[22; 34) '{ 0i32 }': i32
@@ -28,7 +28,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
28[174; 196) 'minus_...ONST_2': bool 28[174; 196) 'minus_...ONST_2': bool
29[189; 196) 'CONST_2': isize 29[189; 196) 'CONST_2': isize
30[206; 207) 'c': i32 30[206; 207) 'c': i32
31[210; 211) 'f': fn(bool) -> i32 31[210; 211) 'f': fn f(bool) -> i32
32[210; 219) 'f(z || y)': i32 32[210; 219) 'f(z || y)': i32
33[210; 223) 'f(z || y) + 5': i32 33[210; 223) 'f(z || y) + 5': i32
34[212; 213) 'z': bool 34[212; 213) 'z': bool
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
index 7203ad1e2..8ff6e55a6 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap
@@ -1,21 +1,21 @@
1--- 1---
2created: "2019-01-22T14:44:59.954958500+00:00" 2created: "2019-01-26T18:16:16.530712344+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[10; 11) 't': [unknown] 7[10; 11) 't': [unknown]
8[21; 26) '{ t }': [unknown] 8[21; 26) '{ t }': [unknown]
9[23; 24) 't': [unknown] 9[23; 24) 't': [unknown]
10[38; 98) '{ ...(1); }': () 10[38; 98) '{ ...(1); }': ()
11[44; 46) 'id': fn(T) -> T 11[44; 46) 'id': fn id<u32>(T) -> T
12[44; 52) 'id(1u32)': T 12[44; 52) 'id(1u32)': u32
13[47; 51) '1u32': u32 13[47; 51) '1u32': u32
14[58; 68) 'id::<i128>': fn(T) -> T 14[58; 68) 'id::<i128>': fn id<i128>(T) -> T
15[58; 71) 'id::<i128>(1)': T 15[58; 71) 'id::<i128>(1)': i128
16[69; 70) '1': T 16[69; 70) '1': i128
17[81; 82) 'x': T 17[81; 82) 'x': u64
18[90; 92) 'id': fn(T) -> T 18[90; 92) 'id': fn id<u64>(T) -> T
19[90; 95) 'id(1)': T 19[90; 95) 'id(1)': u64
20[93; 94) '1': T 20[93; 94) '1': u64
21 21
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
index 4435180a1..f21bffa75 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap
@@ -1,8 +1,8 @@
1--- 1---
2created: "2019-01-22T14:44:59.961936900+00:00" 2created: "2019-01-26T17:46:03.866825843+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[53; 57) 'self': A<[unknown]> 7[53; 57) 'self': A<[unknown]>
8[65; 87) '{ ... }': [unknown] 8[65; 87) '{ ... }': [unknown]
@@ -12,25 +12,25 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
12[110; 115) '{ t }': [unknown] 12[110; 115) '{ t }': [unknown]
13[112; 113) 't': [unknown] 13[112; 113) 't': [unknown]
14[135; 261) '{ ....x() }': i128 14[135; 261) '{ ....x() }': i128
15[146; 147) 'x': T 15[146; 147) 'x': i32
16[150; 151) '1': T 16[150; 151) '1': i32
17[162; 163) 'y': T 17[162; 163) 'y': i32
18[166; 168) 'id': fn(T) -> T 18[166; 168) 'id': fn id<i32>(T) -> T
19[166; 171) 'id(x)': T 19[166; 171) 'id(x)': i32
20[169; 170) 'x': T 20[169; 170) 'x': i32
21[182; 183) 'a': A<T> 21[182; 183) 'a': A<i32>
22[186; 200) 'A { x: id(y) }': A<T> 22[186; 200) 'A { x: id(y) }': A<i32>
23[193; 195) 'id': fn(T) -> T 23[193; 195) 'id': fn id<i32>(T) -> T
24[193; 198) 'id(y)': T 24[193; 198) 'id(y)': i32
25[196; 197) 'y': T 25[196; 197) 'y': i32
26[211; 212) 'z': T 26[211; 212) 'z': i32
27[215; 217) 'id': fn(T) -> T 27[215; 217) 'id': fn id<i32>(T) -> T
28[215; 222) 'id(a.x)': T 28[215; 222) 'id(a.x)': i32
29[218; 219) 'a': A<T> 29[218; 219) 'a': A<i32>
30[218; 221) 'a.x': T 30[218; 221) 'a.x': i32
31[233; 234) 'b': A<T> 31[233; 234) 'b': A<i32>
32[237; 247) 'A { x: z }': A<T> 32[237; 247) 'A { x: z }': A<i32>
33[244; 245) 'z': T 33[244; 245) 'z': i32
34[254; 255) 'b': A<T> 34[254; 255) 'b': A<i32>
35[254; 259) 'b.x()': i128 35[254; 259) 'b.x()': i128
36 36
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
index 0bceffaef..afbe2f747 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_paths.snap
@@ -1,16 +1,16 @@
1--- 1---
2created: "2019-01-22T14:44:59.975899500+00:00" 2created: "2019-01-26T17:46:03.928773630+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[15; 20) '{ 1 }': u32 7[15; 20) '{ 1 }': u32
8[17; 18) '1': u32 8[17; 18) '1': u32
9[48; 53) '{ 1 }': u32 9[48; 53) '{ 1 }': u32
10[50; 51) '1': u32 10[50; 51) '1': u32
11[67; 91) '{ ...c(); }': () 11[67; 91) '{ ...c(); }': ()
12[73; 74) 'a': fn() -> u32 12[73; 74) 'a': fn a() -> u32
13[73; 76) 'a()': u32 13[73; 76) 'a()': u32
14[82; 86) 'b::c': fn() -> u32 14[82; 86) 'b::c': fn c() -> u32
15[82; 88) 'b::c()': u32 15[82; 88) 'b::c()': u32
16 16
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap
new file mode 100644
index 000000000..a99323264
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap
@@ -0,0 +1,26 @@
1---
2created: "2019-01-27T16:54:18.368427685+00:00"
3creator: [email protected]
4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs
6---
7[10; 11) 'x': [unknown]
8[21; 30) '{ x }': [unknown]
9[27; 28) 'x': [unknown]
10[44; 45) 'x': &[unknown]
11[56; 65) '{ x }': &[unknown]
12[62; 63) 'x': &[unknown]
13[77; 157) '{ ...(1); }': ()
14[87; 88) 'y': u32
15[91; 96) '10u32': u32
16[102; 104) 'id': fn id<u32>(T) -> T
17[102; 107) 'id(y)': u32
18[105; 106) 'y': u32
19[117; 118) 'x': bool
20[127; 132) 'clone': fn clone<bool>(&T) -> T
21[127; 135) 'clone(z)': bool
22[133; 134) 'z': &bool
23[141; 151) 'id::<i128>': fn id<i128>(T) -> T
24[141; 154) 'id::<i128>(1)': i128
25[152; 153) '1': i128
26
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap
index 10aa61954..5021d0eeb 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_unary_op.snap
@@ -1,11 +1,11 @@
1--- 1---
2created: "2019-01-22T14:45:00.059676600+00:00" 2created: "2019-01-28T14:51:16.185273502+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[27; 28) 'x': SomeType 7[27; 28) 'x': SomeType
8[40; 197) '{ ...lo"; }': () 8[40; 272) '{ ...lo"; }': ()
9[50; 51) 'b': bool 9[50; 51) 'b': bool
10[54; 59) 'false': bool 10[54; 59) 'false': bool
11[69; 70) 'c': bool 11[69; 70) 'c': bool
@@ -24,12 +24,25 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
24[147; 153) '!!true': bool 24[147; 153) '!!true': bool
25[148; 153) '!true': bool 25[148; 153) '!true': bool
26[149; 153) 'true': bool 26[149; 153) 'true': bool
27[159; 164) '-3.14': f64 27[163; 164) 'g': i32
28[160; 164) '3.14': f64 28[167; 170) '!42': i32
29[170; 172) '-x': [unknown] 29[168; 170) '42': i32
30[171; 172) 'x': SomeType 30[180; 181) 'h': u32
31[178; 180) '!x': [unknown] 31[184; 190) '!10u32': u32
32[179; 180) 'x': SomeType 32[185; 190) '10u32': u32
33[186; 194) '-"hello"': [unknown] 33[200; 201) 'j': i128
34[187; 194) '"hello"': &str 34[204; 206) '!a': i128
35[205; 206) 'a': i128
36[212; 217) '-3.14': f64
37[213; 217) '3.14': f64
38[223; 225) '!3': i32
39[224; 225) '3': i32
40[231; 233) '-x': [unknown]
41[232; 233) 'x': SomeType
42[239; 241) '!x': [unknown]
43[240; 241) 'x': SomeType
44[247; 255) '-"hello"': [unknown]
45[248; 255) '"hello"': &str
46[261; 269) '!"hello"': [unknown]
47[262; 269) '"hello"': &str
35 48
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 812d1238c..cb8d6351d 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -166,10 +166,15 @@ fn test(x: SomeType) {
166 let d: i128 = -a; 166 let d: i128 = -a;
167 let e = -100; 167 let e = -100;
168 let f = !!!true; 168 let f = !!!true;
169 let g = !42;
170 let h = !10u32;
171 let j = !a;
169 -3.14; 172 -3.14;
173 !3;
170 -x; 174 -x;
171 !x; 175 !x;
172 -"hello"; 176 -"hello";
177 !"hello";
173} 178}
174"#, 179"#,
175 ); 180 );
@@ -596,6 +601,29 @@ fn test() {
596 ); 601 );
597} 602}
598 603
604#[test]
605fn infer_type_param() {
606 check_inference(
607 "infer_type_param",
608 r#"
609fn id<T>(x: T) -> T {
610 x
611}
612
613fn clone<T>(x: &T) -> T {
614 x
615}
616
617fn test() {
618 let y = 10u32;
619 id(y);
620 let x: bool = clone(z);
621 id::<i128>(1);
622}
623"#,
624 );
625}
626
599fn infer(content: &str) -> String { 627fn infer(content: &str) -> String {
600 let (db, _, file_id) = MockDatabase::with_single_file(content); 628 let (db, _, file_id) = MockDatabase::with_single_file(content);
601 let source_file = db.parse(file_id); 629 let source_file = db.parse(file_id);