diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 39 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 116 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 270 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 30 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap | 14 |
12 files changed, 295 insertions, 250 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index b8ca04c5c..92ab0f692 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -5,7 +5,7 @@ use ra_db::{CrateId, FileId}; | |||
5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; | 5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Name, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, | 8 | Name, ScopesWithSyntaxMapping, Ty, HirFileId, |
9 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
10 | nameres::{ModuleScope, lower::ImportId}, | 10 | nameres::{ModuleScope, lower::ImportId}, |
11 | HirDatabase, PersistentHirDatabase, | 11 | HirDatabase, PersistentHirDatabase, |
@@ -175,18 +175,13 @@ impl Module { | |||
175 | db.item_map(self.krate)[self.module_id].clone() | 175 | db.item_map(self.krate)[self.module_id].clone() |
176 | } | 176 | } |
177 | 177 | ||
178 | pub fn resolve_path(&self, db: &impl PersistentHirDatabase, path: &Path) -> PerNs<ModuleDef> { | ||
179 | // TODO replace by Resolver::resolve_path | ||
180 | db.item_map(self.krate).resolve_path(db, *self, path) | ||
181 | } | ||
182 | |||
183 | pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | 178 | pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { |
184 | self.problems_impl(db) | 179 | self.problems_impl(db) |
185 | } | 180 | } |
186 | 181 | ||
187 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 182 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { |
188 | let item_map = db.item_map(self.krate); | 183 | let item_map = db.item_map(self.krate); |
189 | Resolver::default().push_module_scope(item_map, self.module_id) | 184 | Resolver::default().push_module_scope(item_map, *self) |
190 | } | 185 | } |
191 | } | 186 | } |
192 | 187 | ||
@@ -289,6 +284,21 @@ impl Struct { | |||
289 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 284 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
290 | db.type_for_def((*self).into()) | 285 | db.type_for_def((*self).into()) |
291 | } | 286 | } |
287 | |||
288 | // TODO move to a more general type | ||
289 | /// Builds a resolver for type references inside this struct. | ||
290 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
291 | // take the outer scope... | ||
292 | let r = self.module(db).resolver(db); | ||
293 | // ...and add generic params, if present | ||
294 | let p = self.generic_params(db); | ||
295 | let r = if !p.params.is_empty() { | ||
296 | r.push_generic_params_scope(p) | ||
297 | } else { | ||
298 | r | ||
299 | }; | ||
300 | r | ||
301 | } | ||
292 | } | 302 | } |
293 | 303 | ||
294 | impl Docs for Struct { | 304 | impl Docs for Struct { |
@@ -338,6 +348,21 @@ impl Enum { | |||
338 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 348 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
339 | db.type_for_def((*self).into()) | 349 | db.type_for_def((*self).into()) |
340 | } | 350 | } |
351 | |||
352 | // TODO move to a more general type | ||
353 | /// Builds a resolver for type references inside this struct. | ||
354 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
355 | // take the outer scope... | ||
356 | let r = self.module(db).resolver(db); | ||
357 | // ...and add generic params, if present | ||
358 | let p = self.generic_params(db); | ||
359 | let r = if !p.params.is_empty() { | ||
360 | r.push_generic_params_scope(p) | ||
361 | } else { | ||
362 | r | ||
363 | }; | ||
364 | r | ||
365 | } | ||
341 | } | 366 | } |
342 | 367 | ||
343 | impl Docs for Enum { | 368 | impl Docs for Enum { |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index c09d3fbf9..503a09f25 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -75,9 +75,6 @@ impl Body { | |||
75 | #[allow(dead_code)] | 75 | #[allow(dead_code)] |
76 | pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { | 76 | pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { |
77 | let mut r = body.owner.resolver(db); | 77 | let mut r = body.owner.resolver(db); |
78 | if !body.params.is_empty() { | ||
79 | r = r.push_function_params(Arc::clone(&body)); | ||
80 | } | ||
81 | let scopes = db.expr_scopes(body.owner); | 78 | let scopes = db.expr_scopes(body.owner); |
82 | let scope_chain = scopes.scope_chain_for(expr_id).collect::<Vec<_>>(); | 79 | let scope_chain = scopes.scope_chain_for(expr_id).collect::<Vec<_>>(); |
83 | for scope in scope_chain.into_iter().rev() { | 80 | for scope in scope_chain.into_iter().rev() { |
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 5fa49d456..a3908048b 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -7,13 +7,13 @@ use ra_syntax::{ | |||
7 | ast::{self, AstNode}}; | 7 | ast::{self, AstNode}}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | Const, Type, | 10 | Const, Type, Function, HirFileId, |
11 | Function, HirFileId, | 11 | HirDatabase, PersistentHirDatabase, |
12 | HirDatabase, | 12 | ModuleDef, Trait, Resolution, |
13 | PersistentHirDatabase, | ||
14 | type_ref::TypeRef, | 13 | type_ref::TypeRef, |
15 | ids::LocationCtx, | 14 | ids::LocationCtx, |
16 | resolve::Resolver, | 15 | resolve::Resolver, |
16 | ty::Ty, | ||
17 | }; | 17 | }; |
18 | 18 | ||
19 | use crate::code_model_api::{Module, ModuleSource}; | 19 | use crate::code_model_api::{Module, ModuleSource}; |
@@ -75,7 +75,7 @@ impl ImplBlock { | |||
75 | self.module_impl_blocks.module.clone() | 75 | self.module_impl_blocks.module.clone() |
76 | } | 76 | } |
77 | 77 | ||
78 | pub fn target_trait(&self) -> Option<&TypeRef> { | 78 | pub fn target_trait_ref(&self) -> Option<&TypeRef> { |
79 | self.impl_data().target_trait() | 79 | self.impl_data().target_trait() |
80 | } | 80 | } |
81 | 81 | ||
@@ -83,6 +83,23 @@ impl ImplBlock { | |||
83 | self.impl_data().target_type() | 83 | self.impl_data().target_type() |
84 | } | 84 | } |
85 | 85 | ||
86 | pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { | ||
87 | Ty::from_hir(db, &self.resolver(db), self.target_type()) | ||
88 | } | ||
89 | |||
90 | pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> { | ||
91 | if let Some(TypeRef::Path(path)) = self.target_trait_ref() { | ||
92 | let resolver = self.resolver(db); | ||
93 | if let Some(Resolution::Def { | ||
94 | def: ModuleDef::Trait(tr), | ||
95 | }) = resolver.resolve_path(db, path).take_types() | ||
96 | { | ||
97 | return Some(tr); | ||
98 | } | ||
99 | } | ||
100 | None | ||
101 | } | ||
102 | |||
86 | pub fn items(&self) -> &[ImplItem] { | 103 | pub fn items(&self) -> &[ImplItem] { |
87 | self.impl_data().items() | 104 | self.impl_data().items() |
88 | } | 105 | } |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e58658378..54da55598 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -55,13 +55,13 @@ pub use self::{ | |||
55 | name::Name, | 55 | name::Name, |
56 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, | 56 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, |
57 | macros::{MacroDef, MacroInput, MacroExpansion}, | 57 | macros::{MacroDef, MacroInput, MacroExpansion}, |
58 | nameres::{ItemMap, PerNs, Namespace, Resolution}, | 58 | nameres::{ItemMap, PerNs, Namespace}, |
59 | ty::Ty, | 59 | ty::Ty, |
60 | impl_block::{ImplBlock, ImplItem}, | 60 | impl_block::{ImplBlock, ImplItem}, |
61 | docs::{Docs, Documentation}, | 61 | docs::{Docs, Documentation}, |
62 | adt::AdtDef, | 62 | adt::AdtDef, |
63 | expr::{ExprScopes, ScopesWithSyntaxMapping}, | 63 | expr::{ExprScopes, ScopesWithSyntaxMapping}, |
64 | resolve::Resolver, | 64 | resolve::{Resolver, Resolution}, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | pub use self::code_model_api::{ | 67 | pub use self::code_model_api::{ |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index e825ec089..193c6a977 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -24,8 +24,9 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
24 | 24 | ||
25 | use crate::{ | 25 | use crate::{ |
26 | Module, ModuleDef, | 26 | Module, ModuleDef, |
27 | Path, PathKind, Crate, | 27 | Path, PathKind, PersistentHirDatabase, |
28 | Name, PersistentHirDatabase, | 28 | Crate, |
29 | Name, | ||
29 | module_tree::{ModuleId, ModuleTree}, | 30 | module_tree::{ModuleId, ModuleTree}, |
30 | nameres::lower::{ImportId, LoweredModule, ImportData}, | 31 | nameres::lower::{ImportId, LoweredModule, ImportData}, |
31 | }; | 32 | }; |
@@ -46,7 +47,7 @@ impl std::ops::Index<ModuleId> for ItemMap { | |||
46 | 47 | ||
47 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 48 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
48 | pub struct ModuleScope { | 49 | pub struct ModuleScope { |
49 | items: FxHashMap<Name, Resolution>, | 50 | pub(crate) items: FxHashMap<Name, Resolution>, |
50 | } | 51 | } |
51 | 52 | ||
52 | impl ModuleScope { | 53 | impl ModuleScope { |
@@ -113,6 +114,10 @@ impl<T> PerNs<T> { | |||
113 | self.types.is_none() && self.values.is_none() | 114 | self.types.is_none() && self.values.is_none() |
114 | } | 115 | } |
115 | 116 | ||
117 | pub fn is_both(&self) -> bool { | ||
118 | self.types.is_some() && self.values.is_some() | ||
119 | } | ||
120 | |||
116 | pub fn take(self, namespace: Namespace) -> Option<T> { | 121 | pub fn take(self, namespace: Namespace) -> Option<T> { |
117 | match namespace { | 122 | match namespace { |
118 | Namespace::Types => self.types, | 123 | Namespace::Types => self.types, |
@@ -139,6 +144,13 @@ impl<T> PerNs<T> { | |||
139 | } | 144 | } |
140 | } | 145 | } |
141 | 146 | ||
147 | pub fn combine(self, other: PerNs<T>) -> PerNs<T> { | ||
148 | PerNs { | ||
149 | types: self.types.or(other.types), | ||
150 | values: self.values.or(other.values), | ||
151 | } | ||
152 | } | ||
153 | |||
142 | pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { | 154 | pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { |
143 | PerNs { | 155 | PerNs { |
144 | types: self.types.and_then(&f), | 156 | types: self.types.and_then(&f), |
@@ -402,10 +414,11 @@ impl ItemMap { | |||
402 | if module.krate != original_module.krate { | 414 | if module.krate != original_module.krate { |
403 | let path = Path { | 415 | let path = Path { |
404 | segments: path.segments[i..].iter().cloned().collect(), | 416 | segments: path.segments[i..].iter().cloned().collect(), |
405 | kind: PathKind::Crate, | 417 | kind: PathKind::Self_, |
406 | }; | 418 | }; |
407 | log::debug!("resolving {:?} in other crate", path); | 419 | log::debug!("resolving {:?} in other crate", path); |
408 | let def = module.resolve_path(db, &path); | 420 | let item_map = db.item_map(module.krate); |
421 | let def = item_map.resolve_path(db, *module, &path); | ||
409 | return (def, ReachedFixedPoint::Yes); | 422 | return (def, ReachedFixedPoint::Yes); |
410 | } | 423 | } |
411 | 424 | ||
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 1ce7bd146..0e0683db7 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -5,11 +5,12 @@ use relative_path::RelativePath; | |||
5 | use test_utils::{assert_eq_text, covers}; | 5 | use test_utils::{assert_eq_text, covers}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | ItemMap, Resolution, | 8 | ItemMap, |
9 | PersistentHirDatabase, | 9 | PersistentHirDatabase, |
10 | mock::MockDatabase, | 10 | mock::MockDatabase, |
11 | module_tree::ModuleId, | 11 | module_tree::ModuleId, |
12 | }; | 12 | }; |
13 | use super::Resolution; | ||
13 | 14 | ||
14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | 15 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { |
15 | let (db, pos) = MockDatabase::with_position(fixture); | 16 | let (db, pos) = MockDatabase::with_position(fixture); |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index b7fbf6df2..36daed65b 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -1,30 +1,29 @@ | |||
1 | #![allow(unused_variables, dead_code)] | ||
2 | //! Name resolution. | 1 | //! Name resolution. |
3 | use std::sync::Arc; | 2 | use std::sync::Arc; |
4 | 3 | ||
5 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
6 | 5 | ||
7 | use crate::{ | 6 | use crate::{ |
8 | ModuleDef, | 7 | ModuleDef, Module, |
9 | name::Name, | 8 | db::HirDatabase, |
10 | nameres::{PerNs, lower::ImportId, ItemMap}, | 9 | name::{Name, KnownName}, |
11 | module_tree::ModuleId, | 10 | nameres::{PerNs, ItemMap}, |
12 | generics::GenericParams, | 11 | generics::GenericParams, |
13 | expr::{Body, scope::{ExprScopes, ScopeId}, PatId}, | 12 | expr::{scope::{ExprScopes, ScopeId}, PatId}, |
14 | impl_block::ImplBlock, | 13 | impl_block::ImplBlock, |
15 | path::Path, | 14 | path::Path, |
16 | }; | 15 | }; |
17 | 16 | ||
18 | #[derive(Debug, Clone, Default)] | 17 | #[derive(Debug, Clone, Default)] |
19 | pub struct Resolver { | 18 | pub struct Resolver { |
20 | scopes: Vec<Scope>, // maybe a 'linked list' of scopes? or allow linking a Resolver to a parent Resolver? that's an optimization that might not be necessary, though | 19 | scopes: Vec<Scope>, |
21 | } | 20 | } |
22 | 21 | ||
23 | // TODO how to store these best | 22 | // TODO how to store these best |
24 | #[derive(Debug, Clone)] | 23 | #[derive(Debug, Clone)] |
25 | pub(crate) struct ModuleItemMap { | 24 | pub(crate) struct ModuleItemMap { |
26 | item_map: Arc<ItemMap>, | 25 | item_map: Arc<ItemMap>, |
27 | module_id: ModuleId, | 26 | module: Module, |
28 | } | 27 | } |
29 | 28 | ||
30 | #[derive(Debug, Clone)] | 29 | #[derive(Debug, Clone)] |
@@ -39,8 +38,6 @@ pub(crate) enum Scope { | |||
39 | ModuleScope(ModuleItemMap), | 38 | ModuleScope(ModuleItemMap), |
40 | /// Brings the generic parameters of an item into scope | 39 | /// Brings the generic parameters of an item into scope |
41 | GenericParams(Arc<GenericParams>), | 40 | GenericParams(Arc<GenericParams>), |
42 | /// Brings the function parameters into scope | ||
43 | FunctionParams(Arc<Body>), | ||
44 | /// Brings `Self` into scope | 41 | /// Brings `Self` into scope |
45 | ImplBlockScope(ImplBlock), | 42 | ImplBlockScope(ImplBlock), |
46 | /// Local bindings | 43 | /// Local bindings |
@@ -49,36 +46,64 @@ pub(crate) enum Scope { | |||
49 | 46 | ||
50 | #[derive(Debug, Clone, PartialEq, Eq)] | 47 | #[derive(Debug, Clone, PartialEq, Eq)] |
51 | pub enum Resolution { | 48 | pub enum Resolution { |
49 | // FIXME make these tuple variants | ||
52 | /// An item | 50 | /// An item |
53 | Def { | 51 | Def { |
54 | def: ModuleDef, | 52 | def: ModuleDef, |
55 | import: Option<ImportId>, | ||
56 | }, | 53 | }, |
57 | /// A local binding (only value namespace) | 54 | /// A local binding (only value namespace) |
58 | LocalBinding { pat: PatId }, | 55 | LocalBinding { |
56 | pat: PatId, | ||
57 | }, | ||
59 | /// A generic parameter | 58 | /// A generic parameter |
60 | GenericParam { idx: u32 }, | 59 | GenericParam { |
61 | // TODO how does `Self` resolve? | 60 | idx: u32, |
61 | }, | ||
62 | SelfType(ImplBlock), | ||
62 | } | 63 | } |
63 | 64 | ||
64 | impl Resolver { | 65 | impl Resolver { |
65 | pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { | 66 | pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { |
67 | let mut resolution = PerNs::none(); | ||
66 | for scope in self.scopes.iter().rev() { | 68 | for scope in self.scopes.iter().rev() { |
67 | let resolution = scope.resolve_name(name); | 69 | resolution = resolution.combine(scope.resolve_name(name)); |
68 | if !resolution.is_none() { | 70 | if resolution.is_both() { |
69 | return resolution; | 71 | return resolution; |
70 | } | 72 | } |
71 | } | 73 | } |
72 | PerNs::none() | 74 | resolution |
73 | } | 75 | } |
74 | 76 | ||
75 | pub fn resolve_path(&self, path: &Path) -> PerNs<Resolution> { | 77 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> { |
76 | unimplemented!() | 78 | if let Some(name) = path.as_ident() { |
79 | self.resolve_name(name) | ||
80 | } else if path.is_self() { | ||
81 | self.resolve_name(&Name::self_param()) | ||
82 | } else { | ||
83 | let (item_map, module) = match self.module() { | ||
84 | Some(m) => m, | ||
85 | _ => return PerNs::none(), | ||
86 | }; | ||
87 | let module_res = item_map.resolve_path(db, module, path); | ||
88 | module_res.map(|def| Resolution::Def { def }) | ||
89 | } | ||
77 | } | 90 | } |
78 | 91 | ||
79 | pub fn all_names(&self) -> FxHashMap<Name, Resolution> { | 92 | pub fn all_names(&self) -> FxHashMap<Name, Resolution> { |
80 | unimplemented!() | 93 | unimplemented!() |
81 | } | 94 | } |
95 | |||
96 | fn module(&self) -> Option<(&ItemMap, Module)> { | ||
97 | for scope in self.scopes.iter().rev() { | ||
98 | match scope { | ||
99 | Scope::ModuleScope(m) => { | ||
100 | return Some((&m.item_map, m.module.clone())); | ||
101 | } | ||
102 | _ => {} | ||
103 | } | ||
104 | } | ||
105 | None | ||
106 | } | ||
82 | } | 107 | } |
83 | 108 | ||
84 | impl Resolver { | 109 | impl Resolver { |
@@ -95,11 +120,8 @@ impl Resolver { | |||
95 | self.push_scope(Scope::ImplBlockScope(impl_block)) | 120 | self.push_scope(Scope::ImplBlockScope(impl_block)) |
96 | } | 121 | } |
97 | 122 | ||
98 | pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module_id: ModuleId) -> Resolver { | 123 | pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module: Module) -> Resolver { |
99 | self.push_scope(Scope::ModuleScope(ModuleItemMap { | 124 | self.push_scope(Scope::ModuleScope(ModuleItemMap { item_map, module })) |
100 | item_map, | ||
101 | module_id, | ||
102 | })) | ||
103 | } | 125 | } |
104 | 126 | ||
105 | pub(crate) fn push_expr_scope( | 127 | pub(crate) fn push_expr_scope( |
@@ -112,19 +134,45 @@ impl Resolver { | |||
112 | scope_id, | 134 | scope_id, |
113 | })) | 135 | })) |
114 | } | 136 | } |
115 | |||
116 | pub(crate) fn push_function_params(self, body: Arc<Body>) -> Resolver { | ||
117 | self.push_scope(Scope::FunctionParams(body)) | ||
118 | } | ||
119 | |||
120 | pub(crate) fn pop_scope(mut self) -> Resolver { | ||
121 | self.scopes.pop(); | ||
122 | self | ||
123 | } | ||
124 | } | 137 | } |
125 | 138 | ||
126 | impl Scope { | 139 | impl Scope { |
127 | fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { | 140 | fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { |
128 | unimplemented!() | 141 | match self { |
142 | Scope::ModuleScope(m) => { | ||
143 | if let Some(KnownName::SelfParam) = name.as_known_name() { | ||
144 | PerNs::types(Resolution::Def { | ||
145 | def: m.module.into(), | ||
146 | }) | ||
147 | } else { | ||
148 | match m.item_map[m.module.module_id].get(name) { | ||
149 | Some(res) => res.def.map(|def| Resolution::Def { def }), | ||
150 | None => PerNs::none(), | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | Scope::GenericParams(gp) => match gp.find_by_name(name) { | ||
155 | Some(gp) => PerNs::types(Resolution::GenericParam { idx: gp.idx }), | ||
156 | None => PerNs::none(), | ||
157 | }, | ||
158 | Scope::ImplBlockScope(i) => { | ||
159 | if name.as_known_name() == Some(KnownName::SelfType) { | ||
160 | PerNs::types(Resolution::SelfType(i.clone())) | ||
161 | } else { | ||
162 | PerNs::none() | ||
163 | } | ||
164 | } | ||
165 | Scope::ExprScope(e) => { | ||
166 | let entry = e | ||
167 | .expr_scopes | ||
168 | .entries(e.scope_id) | ||
169 | .iter() | ||
170 | .find(|entry| entry.name() == name); | ||
171 | match entry { | ||
172 | Some(e) => PerNs::values(Resolution::LocalBinding { pat: e.pat() }), | ||
173 | None => PerNs::none(), | ||
174 | } | ||
175 | } | ||
176 | } | ||
129 | } | 177 | } |
130 | } | 178 | } |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index d3e31981a..d9c62f84c 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -33,15 +33,16 @@ use rustc_hash::FxHashMap; | |||
33 | use test_utils::tested_by; | 33 | use test_utils::tested_by; |
34 | 34 | ||
35 | use crate::{ | 35 | use crate::{ |
36 | Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, | 36 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, |
37 | FnSignature, ExprScopes, ModuleDef, AdtDef, | 37 | FnSignature, ModuleDef, AdtDef, |
38 | HirDatabase, | 38 | HirDatabase, |
39 | type_ref::{TypeRef, Mutability}, | 39 | type_ref::{TypeRef, Mutability}, |
40 | name::KnownName, | 40 | name::KnownName, |
41 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, | 41 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, |
42 | generics::GenericParams, | 42 | generics::GenericParams, |
43 | path::GenericArg, | 43 | path::GenericArg, |
44 | adt::VariantDef, | 44 | adt::VariantDef, |
45 | resolve::{Resolver, Resolution}, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | /// The ID of a type variable. | 48 | /// The ID of a type variable. |
@@ -300,47 +301,38 @@ pub struct FnSig { | |||
300 | } | 301 | } |
301 | 302 | ||
302 | impl Ty { | 303 | impl Ty { |
303 | pub(crate) fn from_hir( | 304 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
304 | db: &impl HirDatabase, | ||
305 | // TODO: the next three parameters basically describe the scope for name | ||
306 | // resolution; this should be refactored into something like a general | ||
307 | // resolver architecture | ||
308 | module: &Module, | ||
309 | impl_block: Option<&ImplBlock>, | ||
310 | generics: &GenericParams, | ||
311 | type_ref: &TypeRef, | ||
312 | ) -> Self { | ||
313 | match type_ref { | 305 | match type_ref { |
314 | TypeRef::Never => Ty::Never, | 306 | TypeRef::Never => Ty::Never, |
315 | TypeRef::Tuple(inner) => { | 307 | TypeRef::Tuple(inner) => { |
316 | let inner_tys = inner | 308 | let inner_tys = inner |
317 | .iter() | 309 | .iter() |
318 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) | 310 | .map(|tr| Ty::from_hir(db, resolver, tr)) |
319 | .collect::<Vec<_>>(); | 311 | .collect::<Vec<_>>(); |
320 | Ty::Tuple(inner_tys.into()) | 312 | Ty::Tuple(inner_tys.into()) |
321 | } | 313 | } |
322 | TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path), | 314 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), |
323 | TypeRef::RawPtr(inner, mutability) => { | 315 | TypeRef::RawPtr(inner, mutability) => { |
324 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 316 | let inner_ty = Ty::from_hir(db, resolver, inner); |
325 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | 317 | Ty::RawPtr(Arc::new(inner_ty), *mutability) |
326 | } | 318 | } |
327 | TypeRef::Array(inner) => { | 319 | TypeRef::Array(inner) => { |
328 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 320 | let inner_ty = Ty::from_hir(db, resolver, inner); |
329 | Ty::Array(Arc::new(inner_ty)) | 321 | Ty::Array(Arc::new(inner_ty)) |
330 | } | 322 | } |
331 | TypeRef::Slice(inner) => { | 323 | TypeRef::Slice(inner) => { |
332 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 324 | let inner_ty = Ty::from_hir(db, resolver, inner); |
333 | Ty::Slice(Arc::new(inner_ty)) | 325 | Ty::Slice(Arc::new(inner_ty)) |
334 | } | 326 | } |
335 | TypeRef::Reference(inner, mutability) => { | 327 | TypeRef::Reference(inner, mutability) => { |
336 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 328 | let inner_ty = Ty::from_hir(db, resolver, inner); |
337 | Ty::Ref(Arc::new(inner_ty), *mutability) | 329 | Ty::Ref(Arc::new(inner_ty), *mutability) |
338 | } | 330 | } |
339 | TypeRef::Placeholder => Ty::Unknown, | 331 | TypeRef::Placeholder => Ty::Unknown, |
340 | TypeRef::Fn(params) => { | 332 | TypeRef::Fn(params) => { |
341 | let mut inner_tys = params | 333 | let mut inner_tys = params |
342 | .iter() | 334 | .iter() |
343 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) | 335 | .map(|tr| Ty::from_hir(db, resolver, tr)) |
344 | .collect::<Vec<_>>(); | 336 | .collect::<Vec<_>>(); |
345 | let return_ty = inner_tys | 337 | let return_ty = inner_tys |
346 | .pop() | 338 | .pop() |
@@ -355,40 +347,13 @@ impl Ty { | |||
355 | } | 347 | } |
356 | } | 348 | } |
357 | 349 | ||
358 | pub(crate) fn from_hir_opt( | 350 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { |
359 | db: &impl HirDatabase, | ||
360 | module: &Module, | ||
361 | impl_block: Option<&ImplBlock>, | ||
362 | generics: &GenericParams, | ||
363 | type_ref: Option<&TypeRef>, | ||
364 | ) -> Self { | ||
365 | type_ref.map_or(Ty::Unknown, |t| { | ||
366 | Ty::from_hir(db, module, impl_block, generics, t) | ||
367 | }) | ||
368 | } | ||
369 | |||
370 | pub(crate) fn from_hir_path( | ||
371 | db: &impl HirDatabase, | ||
372 | module: &Module, | ||
373 | impl_block: Option<&ImplBlock>, | ||
374 | generics: &GenericParams, | ||
375 | path: &Path, | ||
376 | ) -> Self { | ||
377 | if let Some(name) = path.as_ident() { | 351 | if let Some(name) = path.as_ident() { |
352 | // TODO handle primitive type names in resolver as well? | ||
378 | if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { | 353 | if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { |
379 | return Ty::Int(int_ty); | 354 | return Ty::Int(int_ty); |
380 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { | 355 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { |
381 | return Ty::Float(float_ty); | 356 | return Ty::Float(float_ty); |
382 | } else if name.as_known_name() == Some(KnownName::SelfType) { | ||
383 | // TODO pass the impl block's generics? | ||
384 | let generics = &GenericParams::default(); | ||
385 | return Ty::from_hir_opt( | ||
386 | db, | ||
387 | module, | ||
388 | None, | ||
389 | generics, | ||
390 | impl_block.map(|i| i.target_type()), | ||
391 | ); | ||
392 | } else if let Some(known) = name.as_known_name() { | 357 | } else if let Some(known) = name.as_known_name() { |
393 | match known { | 358 | match known { |
394 | KnownName::Bool => return Ty::Bool, | 359 | KnownName::Bool => return Ty::Bool, |
@@ -396,25 +361,40 @@ impl Ty { | |||
396 | KnownName::Str => return Ty::Str, | 361 | KnownName::Str => return Ty::Str, |
397 | _ => {} | 362 | _ => {} |
398 | } | 363 | } |
399 | } else if let Some(generic_param) = generics.find_by_name(&name) { | 364 | } |
365 | } | ||
366 | |||
367 | // Resolve the path (in type namespace) | ||
368 | let resolution = resolver.resolve_path(db, path).take_types(); | ||
369 | |||
370 | let def = match resolution { | ||
371 | Some(Resolution::Def { def, .. }) => def, | ||
372 | Some(Resolution::LocalBinding { .. }) => { | ||
373 | // this should never happen | ||
374 | panic!("path resolved to local binding in type ns"); | ||
375 | } | ||
376 | Some(Resolution::GenericParam { idx }) => { | ||
400 | return Ty::Param { | 377 | return Ty::Param { |
401 | idx: generic_param.idx, | 378 | idx, |
402 | name: generic_param.name.clone(), | 379 | // TODO: maybe return name in resolution? |
380 | name: path | ||
381 | .as_ident() | ||
382 | .expect("generic param should be single-segment path") | ||
383 | .clone(), | ||
403 | }; | 384 | }; |
404 | } | 385 | } |
405 | } | 386 | Some(Resolution::SelfType(impl_block)) => { |
387 | return impl_block.target_ty(db); | ||
388 | } | ||
389 | None => return Ty::Unknown, | ||
390 | }; | ||
406 | 391 | ||
407 | // Resolve in module (in type namespace) | 392 | let typable: TypableDef = match def.into() { |
408 | let typable: TypableDef = match module | ||
409 | .resolve_path(db, path) | ||
410 | .take_types() | ||
411 | .and_then(|it| it.into()) | ||
412 | { | ||
413 | None => return Ty::Unknown, | 393 | None => return Ty::Unknown, |
414 | Some(it) => it, | 394 | Some(it) => it, |
415 | }; | 395 | }; |
416 | let ty = db.type_for_def(typable); | 396 | let ty = db.type_for_def(typable); |
417 | let substs = Ty::substs_from_path(db, module, impl_block, generics, path, typable); | 397 | let substs = Ty::substs_from_path(db, resolver, path, typable); |
418 | ty.apply_substs(substs) | 398 | ty.apply_substs(substs) |
419 | } | 399 | } |
420 | 400 | ||
@@ -422,10 +402,7 @@ impl Ty { | |||
422 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | 402 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. |
423 | fn substs_from_path( | 403 | fn substs_from_path( |
424 | db: &impl HirDatabase, | 404 | db: &impl HirDatabase, |
425 | // the scope of the segment... | 405 | resolver: &Resolver, |
426 | module: &Module, | ||
427 | impl_block: Option<&ImplBlock>, | ||
428 | outer_generics: &GenericParams, | ||
429 | path: &Path, | 406 | path: &Path, |
430 | resolved: TypableDef, | 407 | resolved: TypableDef, |
431 | ) -> Substs { | 408 | ) -> Substs { |
@@ -462,7 +439,7 @@ impl Ty { | |||
462 | for arg in generic_args.args.iter().take(param_count) { | 439 | for arg in generic_args.args.iter().take(param_count) { |
463 | match arg { | 440 | match arg { |
464 | GenericArg::Type(type_ref) => { | 441 | GenericArg::Type(type_ref) => { |
465 | let ty = Ty::from_hir(db, module, impl_block, outer_generics, type_ref); | 442 | let ty = Ty::from_hir(db, resolver, type_ref); |
466 | substs.push(ty); | 443 | substs.push(ty); |
467 | } | 444 | } |
468 | } | 445 | } |
@@ -666,24 +643,17 @@ impl fmt::Display for Ty { | |||
666 | /// function body. | 643 | /// function body. |
667 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 644 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
668 | let signature = def.signature(db); | 645 | let signature = def.signature(db); |
669 | let module = def.module(db); | 646 | let resolver = def.resolver(db); |
670 | let impl_block = def.impl_block(db); | ||
671 | let generics = def.generic_params(db); | 647 | let generics = def.generic_params(db); |
648 | let name = def.name(db); | ||
672 | let input = signature | 649 | let input = signature |
673 | .params() | 650 | .params() |
674 | .iter() | 651 | .iter() |
675 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) | 652 | .map(|tr| Ty::from_hir(db, &resolver, tr)) |
676 | .collect::<Vec<_>>(); | 653 | .collect::<Vec<_>>(); |
677 | let output = Ty::from_hir( | 654 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); |
678 | db, | ||
679 | &module, | ||
680 | impl_block.as_ref(), | ||
681 | &generics, | ||
682 | signature.ret_type(), | ||
683 | ); | ||
684 | let sig = Arc::new(FnSig { input, output }); | 655 | let sig = Arc::new(FnSig { input, output }); |
685 | let substs = make_substs(&generics); | 656 | let substs = make_substs(&generics); |
686 | let name = def.name(db); | ||
687 | Ty::FnDef { | 657 | Ty::FnDef { |
688 | def, | 658 | def, |
689 | sig, | 659 | sig, |
@@ -764,13 +734,13 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | |||
764 | 734 | ||
765 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | 735 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { |
766 | let parent_def = field.parent_def(db); | 736 | let parent_def = field.parent_def(db); |
767 | let (generics, module) = match parent_def { | 737 | let resolver = match parent_def { |
768 | VariantDef::Struct(it) => (it.generic_params(db), it.module(db)), | 738 | VariantDef::Struct(it) => it.resolver(db), |
769 | VariantDef::EnumVariant(it) => (it.parent_enum(db).generic_params(db), it.module(db)), | 739 | VariantDef::EnumVariant(it) => it.parent_enum(db).resolver(db), |
770 | }; | 740 | }; |
771 | let var_data = parent_def.variant_data(db); | 741 | let var_data = parent_def.variant_data(db); |
772 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; | 742 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; |
773 | Ty::from_hir(db, &module, None, &generics, type_ref) | 743 | Ty::from_hir(db, &resolver, type_ref) |
774 | } | 744 | } |
775 | 745 | ||
776 | /// The result of type inference: A mapping from expressions and patterns to types. | 746 | /// The result of type inference: A mapping from expressions and patterns to types. |
@@ -814,9 +784,7 @@ impl Index<PatId> for InferenceResult { | |||
814 | struct InferenceContext<'a, D: HirDatabase> { | 784 | struct InferenceContext<'a, D: HirDatabase> { |
815 | db: &'a D, | 785 | db: &'a D, |
816 | body: Arc<Body>, | 786 | body: Arc<Body>, |
817 | scopes: Arc<ExprScopes>, | 787 | resolver: Resolver, |
818 | module: Module, | ||
819 | impl_block: Option<ImplBlock>, | ||
820 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 788 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
821 | method_resolutions: FxHashMap<ExprId, Function>, | 789 | method_resolutions: FxHashMap<ExprId, Function>, |
822 | field_resolutions: FxHashMap<ExprId, StructField>, | 790 | field_resolutions: FxHashMap<ExprId, StructField>, |
@@ -905,13 +873,7 @@ fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
905 | } | 873 | } |
906 | 874 | ||
907 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 875 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
908 | fn new( | 876 | fn new(db: &'a D, body: Arc<Body>, resolver: Resolver) -> Self { |
909 | db: &'a D, | ||
910 | body: Arc<Body>, | ||
911 | scopes: Arc<ExprScopes>, | ||
912 | module: Module, | ||
913 | impl_block: Option<ImplBlock>, | ||
914 | ) -> Self { | ||
915 | InferenceContext { | 877 | InferenceContext { |
916 | method_resolutions: FxHashMap::default(), | 878 | method_resolutions: FxHashMap::default(), |
917 | field_resolutions: FxHashMap::default(), | 879 | field_resolutions: FxHashMap::default(), |
@@ -921,9 +883,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
921 | return_ty: Ty::Unknown, // set in collect_fn_signature | 883 | return_ty: Ty::Unknown, // set in collect_fn_signature |
922 | db, | 884 | db, |
923 | body, | 885 | body, |
924 | scopes, | 886 | resolver, |
925 | module, | ||
926 | impl_block, | ||
927 | } | 887 | } |
928 | } | 888 | } |
929 | 889 | ||
@@ -940,8 +900,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
940 | *ty = resolved; | 900 | *ty = resolved; |
941 | } | 901 | } |
942 | InferenceResult { | 902 | InferenceResult { |
943 | method_resolutions: mem::replace(&mut self.method_resolutions, Default::default()), | 903 | method_resolutions: self.method_resolutions, |
944 | field_resolutions: mem::replace(&mut self.field_resolutions, Default::default()), | 904 | field_resolutions: self.field_resolutions, |
945 | type_of_expr: expr_types, | 905 | type_of_expr: expr_types, |
946 | type_of_pat: pat_types, | 906 | type_of_pat: pat_types, |
947 | } | 907 | } |
@@ -964,13 +924,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
964 | } | 924 | } |
965 | 925 | ||
966 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { | 926 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { |
967 | // TODO provide generics of function | ||
968 | let generics = GenericParams::default(); | ||
969 | let ty = Ty::from_hir( | 927 | let ty = Ty::from_hir( |
970 | self.db, | 928 | self.db, |
971 | &self.module, | 929 | // TODO use right resolver for block |
972 | self.impl_block.as_ref(), | 930 | &self.resolver, |
973 | &generics, | ||
974 | type_ref, | 931 | type_ref, |
975 | ); | 932 | ); |
976 | let ty = self.insert_type_vars(ty); | 933 | let ty = self.insert_type_vars(ty); |
@@ -1147,38 +1104,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1147 | }) | 1104 | }) |
1148 | } | 1105 | } |
1149 | 1106 | ||
1150 | fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Option<Ty> { | 1107 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { |
1151 | if path.is_ident() || path.is_self() { | 1108 | let resolved = resolver.resolve_path(self.db, &path).take_values()?; |
1152 | // resolve locally | 1109 | match resolved { |
1153 | let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); | 1110 | Resolution::Def { def, .. } => { |
1154 | if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { | 1111 | let typable: Option<TypableDef> = def.into(); |
1155 | let ty = self.type_of_pat.get(scope_entry.pat())?; | 1112 | let typable = typable?; |
1113 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
1114 | let ty = self.db.type_for_def(typable).apply_substs(substs); | ||
1115 | let ty = self.insert_type_vars(ty); | ||
1116 | Some(ty) | ||
1117 | } | ||
1118 | Resolution::LocalBinding { pat } => { | ||
1119 | let ty = self.type_of_pat.get(pat)?; | ||
1156 | let ty = self.resolve_ty_as_possible(&mut vec![], ty.clone()); | 1120 | let ty = self.resolve_ty_as_possible(&mut vec![], ty.clone()); |
1157 | return Some(ty); | 1121 | Some(ty) |
1158 | }; | 1122 | } |
1159 | }; | 1123 | Resolution::GenericParam { .. } => { |
1160 | 1124 | // generic params can't refer to values... yet | |
1161 | // resolve in module | 1125 | None |
1162 | let typable: Option<TypableDef> = self | 1126 | } |
1163 | .module | 1127 | Resolution::SelfType(_) => { |
1164 | .resolve_path(self.db, &path) | 1128 | log::error!("path expr {:?} resolved to Self type in values ns", path); |
1165 | .take_values()? | 1129 | None |
1166 | .into(); | 1130 | } |
1167 | let typable = typable?; | 1131 | } |
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); | ||
1179 | let ty = self.insert_type_vars(ty); | ||
1180 | |||
1181 | Some(ty) | ||
1182 | } | 1132 | } |
1183 | 1133 | ||
1184 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { | 1134 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { |
@@ -1186,26 +1136,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1186 | Some(path) => path, | 1136 | Some(path) => path, |
1187 | None => return (Ty::Unknown, None), | 1137 | None => return (Ty::Unknown, None), |
1188 | }; | 1138 | }; |
1189 | let typable: Option<TypableDef> = self | 1139 | let resolver = &self.resolver; |
1190 | .module | 1140 | let typable: Option<TypableDef> = match resolver.resolve_path(self.db, &path).take_types() { |
1191 | .resolve_path(self.db, &path) | 1141 | Some(Resolution::Def { def, .. }) => def.into(), |
1192 | .take_types() | 1142 | Some(Resolution::LocalBinding { .. }) => { |
1193 | .and_then(|it| it.into()); | 1143 | // this cannot happen |
1144 | log::error!("path resolved to local binding in type ns"); | ||
1145 | return (Ty::Unknown, None); | ||
1146 | } | ||
1147 | Some(Resolution::GenericParam { .. }) => { | ||
1148 | // generic params can't be used in struct literals | ||
1149 | return (Ty::Unknown, None); | ||
1150 | } | ||
1151 | Some(Resolution::SelfType(..)) => { | ||
1152 | // TODO this is allowed in an impl for a struct, handle this | ||
1153 | return (Ty::Unknown, None); | ||
1154 | } | ||
1155 | None => return (Ty::Unknown, None), | ||
1156 | }; | ||
1194 | let def = match typable { | 1157 | let def = match typable { |
1195 | None => return (Ty::Unknown, None), | 1158 | None => return (Ty::Unknown, None), |
1196 | Some(it) => it, | 1159 | Some(it) => it, |
1197 | }; | 1160 | }; |
1198 | // TODO remove the duplication between here and `Ty::from_path`? | 1161 | // TODO remove the duplication between here and `Ty::from_path`? |
1199 | // TODO provide generics of function | 1162 | let substs = Ty::substs_from_path(self.db, resolver, path, def); |
1200 | let generics = GenericParams::default(); | ||
1201 | let substs = Ty::substs_from_path( | ||
1202 | self.db, | ||
1203 | &self.module, | ||
1204 | self.impl_block.as_ref(), | ||
1205 | &generics, | ||
1206 | path, | ||
1207 | def, | ||
1208 | ); | ||
1209 | match def { | 1163 | match def { |
1210 | TypableDef::Struct(s) => { | 1164 | TypableDef::Struct(s) => { |
1211 | let ty = type_for_struct(self.db, s); | 1165 | let ty = type_for_struct(self.db, s); |
@@ -1303,12 +1257,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1303 | path: ref p, | 1257 | path: ref p, |
1304 | args: ref fields, | 1258 | args: ref fields, |
1305 | } => self.infer_struct_pat(p.as_ref(), fields, expected), | 1259 | } => self.infer_struct_pat(p.as_ref(), fields, expected), |
1306 | Pat::Path(path) => self | 1260 | Pat::Path(path) => { |
1307 | .module | 1261 | // TODO use correct resolver for the surrounding expression |
1308 | .resolve_path(self.db, &path) | 1262 | let resolver = self.resolver.clone(); |
1309 | .take_values() | 1263 | self.infer_path_expr(&resolver, &path) |
1310 | .and_then(|module_def| module_def.into()) | 1264 | .unwrap_or(Ty::Unknown) |
1311 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), | 1265 | } |
1312 | Pat::Bind { | 1266 | Pat::Bind { |
1313 | mode, | 1267 | mode, |
1314 | name: _name, | 1268 | name: _name, |
@@ -1496,7 +1450,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1496 | 1450 | ||
1497 | expected.ty | 1451 | expected.ty |
1498 | } | 1452 | } |
1499 | Expr::Path(p) => self.infer_path_expr(tgt_expr, p).unwrap_or(Ty::Unknown), | 1453 | Expr::Path(p) => { |
1454 | // TODO this could be more efficient... | ||
1455 | let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); | ||
1456 | self.infer_path_expr(&resolver, p).unwrap_or(Ty::Unknown) | ||
1457 | } | ||
1500 | Expr::Continue => Ty::Never, | 1458 | Expr::Continue => Ty::Never, |
1501 | Expr::Break { expr } => { | 1459 | Expr::Break { expr } => { |
1502 | if let Some(expr) = expr { | 1460 | if let Some(expr) = expr { |
@@ -1730,10 +1688,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1730 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | 1688 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { |
1731 | db.check_canceled(); | 1689 | db.check_canceled(); |
1732 | let body = func.body(db); | 1690 | let body = func.body(db); |
1733 | let scopes = db.expr_scopes(func); | 1691 | let resolver = func.resolver(db); |
1734 | let module = func.module(db); | 1692 | let mut ctx = InferenceContext::new(db, body, resolver); |
1735 | let impl_block = func.impl_block(db); | ||
1736 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); | ||
1737 | 1693 | ||
1738 | let signature = func.signature(db); | 1694 | let signature = func.signature(db); |
1739 | ctx.collect_fn_signature(&signature); | 1695 | ctx.collect_fn_signature(&signature); |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index e857d6856..2282286b0 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -7,12 +7,10 @@ use std::sync::Arc; | |||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | HirDatabase, module_tree::ModuleId, Module, ModuleDef, Crate, Name, Function, Trait, | 10 | HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, Trait, |
11 | ids::TraitId, | 11 | ids::TraitId, |
12 | impl_block::{ImplId, ImplBlock, ImplItem}, | 12 | impl_block::{ImplId, ImplBlock, ImplItem}, |
13 | generics::GenericParams, | ||
14 | ty::{AdtDef, Ty}, | 13 | ty::{AdtDef, Ty}, |
15 | type_ref::TypeRef, | ||
16 | }; | 14 | }; |
17 | 15 | ||
18 | /// This is used as a key for indexing impls. | 16 | /// This is used as a key for indexing impls. |
@@ -85,17 +83,10 @@ impl CrateImplBlocks { | |||
85 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { | 83 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { |
86 | let module_impl_blocks = db.impls_in_module(module.clone()); | 84 | let module_impl_blocks = db.impls_in_module(module.clone()); |
87 | 85 | ||
88 | for (impl_id, impl_data) in module_impl_blocks.impls.iter() { | 86 | for (impl_id, _) in module_impl_blocks.impls.iter() { |
89 | let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); | 87 | let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); |
90 | // TODO provide generics of impl | 88 | |
91 | let generics = GenericParams::default(); | 89 | let target_ty = impl_block.target_ty(db); |
92 | let target_ty = Ty::from_hir( | ||
93 | db, | ||
94 | &module, | ||
95 | Some(&impl_block), | ||
96 | &generics, | ||
97 | impl_data.target_type(), | ||
98 | ); | ||
99 | 90 | ||
100 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | 91 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { |
101 | self.impls | 92 | self.impls |
@@ -104,14 +95,11 @@ impl CrateImplBlocks { | |||
104 | .push((module.module_id, impl_id)); | 95 | .push((module.module_id, impl_id)); |
105 | } | 96 | } |
106 | 97 | ||
107 | if let Some(TypeRef::Path(path)) = impl_data.target_trait() { | 98 | if let Some(tr) = impl_block.target_trait(db) { |
108 | let perns = module.resolve_path(db, path); | 99 | self.impls_by_trait |
109 | if let Some(ModuleDef::Trait(tr)) = perns.take_types() { | 100 | .entry(tr.id) |
110 | self.impls_by_trait | 101 | .or_insert_with(Vec::new) |
111 | .entry(tr.id) | 102 | .push((module.module_id, impl_id)); |
112 | .or_insert_with(Vec::new) | ||
113 | .push((module.module_id, impl_id)); | ||
114 | } | ||
115 | } | 103 | } |
116 | } | 104 | } |
117 | 105 | ||
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 8ff6e55a6..91c48897c 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,12 +1,12 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-26T18:16:16.530712344+00:00" | 2 | created: "2019-01-27T14:52:29.934503829+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: crates/ra_hir/src/ty/tests.rs | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [10; 11) 't': [unknown] | 7 | [10; 11) 't': T |
8 | [21; 26) '{ t }': [unknown] | 8 | [21; 26) '{ t }': T |
9 | [23; 24) 't': [unknown] | 9 | [23; 24) 't': T |
10 | [38; 98) '{ ...(1); }': () | 10 | [38; 98) '{ ...(1); }': () |
11 | [44; 46) 'id': fn id<u32>(T) -> T | 11 | [44; 46) 'id': fn id<u32>(T) -> T |
12 | [44; 52) 'id(1u32)': u32 | 12 | [44; 52) 'id(1u32)': u32 |
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 f21bffa75..626f31252 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,5 +1,5 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-26T17:46:03.866825843+00:00" | 2 | created: "2019-01-27T14:52:29.938713255+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: crates/ra_hir/src/ty/tests.rs | 5 | source: crates/ra_hir/src/ty/tests.rs |
@@ -8,9 +8,9 @@ source: crates/ra_hir/src/ty/tests.rs | |||
8 | [65; 87) '{ ... }': [unknown] | 8 | [65; 87) '{ ... }': [unknown] |
9 | [75; 79) 'self': A<[unknown]> | 9 | [75; 79) 'self': A<[unknown]> |
10 | [75; 81) 'self.x': [unknown] | 10 | [75; 81) 'self.x': [unknown] |
11 | [99; 100) 't': [unknown] | 11 | [99; 100) 't': T |
12 | [110; 115) '{ t }': [unknown] | 12 | [110; 115) '{ t }': T |
13 | [112; 113) 't': [unknown] | 13 | [112; 113) 't': T |
14 | [135; 261) '{ ....x() }': i128 | 14 | [135; 261) '{ ....x() }': i128 |
15 | [146; 147) 'x': i32 | 15 | [146; 147) 'x': i32 |
16 | [150; 151) '1': i32 | 16 | [150; 151) '1': i32 |
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 index a99323264..216d1e41f 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap | |||
@@ -1,15 +1,15 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-27T16:54:18.368427685+00:00" | 2 | created: "2019-01-27T20:38:32.153717698+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: crates/ra_hir/src/ty/tests.rs | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [10; 11) 'x': [unknown] | 7 | [10; 11) 'x': T |
8 | [21; 30) '{ x }': [unknown] | 8 | [21; 30) '{ x }': T |
9 | [27; 28) 'x': [unknown] | 9 | [27; 28) 'x': T |
10 | [44; 45) 'x': &[unknown] | 10 | [44; 45) 'x': &T |
11 | [56; 65) '{ x }': &[unknown] | 11 | [56; 65) '{ x }': &T |
12 | [62; 63) 'x': &[unknown] | 12 | [62; 63) 'x': &T |
13 | [77; 157) '{ ...(1); }': () | 13 | [77; 157) '{ ...(1); }': () |
14 | [87; 88) 'y': u32 | 14 | [87; 88) 'y': u32 |
15 | [91; 96) '10u32': u32 | 15 | [91; 96) '10u32': u32 |