aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-09-12 21:35:53 +0100
committerAleksey Kladov <[email protected]>2019-09-13 14:24:10 +0100
commit51e2d76b9839410020c75ac02ad602675b0a5aa9 (patch)
tree989afd660d62db28196a8792cec2affb7bfd50a7 /crates/ra_hir/src
parent1adf0519bcc8286c06e12aa7e5b16298addfea4a (diff)
Specify desirable namespace when calling resolve
That way, we are able to get rid of a number of unreachable statements
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs10
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/nameres.rs10
-rw-r--r--crates/ra_hir/src/nameres/per_ns.rs9
-rw-r--r--crates/ra_hir/src/resolve.rs405
-rw-r--r--crates/ra_hir/src/source_binder.rs66
-rw-r--r--crates/ra_hir/src/ty/infer.rs256
-rw-r--r--crates/ra_hir/src/ty/lower.rs108
8 files changed, 458 insertions, 408 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index c1938bd86..dad1c93c4 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -22,7 +22,7 @@ use crate::{
22 U8, USIZE, 22 U8, USIZE,
23 }, 23 },
24 nameres::{CrateModuleId, ImportId, ModuleScope, Namespace}, 24 nameres::{CrateModuleId, ImportId, ModuleScope, Namespace},
25 resolve::Resolver, 25 resolve::{Resolver, TypeNs},
26 traits::{TraitData, TraitItem}, 26 traits::{TraitData, TraitItem},
27 ty::{ 27 ty::{
28 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 28 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness},
@@ -868,11 +868,9 @@ impl Trait {
868 } 868 }
869 _ => None, 869 _ => None,
870 }) 870 })
871 .filter_map(|path| { 871 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
872 match resolver.resolve_path_without_assoc_items(db, path).take_types() { 872 Some(TypeNs::Trait(t)) => Some(t),
873 Some(crate::Resolution::Def(ModuleDef::Trait(t))) => Some(t), 873 _ => None,
874 _ => None,
875 }
876 }) 874 })
877 .collect() 875 .collect()
878 } 876 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 508da3623..80cf8d9c0 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -73,7 +73,7 @@ pub use self::{
73 name::Name, 73 name::Name,
74 nameres::{ImportId, Namespace, PerNs}, 74 nameres::{ImportId, Namespace, PerNs},
75 path::{Path, PathKind}, 75 path::{Path, PathKind},
76 resolve::Resolution, 76 resolve::ScopeDef,
77 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 77 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
78 source_id::{AstIdMap, ErasedFileAstId}, 78 source_id::{AstIdMap, ErasedFileAstId},
79 ty::{ 79 ty::{
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 3a3bf6b5f..44a4ddba0 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -279,10 +279,6 @@ impl CrateDefMap {
279 self.root 279 self.root
280 } 280 }
281 281
282 pub(crate) fn mk_module(&self, module_id: CrateModuleId) -> Module {
283 Module { krate: self.krate, module_id }
284 }
285
286 pub(crate) fn prelude(&self) -> Option<Module> { 282 pub(crate) fn prelude(&self) -> Option<Module> {
287 self.prelude 283 self.prelude
288 } 284 }
@@ -389,7 +385,7 @@ impl CrateDefMap {
389 }; 385 };
390 386
391 for (i, segment) in segments { 387 for (i, segment) in segments {
392 let curr = match curr_per_ns.as_ref().take_types() { 388 let curr = match curr_per_ns.take_types() {
393 Some(r) => r, 389 Some(r) => r,
394 None => { 390 None => {
395 // we still have path segments left, but the path so far 391 // we still have path segments left, but the path so far
@@ -433,7 +429,7 @@ impl CrateDefMap {
433 Some(variant) => PerNs::both(variant.into(), variant.into()), 429 Some(variant) => PerNs::both(variant.into(), variant.into()),
434 None => { 430 None => {
435 return ResolvePathResult::with( 431 return ResolvePathResult::with(
436 PerNs::types((*e).into()), 432 PerNs::types(e.into()),
437 ReachedFixedPoint::Yes, 433 ReachedFixedPoint::Yes,
438 Some(i), 434 Some(i),
439 ); 435 );
@@ -450,7 +446,7 @@ impl CrateDefMap {
450 ); 446 );
451 447
452 return ResolvePathResult::with( 448 return ResolvePathResult::with(
453 PerNs::types(*s), 449 PerNs::types(s),
454 ReachedFixedPoint::Yes, 450 ReachedFixedPoint::Yes,
455 Some(i), 451 Some(i),
456 ); 452 );
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
index d07cc08f4..b0f4dff33 100644
--- a/crates/ra_hir/src/nameres/per_ns.rs
+++ b/crates/ra_hir/src/nameres/per_ns.rs
@@ -68,10 +68,6 @@ impl<T> PerNs<T> {
68 PerNs { types: None, values: None, macros: self.macros } 68 PerNs { types: None, values: None, macros: self.macros }
69 } 69 }
70 70
71 pub fn as_ref(&self) -> PerNs<&T> {
72 PerNs { types: self.types.as_ref(), values: self.values.as_ref(), macros: self.macros }
73 }
74
75 pub fn or(self, other: PerNs<T>) -> PerNs<T> { 71 pub fn or(self, other: PerNs<T>) -> PerNs<T> {
76 PerNs { 72 PerNs {
77 types: self.types.or(other.types), 73 types: self.types.or(other.types),
@@ -79,9 +75,4 @@ impl<T> PerNs<T> {
79 macros: self.macros.or(other.macros), 75 macros: self.macros.or(other.macros),
80 } 76 }
81 } 77 }
82
83 /// Map types and values. Leave macros unchanged.
84 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> {
85 PerNs { types: self.types.map(&f), values: self.values.map(&f), macros: self.macros }
86 }
87} 78}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index a77a9aeb1..d841593f8 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -1,7 +1,7 @@
1//! Name resolution. 1//! Name resolution.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use rustc_hash::{FxHashMap, FxHashSet}; 4use rustc_hash::FxHashSet;
5 5
6use crate::{ 6use crate::{
7 code_model::Crate, 7 code_model::Crate,
@@ -14,8 +14,9 @@ use crate::{
14 impl_block::ImplBlock, 14 impl_block::ImplBlock,
15 name::{Name, SELF_PARAM, SELF_TYPE}, 15 name::{Name, SELF_PARAM, SELF_TYPE},
16 nameres::{CrateDefMap, CrateModuleId, PerNs}, 16 nameres::{CrateDefMap, CrateModuleId, PerNs},
17 path::Path, 17 path::{Path, PathKind},
18 Adt, Enum, MacroDef, ModuleDef, Struct, Trait, 18 Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct,
19 Trait, TypeAlias,
19}; 20};
20 21
21#[derive(Debug, Clone, Default)] 22#[derive(Debug, Clone, Default)]
@@ -37,69 +38,6 @@ pub(crate) struct ExprScope {
37} 38}
38 39
39#[derive(Debug, Clone)] 40#[derive(Debug, Clone)]
40pub(crate) struct PathResult {
41 /// The actual path resolution
42 // FIXME: `PerNs<Resolution>` type doesn't make sense, as not every
43 // Resolution variant can appear in every namespace
44 resolution: PerNs<Resolution>,
45 /// The first index in the path that we
46 /// were unable to resolve.
47 /// When path is fully resolved, this is 0.
48 remaining_index: usize,
49}
50
51impl PathResult {
52 /// Returns the remaining index in the result
53 /// returns None if the path was fully resolved
54 pub(crate) fn remaining_index(&self) -> Option<usize> {
55 if self.remaining_index > 0 {
56 Some(self.remaining_index)
57 } else {
58 None
59 }
60 }
61
62 /// Consumes `PathResult` and returns the contained `PerNs<Resolution>`
63 /// if the path was fully resolved, meaning we have no remaining items
64 pub(crate) fn into_fully_resolved(self) -> PerNs<Resolution> {
65 if self.is_fully_resolved() {
66 self.resolution
67 } else {
68 PerNs::none()
69 }
70 }
71
72 /// Consumes `PathResult` and returns the resolution and the
73 /// remaining_index as a tuple.
74 pub(crate) fn into_inner(self) -> (PerNs<Resolution>, Option<usize>) {
75 let index = self.remaining_index();
76 (self.resolution, index)
77 }
78
79 /// Path is fully resolved when `remaining_index` is none
80 /// and the resolution contains anything
81 pub(crate) fn is_fully_resolved(&self) -> bool {
82 !self.resolution.is_none() && self.remaining_index().is_none()
83 }
84
85 fn empty() -> PathResult {
86 PathResult { resolution: PerNs::none(), remaining_index: 0 }
87 }
88
89 fn from_resolution(res: PerNs<Resolution>) -> PathResult {
90 PathResult::from_resolution_with_index(res, 0)
91 }
92
93 fn from_resolution_with_index(res: PerNs<Resolution>, remaining_index: usize) -> PathResult {
94 if res.is_none() {
95 PathResult::empty()
96 } else {
97 PathResult { resolution: res, remaining_index }
98 }
99 }
100}
101
102#[derive(Debug, Clone)]
103pub(crate) enum Scope { 41pub(crate) enum Scope {
104 /// All the items and imported names of a module 42 /// All the items and imported names of a module
105 ModuleScope(ModuleItemMap), 43 ModuleScope(ModuleItemMap),
@@ -112,25 +50,41 @@ pub(crate) enum Scope {
112} 50}
113 51
114#[derive(Debug, Clone, PartialEq, Eq)] 52#[derive(Debug, Clone, PartialEq, Eq)]
115pub enum Resolution { 53pub enum TypeNs {
116 /// An item 54 SelfType(ImplBlock),
117 Def(ModuleDef), 55 GenericParam(u32),
56 Adt(Adt),
57 EnumVariant(EnumVariant),
58 TypeAlias(TypeAlias),
59 BuiltinType(BuiltinType),
60 Trait(Trait),
61 // Module belong to type ns, but the resovler is used when all module paths
62 // are fully resolved.
63 // Module(Module)
64}
65
66#[derive(Debug)]
67pub enum ValueOrPartial {
68 ValueNs(ValueNs),
69 Partial(TypeNs, usize),
70}
118 71
119 // FIXME: there's no way we can syntactically confuse a local with generic 72#[derive(Debug)]
120 // param, so these two should not be members of the single enum 73pub enum ValueNs {
121 /// A local binding (only value namespace)
122 LocalBinding(PatId), 74 LocalBinding(PatId),
123 /// A generic parameter 75 Function(Function),
124 GenericParam(u32), 76 Const(Const),
125 SelfType(ImplBlock), 77 Static(Static),
78 Struct(Struct),
79 EnumVariant(EnumVariant),
126} 80}
127 81
128impl Resolver { 82impl Resolver {
129 /// Resolve known trait from std, like `std::futures::Future` 83 /// Resolve known trait from std, like `std::futures::Future`
130 pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option<Trait> { 84 pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option<Trait> {
131 let res = self.resolve_path_segments(db, path).into_fully_resolved().take_types()?; 85 let res = self.resolve_module_path(db, path).take_types()?;
132 match res { 86 match res {
133 Resolution::Def(ModuleDef::Trait(it)) => Some(it), 87 ModuleDef::Trait(it) => Some(it),
134 _ => None, 88 _ => None,
135 } 89 }
136 } 90 }
@@ -141,94 +95,214 @@ impl Resolver {
141 db: &impl HirDatabase, 95 db: &impl HirDatabase,
142 path: &Path, 96 path: &Path,
143 ) -> Option<Struct> { 97 ) -> Option<Struct> {
144 let res = self.resolve_path_segments(db, path).into_fully_resolved().take_types()?; 98 let res = self.resolve_module_path(db, path).take_types()?;
145 match res { 99 match res {
146 Resolution::Def(ModuleDef::Adt(Adt::Struct(it))) => Some(it), 100 ModuleDef::Adt(Adt::Struct(it)) => Some(it),
147 _ => None, 101 _ => None,
148 } 102 }
149 } 103 }
150 104
151 /// Resolve known enum from std, like `std::result::Result` 105 /// Resolve known enum from std, like `std::result::Result`
152 pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option<Enum> { 106 pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option<Enum> {
153 let res = self.resolve_path_segments(db, path).into_fully_resolved().take_types()?; 107 let res = self.resolve_module_path(db, path).take_types()?;
154 match res { 108 match res {
155 Resolution::Def(ModuleDef::Adt(Adt::Enum(it))) => Some(it), 109 ModuleDef::Adt(Adt::Enum(it)) => Some(it),
156 _ => None, 110 _ => None,
157 } 111 }
158 } 112 }
159 113
160 pub(crate) fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> { 114 /// pub only for source-binder
161 let mut resolution = PerNs::none(); 115 pub(crate) fn resolve_module_path(
116 &self,
117 db: &impl HirDatabase,
118 path: &Path,
119 ) -> PerNs<ModuleDef> {
120 let (item_map, module) = match self.module() {
121 Some(it) => it,
122 None => return PerNs::none(),
123 };
124 let (module_res, segment_index) = item_map.resolve_path(db, module, path);
125 if segment_index.is_some() {
126 return PerNs::none();
127 }
128 module_res
129 }
130
131 pub(crate) fn resolve_path_in_type_ns(
132 &self,
133 db: &impl HirDatabase,
134 path: &Path,
135 ) -> Option<(TypeNs, Option<usize>)> {
136 let first_name = &path.segments.first()?.name;
137 let skip_to_mod = path.kind != PathKind::Plain;
162 for scope in self.scopes.iter().rev() { 138 for scope in self.scopes.iter().rev() {
163 resolution = resolution.or(scope.resolve_name(db, name)); 139 match scope {
164 if resolution.is_all() { 140 Scope::ExprScope(_) => continue,
165 return resolution; 141 Scope::GenericParams(_) | Scope::ImplBlockScope(_) if skip_to_mod => continue,
142
143 Scope::GenericParams(params) => {
144 if let Some(param) = params.find_by_name(first_name) {
145 let idx = if path.segments.len() == 1 { None } else { Some(1) };
146 return Some((TypeNs::GenericParam(param.idx), idx));
147 }
148 }
149 Scope::ImplBlockScope(impl_) => {
150 if first_name == &SELF_TYPE {
151 let idx = if path.segments.len() == 1 { None } else { Some(1) };
152 return Some((TypeNs::SelfType(*impl_), idx));
153 }
154 }
155 Scope::ModuleScope(m) => {
156 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
157 let res = match module_def.take_types()? {
158 ModuleDef::Adt(it) => TypeNs::Adt(it),
159 ModuleDef::EnumVariant(it) => TypeNs::EnumVariant(it),
160
161 ModuleDef::TypeAlias(it) => TypeNs::TypeAlias(it),
162 ModuleDef::BuiltinType(it) => TypeNs::BuiltinType(it),
163
164 ModuleDef::Trait(it) => TypeNs::Trait(it),
165
166 ModuleDef::Function(_)
167 | ModuleDef::Const(_)
168 | ModuleDef::Static(_)
169 | ModuleDef::Module(_) => return None,
170 };
171 return Some((res, idx));
172 }
166 } 173 }
167 } 174 }
168 resolution 175 None
169 } 176 }
170 177
171 pub(crate) fn resolve_path_as_macro( 178 pub(crate) fn resolve_path_in_type_ns_fully(
172 &self, 179 &self,
173 db: &impl HirDatabase, 180 db: &impl HirDatabase,
174 path: &Path, 181 path: &Path,
175 ) -> Option<MacroDef> { 182 ) -> Option<TypeNs> {
176 let (item_map, module) = self.module()?; 183 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
177 item_map.resolve_path(db, module, path).0.get_macros() 184 if unresolved.is_some() {
185 return None;
186 }
187 Some(res)
178 } 188 }
179 189
180 /// Returns the resolved path segments 190 pub(crate) fn resolve_path_in_value_ns(
181 /// Which may be fully resolved, empty or partially resolved. 191 &self,
182 pub(crate) fn resolve_path_segments(&self, db: &impl HirDatabase, path: &Path) -> PathResult { 192 db: &impl HirDatabase,
183 if let Some(name) = path.as_ident() { 193 path: &Path,
184 PathResult::from_resolution(self.resolve_name(db, name)) 194 ) -> Option<ValueOrPartial> {
185 } else if path.is_self() { 195 let n_segments = path.segments.len();
186 PathResult::from_resolution(self.resolve_name(db, &SELF_PARAM)) 196 let tmp = SELF_PARAM;
187 } else { 197 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
188 let (item_map, module) = match self.module() { 198 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
189 Some(it) => it, 199 for scope in self.scopes.iter().rev() {
190 None => return PathResult::empty(), 200 match scope {
191 }; 201 Scope::ExprScope(_) | Scope::GenericParams(_) | Scope::ImplBlockScope(_)
192 let (module_res, segment_index) = item_map.resolve_path(db, module, path); 202 if skip_to_mod =>
193 203 {
194 let def = module_res.map(Resolution::Def); 204 continue
195 205 }
196 if let Some(index) = segment_index { 206
197 PathResult::from_resolution_with_index(def, index) 207 Scope::ExprScope(scope) if n_segments <= 1 => {
198 } else { 208 let entry = scope
199 PathResult::from_resolution(def) 209 .expr_scopes
210 .entries(scope.scope_id)
211 .iter()
212 .find(|entry| entry.name() == first_name);
213
214 if let Some(e) = entry {
215 return Some(ValueOrPartial::ValueNs(ValueNs::LocalBinding(e.pat())));
216 }
217 }
218 Scope::ExprScope(_) => continue,
219
220 Scope::GenericParams(params) if n_segments > 1 => {
221 if let Some(param) = params.find_by_name(first_name) {
222 let ty = TypeNs::GenericParam(param.idx);
223 return Some(ValueOrPartial::Partial(ty, 1));
224 }
225 }
226 Scope::GenericParams(_) => continue,
227
228 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
229 if first_name == &SELF_TYPE {
230 let ty = TypeNs::SelfType(*impl_);
231 return Some(ValueOrPartial::Partial(ty, 1));
232 }
233 }
234 Scope::ImplBlockScope(_) => continue,
235
236 Scope::ModuleScope(m) => {
237 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
238 return match idx {
239 None => {
240 let value = match module_def.take_values()? {
241 ModuleDef::Function(it) => ValueNs::Function(it),
242 ModuleDef::Adt(Adt::Struct(it)) => ValueNs::Struct(it),
243 ModuleDef::EnumVariant(it) => ValueNs::EnumVariant(it),
244 ModuleDef::Const(it) => ValueNs::Const(it),
245 ModuleDef::Static(it) => ValueNs::Static(it),
246
247 ModuleDef::Adt(Adt::Enum(_))
248 | ModuleDef::Adt(Adt::Union(_))
249 | ModuleDef::Trait(_)
250 | ModuleDef::TypeAlias(_)
251 | ModuleDef::BuiltinType(_)
252 | ModuleDef::Module(_) => return None,
253 };
254 Some(ValueOrPartial::ValueNs(value))
255 }
256 Some(idx) => {
257 let ty = match module_def.take_types()? {
258 ModuleDef::Adt(it) => TypeNs::Adt(it),
259 ModuleDef::Trait(it) => TypeNs::Trait(it),
260 ModuleDef::TypeAlias(it) => TypeNs::TypeAlias(it),
261 ModuleDef::BuiltinType(it) => TypeNs::BuiltinType(it),
262
263 ModuleDef::Module(_)
264 | ModuleDef::Function(_)
265 | ModuleDef::EnumVariant(_)
266 | ModuleDef::Const(_)
267 | ModuleDef::Static(_) => return None,
268 };
269 Some(ValueOrPartial::Partial(ty, idx))
270 }
271 };
272 }
200 } 273 }
201 } 274 }
275 None
202 } 276 }
203 277
204 /// Returns the fully resolved path if we were able to resolve it. 278 pub(crate) fn resolve_path_in_value_ns_fully(
205 /// otherwise returns `PerNs::none`
206 pub(crate) fn resolve_path_without_assoc_items(
207 &self, 279 &self,
208 db: &impl HirDatabase, 280 db: &impl HirDatabase,
209 path: &Path, 281 path: &Path,
210 ) -> PerNs<Resolution> { 282 ) -> Option<ValueNs> {
211 // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise 283 match self.resolve_path_in_value_ns(db, path)? {
212 self.resolve_path_segments(db, path).into_fully_resolved() 284 ValueOrPartial::ValueNs(it) => Some(it),
285 ValueOrPartial::Partial(..) => None,
286 }
213 } 287 }
214 288
215 pub(crate) fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<Resolution>> { 289 pub(crate) fn resolve_path_as_macro(
216 let mut names = FxHashMap::default(); 290 &self,
291 db: &impl HirDatabase,
292 path: &Path,
293 ) -> Option<MacroDef> {
294 let (item_map, module) = self.module()?;
295 item_map.resolve_path(db, module, path).0.get_macros()
296 }
297
298 pub(crate) fn process_all_names(
299 &self,
300 db: &impl HirDatabase,
301 f: &mut dyn FnMut(Name, ScopeDef),
302 ) {
217 for scope in self.scopes.iter().rev() { 303 for scope in self.scopes.iter().rev() {
218 scope.collect_names(db, &mut |name, res| { 304 scope.process_names(db, f);
219 let current: &mut PerNs<Resolution> = names.entry(name).or_default();
220 if current.types.is_none() {
221 current.types = res.types;
222 }
223 if current.values.is_none() {
224 current.values = res.values;
225 }
226 if current.macros.is_none() {
227 current.macros = res.macros;
228 }
229 });
230 } 305 }
231 names
232 } 306 }
233 307
234 pub(crate) fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<Trait> { 308 pub(crate) fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<Trait> {
@@ -301,41 +375,28 @@ impl Resolver {
301 } 375 }
302} 376}
303 377
304impl Scope { 378/// For IDE only
305 fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> { 379pub enum ScopeDef {
306 match self { 380 ModuleDef(ModuleDef),
307 Scope::ModuleScope(m) => { 381 MacroDef(MacroDef),
308 if name == &SELF_PARAM { 382 GenericParam(u32),
309 PerNs::types(Resolution::Def(m.crate_def_map.mk_module(m.module_id).into())) 383 SelfType(ImplBlock),
310 } else { 384 LocalBinding(PatId),
311 m.crate_def_map 385 Unknown,
312 .resolve_name_in_module(db, m.module_id, name) 386}
313 .map(Resolution::Def) 387
314 } 388impl From<PerNs<ModuleDef>> for ScopeDef {
315 } 389 fn from(def: PerNs<ModuleDef>) -> Self {
316 Scope::GenericParams(gp) => match gp.find_by_name(name) { 390 def.take_types()
317 Some(gp) => PerNs::types(Resolution::GenericParam(gp.idx)), 391 .or_else(|| def.take_values())
318 None => PerNs::none(), 392 .map(ScopeDef::ModuleDef)
319 }, 393 .or_else(|| def.get_macros().map(ScopeDef::MacroDef))
320 Scope::ImplBlockScope(i) => { 394 .unwrap_or(ScopeDef::Unknown)
321 if name == &SELF_TYPE {
322 PerNs::types(Resolution::SelfType(*i))
323 } else {
324 PerNs::none()
325 }
326 }
327 Scope::ExprScope(e) => {
328 let entry =
329 e.expr_scopes.entries(e.scope_id).iter().find(|entry| entry.name() == name);
330 match entry {
331 Some(e) => PerNs::values(Resolution::LocalBinding(e.pat())),
332 None => PerNs::none(),
333 }
334 }
335 }
336 } 395 }
396}
337 397
338 fn collect_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, PerNs<Resolution>)) { 398impl Scope {
399 fn process_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
339 match self { 400 match self {
340 Scope::ModuleScope(m) => { 401 Scope::ModuleScope(m) => {
341 // FIXME: should we provide `self` here? 402 // FIXME: should we provide `self` here?
@@ -346,32 +407,32 @@ impl Scope {
346 // }), 407 // }),
347 // ); 408 // );
348 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { 409 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| {
349 f(name.clone(), res.def.map(Resolution::Def)); 410 f(name.clone(), res.def.into());
350 }); 411 });
351 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 412 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
352 f(name.clone(), PerNs::macros(macro_)); 413 f(name.clone(), ScopeDef::MacroDef(macro_));
353 }); 414 });
354 m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| { 415 m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| {
355 f(name.clone(), PerNs::types(Resolution::Def(*def))); 416 f(name.clone(), ScopeDef::ModuleDef(*def));
356 }); 417 });
357 if let Some(prelude) = m.crate_def_map.prelude() { 418 if let Some(prelude) = m.crate_def_map.prelude() {
358 let prelude_def_map = db.crate_def_map(prelude.krate); 419 let prelude_def_map = db.crate_def_map(prelude.krate);
359 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { 420 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| {
360 f(name.clone(), res.def.map(Resolution::Def)); 421 f(name.clone(), res.def.into());
361 }); 422 });
362 } 423 }
363 } 424 }
364 Scope::GenericParams(gp) => { 425 Scope::GenericParams(gp) => {
365 for param in &gp.params { 426 for param in &gp.params {
366 f(param.name.clone(), PerNs::types(Resolution::GenericParam(param.idx))) 427 f(param.name.clone(), ScopeDef::GenericParam(param.idx))
367 } 428 }
368 } 429 }
369 Scope::ImplBlockScope(i) => { 430 Scope::ImplBlockScope(i) => {
370 f(SELF_TYPE, PerNs::types(Resolution::SelfType(*i))); 431 f(SELF_TYPE, ScopeDef::SelfType(*i));
371 } 432 }
372 Scope::ExprScope(e) => { 433 Scope::ExprScope(e) => {
373 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { 434 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| {
374 f(e.name().clone(), PerNs::values(Resolution::LocalBinding(e.pat()))); 435 f(e.name().clone(), ScopeDef::LocalBinding(e.pat()));
375 }); 436 });
376 } 437 }
377 } 438 }
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 65b304b43..cff55b640 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -15,7 +15,7 @@ use ra_syntax::{
15 SyntaxKind::*, 15 SyntaxKind::*,
16 SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, 16 SyntaxNode, SyntaxNodePtr, TextRange, TextUnit,
17}; 17};
18use rustc_hash::{FxHashMap, FxHashSet}; 18use rustc_hash::FxHashSet;
19 19
20use crate::{ 20use crate::{
21 db::HirDatabase, 21 db::HirDatabase,
@@ -27,9 +27,10 @@ use crate::{
27 ids::LocationCtx, 27 ids::LocationCtx,
28 name, 28 name,
29 path::{PathKind, PathSegment}, 29 path::{PathKind, PathSegment},
30 resolve::{ScopeDef, TypeNs, ValueNs},
30 ty::method_resolution::implements_trait, 31 ty::method_resolution::implements_trait,
31 AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef, 32 AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef,
32 Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty, 33 Module, Name, Path, Resolver, Static, Struct, Trait, Ty,
33}; 34};
34 35
35/// Locates the module by `FileId`. Picks topmost module in the file. 36/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -301,8 +302,41 @@ impl SourceAnalyzer {
301 &self, 302 &self,
302 db: &impl HirDatabase, 303 db: &impl HirDatabase,
303 path: &crate::Path, 304 path: &crate::Path,
304 ) -> PerNs<crate::Resolution> { 305 ) -> Option<PathResolution> {
305 self.resolver.resolve_path_without_assoc_items(db, path) 306 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty {
307 TypeNs::SelfType(it) => PathResolution::SelfType(it),
308 TypeNs::GenericParam(it) => PathResolution::GenericParam(it),
309 TypeNs::Adt(it) => PathResolution::Def(it.into()),
310 TypeNs::EnumVariant(it) => PathResolution::Def(it.into()),
311 TypeNs::TypeAlias(it) => PathResolution::Def(it.into()),
312 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
313 TypeNs::Trait(it) => PathResolution::Def(it.into()),
314 });
315 let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| {
316 let res = match val {
317 ValueNs::LocalBinding(it) => {
318 // We get a `PatId` from resolver, but it actually can only
319 // point at `BindPat`, and not at the arbitrary pattern.
320 let pat_ptr = self
321 .body_source_map
322 .as_ref()?
323 .pat_syntax(it)?
324 .ast // FIXME: ignoring file_id here is definitelly wrong
325 .map_a(|ptr| ptr.cast::<ast::BindPat>().unwrap());
326 PathResolution::LocalBinding(pat_ptr)
327 }
328 ValueNs::Function(it) => PathResolution::Def(it.into()),
329 ValueNs::Const(it) => PathResolution::Def(it.into()),
330 ValueNs::Static(it) => PathResolution::Def(it.into()),
331 ValueNs::Struct(it) => PathResolution::Def(it.into()),
332 ValueNs::EnumVariant(it) => PathResolution::Def(it.into()),
333 };
334 Some(res)
335 });
336
337 let items =
338 self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def);
339 types.or(values).or(items)
306 } 340 }
307 341
308 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { 342 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
@@ -319,25 +353,7 @@ impl SourceAnalyzer {
319 } 353 }
320 } 354 }
321 let hir_path = crate::Path::from_ast(path.clone())?; 355 let hir_path = crate::Path::from_ast(path.clone())?;
322 let res = self.resolver.resolve_path_without_assoc_items(db, &hir_path); 356 self.resolve_hir_path(db, &hir_path)
323 let res = res.clone().take_types().or_else(|| res.take_values())?;
324 let res = match res {
325 crate::Resolution::Def(it) => PathResolution::Def(it),
326 crate::Resolution::LocalBinding(it) => {
327 // We get a `PatId` from resolver, but it actually can only
328 // point at `BindPat`, and not at the arbitrary pattern.
329 let pat_ptr = self
330 .body_source_map
331 .as_ref()?
332 .pat_syntax(it)?
333 .ast // FIXME: ignoring file_id here is definitelly wrong
334 .map_a(|ptr| ptr.cast::<ast::BindPat>().unwrap());
335 PathResolution::LocalBinding(pat_ptr)
336 }
337 crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),
338 crate::Resolution::SelfType(it) => PathResolution::SelfType(it),
339 };
340 Some(res)
341 } 357 }
342 358
343 pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> { 359 pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option<ScopeEntryWithSyntax> {
@@ -360,8 +376,8 @@ impl SourceAnalyzer {
360 }) 376 })
361 } 377 }
362 378
363 pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap<Name, PerNs<crate::Resolution>> { 379 pub fn process_all_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
364 self.resolver.all_names(db) 380 self.resolver.process_all_names(db, f)
365 } 381 }
366 382
367 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { 383 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 540a99b15..3ee083a04 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -45,11 +45,10 @@ use crate::{
45 name, 45 name,
46 nameres::Namespace, 46 nameres::Namespace,
47 path::{GenericArg, GenericArgs, PathKind, PathSegment}, 47 path::{GenericArg, GenericArgs, PathKind, PathSegment},
48 resolve::{Resolution, Resolver}, 48 resolve::{Resolver, TypeNs, ValueNs, ValueOrPartial},
49 ty::infer::diagnostics::InferenceDiagnostic, 49 ty::infer::diagnostics::InferenceDiagnostic,
50 type_ref::{Mutability, TypeRef}, 50 type_ref::{Mutability, TypeRef},
51 Adt, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, ModuleDef, Name, Path, 51 Adt, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, Name, Path, StructField,
52 StructField,
53}; 52};
54 53
55mod unify; 54mod unify;
@@ -472,141 +471,138 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
472 } 471 }
473 472
474 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> { 473 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> {
475 let resolved = resolver.resolve_path_segments(self.db, &path); 474 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?;
476 475
477 let (def, remaining_index) = resolved.into_inner(); 476 let (value, self_subst) = match value_or_partial {
477 ValueOrPartial::ValueNs(it) => (it, None),
478 ValueOrPartial::Partial(def, remaining_index) => {
479 self.resolve_assoc_item(def, path, remaining_index, id)?
480 }
481 };
478 482
479 log::debug!( 483 let typable: TypableDef = match value {
480 "path {:?} resolved to {:?} with remaining index {:?}", 484 ValueNs::LocalBinding(pat) => {
481 path, 485 let ty = self.result.type_of_pat.get(pat)?.clone();
482 def, 486 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
483 remaining_index 487 return Some(ty);
484 ); 488 }
489 ValueNs::Function(it) => it.into(),
490 ValueNs::Const(it) => it.into(),
491 ValueNs::Static(it) => it.into(),
492 ValueNs::Struct(it) => it.into(),
493 ValueNs::EnumVariant(it) => it.into(),
494 };
485 495
486 // if the remaining_index is None, we expect the path 496 let mut ty = self.db.type_for_def(typable, Namespace::Values);
487 // to be fully resolved, in this case we continue with 497 if let Some(self_subst) = self_subst {
488 // the default by attempting to `take_values´ from the resolution. 498 ty = ty.subst(&self_subst);
489 // Otherwise the path was partially resolved, which means 499 }
490 // we might have resolved into a type for which
491 // we may find some associated item starting at the
492 // path.segment pointed to by `remaining_index´
493 let mut resolved =
494 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
495 500
496 let remaining_index = remaining_index.unwrap_or_else(|| path.segments.len()); 501 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
497 let mut actual_def_ty: Option<Ty> = None; 502 let ty = ty.subst(&substs);
503 let ty = self.insert_type_vars(ty);
504 let ty = self.normalize_associated_types_in(ty);
505 Some(ty)
506 }
507
508 fn resolve_assoc_item(
509 &mut self,
510 mut def: TypeNs,
511 path: &Path,
512 remaining_index: usize,
513 id: ExprOrPatId,
514 ) -> Option<(ValueNs, Option<Substs>)> {
515 assert!(remaining_index < path.segments.len());
516 let krate = self.resolver.krate()?;
517
518 let mut ty = Ty::Unknown;
498 519
499 let krate = resolver.krate()?;
500 // resolve intermediate segments 520 // resolve intermediate segments
501 for (i, segment) in path.segments[remaining_index..].iter().enumerate() { 521 for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
502 let ty = match resolved { 522 let is_last_segment = i == path.segments[remaining_index..].len() - 1;
503 Resolution::Def(def) => { 523 ty = {
504 // FIXME resolve associated items from traits as well 524 let typable: TypableDef = match def {
505 let typable: Option<TypableDef> = def.into(); 525 TypeNs::Adt(it) => it.into(),
506 let typable = typable?; 526 TypeNs::TypeAlias(it) => it.into(),
507 527 TypeNs::BuiltinType(it) => it.into(),
508 let ty = self.db.type_for_def(typable, Namespace::Types); 528 // FIXME associated item of traits, generics, and Self
509 529 TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => {
510 // For example, this substs will take `Gen::*<u32>*::make` 530 return None;
511 assert!(remaining_index > 0); 531 }
512 let substs = Ty::substs_from_path_segment( 532 // FIXME: report error here
513 self.db, 533 TypeNs::EnumVariant(_) => return None,
514 &self.resolver, 534 };
515 &path.segments[remaining_index + i - 1], 535
516 typable, 536 let ty = self.db.type_for_def(typable, Namespace::Types);
517 ); 537
518 538 // For example, this substs will take `Gen::*<u32>*::make`
519 ty.subst(&substs) 539 assert!(remaining_index > 0);
520 } 540 let substs = Ty::substs_from_path_segment(
521 Resolution::LocalBinding(_) => { 541 self.db,
522 // can't have a local binding in an associated item path 542 &self.resolver,
523 return None; 543 &path.segments[remaining_index + i - 1],
524 } 544 typable,
525 Resolution::GenericParam(..) => { 545 );
526 // FIXME associated item of generic param 546 ty.subst(&substs)
527 return None;
528 }
529 Resolution::SelfType(_) => {
530 // FIXME associated item of self type
531 return None;
532 }
533 }; 547 };
548 if is_last_segment {
549 break;
550 }
534 551
535 // Attempt to find an impl_item for the type which has a name matching 552 // Attempt to find an impl_item for the type which has a name matching
536 // the current segment 553 // the current segment
537 log::debug!("looking for path segment: {:?}", segment); 554 log::debug!("looking for path segment: {:?}", segment);
538 555
539 actual_def_ty = Some(ty.clone()); 556 let ty = mem::replace(&mut ty, Ty::Unknown);
540 557 def = ty.iterate_impl_items(self.db, krate, |item| {
541 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, krate, |item| { 558 match item {
542 let matching_def: Option<crate::ModuleDef> = match item { 559 crate::ImplItem::Method(_) => None,
543 crate::ImplItem::Method(func) => { 560 crate::ImplItem::Const(_) => None,
544 if segment.name == func.name(self.db) {
545 Some(func.into())
546 } else {
547 None
548 }
549 }
550
551 crate::ImplItem::Const(konst) => {
552 let data = konst.data(self.db);
553 if segment.name == *data.name() {
554 Some(konst.into())
555 } else {
556 None
557 }
558 }
559 561
560 // FIXME: Resolve associated types 562 // FIXME: Resolve associated types
561 crate::ImplItem::TypeAlias(_) => None, 563 crate::ImplItem::TypeAlias(_) => {
562 }; 564 // Some(TypeNs::TypeAlias(..))
563 match matching_def { 565 None::<TypeNs>
564 Some(_) => {
565 self.write_assoc_resolution(id, item);
566 matching_def
567 } 566 }
568 None => None,
569 } 567 }
570 })?; 568 })?;
571
572 resolved = Resolution::Def(item);
573 } 569 }
574 570
575 match resolved { 571 let segment = path.segments.last().unwrap();
576 Resolution::Def(def) => { 572 let def = ty.clone().iterate_impl_items(self.db, krate, |item| {
577 let typable: Option<TypableDef> = def.into(); 573 let matching_def: Option<ValueNs> = match item {
578 let typable = typable?; 574 crate::ImplItem::Method(func) => {
579 let mut ty = self.db.type_for_def(typable, Namespace::Values); 575 if segment.name == func.name(self.db) {
580 if let Some(sts) = self.find_self_types(&def, actual_def_ty) { 576 Some(ValueNs::Function(func))
581 ty = ty.subst(&sts); 577 } else {
578 None
579 }
582 } 580 }
583 581
584 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 582 crate::ImplItem::Const(konst) => {
585 let ty = ty.subst(&substs); 583 let data = konst.data(self.db);
586 let ty = self.insert_type_vars(ty); 584 if segment.name == *data.name() {
587 let ty = self.normalize_associated_types_in(ty); 585 Some(ValueNs::Const(konst))
588 Some(ty) 586 } else {
589 } 587 None
590 Resolution::LocalBinding(pat) => { 588 }
591 let ty = self.result.type_of_pat.get(pat)?.clone(); 589 }
592 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 590 crate::ImplItem::TypeAlias(_) => None,
593 Some(ty) 591 };
594 } 592 match matching_def {
595 Resolution::GenericParam(..) => { 593 Some(_) => {
596 // generic params can't refer to values... yet 594 self.write_assoc_resolution(id, item);
597 None 595 matching_def
598 } 596 }
599 Resolution::SelfType(_) => { 597 None => None,
600 log::error!("path expr {:?} resolved to Self type in values ns", path);
601 None
602 } 598 }
603 } 599 })?;
600 let self_types = self.find_self_types(&def, ty);
601 Some((def, self_types))
604 } 602 }
605 603
606 fn find_self_types(&self, def: &ModuleDef, actual_def_ty: Option<Ty>) -> Option<Substs> { 604 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
607 let actual_def_ty = actual_def_ty?; 605 if let ValueNs::Function(func) = def {
608
609 if let crate::ModuleDef::Function(func) = def {
610 // We only do the infer if parent has generic params 606 // We only do the infer if parent has generic params
611 let gen = func.generic_params(self.db); 607 let gen = func.generic_params(self.db);
612 if gen.count_parent_params() == 0 { 608 if gen.count_parent_params() == 0 {
@@ -641,30 +637,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
641 None => return (Ty::Unknown, None), 637 None => return (Ty::Unknown, None),
642 }; 638 };
643 let resolver = &self.resolver; 639 let resolver = &self.resolver;
644 let typable: Option<TypableDef> = 640 let def: TypableDef =
645 // FIXME: this should resolve assoc items as well, see this example: 641 // FIXME: this should resolve assoc items as well, see this example:
646 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 642 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
647 match resolver.resolve_path_without_assoc_items(self.db, &path).take_types() { 643 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
648 Some(Resolution::Def(def)) => def.into(), 644 Some(TypeNs::Adt(Adt::Struct(it))) => it.into(),
649 Some(Resolution::LocalBinding(..)) => { 645 Some(TypeNs::Adt(Adt::Union(it))) => it.into(),
650 // this cannot happen 646 Some(TypeNs::EnumVariant(it)) => it.into(),
651 log::error!("path resolved to local binding in type ns"); 647 Some(TypeNs::TypeAlias(it)) => it.into(),
652 return (Ty::Unknown, None); 648
653 } 649 Some(TypeNs::SelfType(_)) |
654 Some(Resolution::GenericParam(..)) => { 650 Some(TypeNs::GenericParam(_)) |
655 // generic params can't be used in struct literals 651 Some(TypeNs::BuiltinType(_)) |
656 return (Ty::Unknown, None); 652 Some(TypeNs::Trait(_)) |
657 } 653 Some(TypeNs::Adt(Adt::Enum(_))) |
658 Some(Resolution::SelfType(..)) => { 654 None => {
659 // FIXME this is allowed in an impl for a struct, handle this 655 return (Ty::Unknown, None)
660 return (Ty::Unknown, None);
661 } 656 }
662 None => return (Ty::Unknown, None),
663 }; 657 };
664 let def = match typable {
665 None => return (Ty::Unknown, None),
666 Some(it) => it,
667 };
668 // FIXME remove the duplication between here and `Ty::from_path`? 658 // FIXME remove the duplication between here and `Ty::from_path`?
669 let substs = Ty::substs_from_path(self.db, resolver, path, def); 659 let substs = Ty::substs_from_path(self.db, resolver, path, def);
670 match def { 660 match def {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 946e9e9fb..3fdb2ca92 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -19,7 +19,7 @@ use crate::{
19 generics::{GenericDef, WherePredicate}, 19 generics::{GenericDef, WherePredicate},
20 nameres::Namespace, 20 nameres::Namespace,
21 path::{GenericArg, PathSegment}, 21 path::{GenericArg, PathSegment},
22 resolve::{Resolution, Resolver}, 22 resolve::{Resolver, TypeNs},
23 ty::Adt, 23 ty::Adt,
24 type_ref::{TypeBound, TypeRef}, 24 type_ref::{TypeBound, TypeRef},
25 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, 25 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField,
@@ -88,16 +88,47 @@ impl Ty {
88 88
89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
90 // Resolve the path (in type namespace) 90 // Resolve the path (in type namespace)
91 let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner(); 91 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) {
92 let resolution = resolution.take_types(); 92 Some(it) => it,
93 93 None => return Ty::Unknown,
94 let def = match resolution { 94 };
95 Some(Resolution::Def(def)) => def, 95
96 Some(Resolution::LocalBinding(..)) => { 96 let typable: TypableDef = match resolution {
97 // this should never happen 97 TypeNs::Trait(trait_) => {
98 panic!("path resolved to local binding in type ns"); 98 let segment = match remaining_index {
99 None => path.segments.last().expect("resolved path has at least one element"),
100 Some(i) => &path.segments[i - 1],
101 };
102 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
103 return if let Some(remaining_index) = remaining_index {
104 if remaining_index == path.segments.len() - 1 {
105 let segment = &path.segments[remaining_index];
106 match trait_ref
107 .trait_
108 .associated_type_by_name_including_super_traits(db, &segment.name)
109 {
110 Some(associated_ty) => {
111 // FIXME handle type parameters on the segment
112 Ty::Projection(ProjectionTy {
113 associated_ty,
114 parameters: trait_ref.substs,
115 })
116 }
117 None => {
118 // associated type not found
119 Ty::Unknown
120 }
121 }
122 } else {
123 // FIXME more than one segment remaining, is this possible?
124 Ty::Unknown
125 }
126 } else {
127 // FIXME dyn Trait without the dyn
128 Ty::Unknown
129 };
99 } 130 }
100 Some(Resolution::GenericParam(idx)) => { 131 TypeNs::GenericParam(idx) => {
101 if remaining_index.is_some() { 132 if remaining_index.is_some() {
102 // e.g. T::Item 133 // e.g. T::Item
103 return Ty::Unknown; 134 return Ty::Unknown;
@@ -111,57 +142,24 @@ impl Ty {
111 .clone(), 142 .clone(),
112 }; 143 };
113 } 144 }
114 Some(Resolution::SelfType(impl_block)) => { 145 TypeNs::SelfType(impl_block) => {
115 if remaining_index.is_some() { 146 if remaining_index.is_some() {
116 // e.g. Self::Item 147 // e.g. Self::Item
117 return Ty::Unknown; 148 return Ty::Unknown;
118 } 149 }
119 return impl_block.target_ty(db); 150 return impl_block.target_ty(db);
120 } 151 }
121 None => { 152
122 // path did not resolve 153 TypeNs::Adt(it) => it.into(),
123 return Ty::Unknown; 154 TypeNs::BuiltinType(it) => it.into(),
124 } 155 TypeNs::TypeAlias(it) => it.into(),
156 // FIXME: report error
157 TypeNs::EnumVariant(_) => return Ty::Unknown,
125 }; 158 };
126 159
127 if let ModuleDef::Trait(trait_) = def { 160 let ty = db.type_for_def(typable, Namespace::Types);
128 let segment = match remaining_index { 161 let substs = Ty::substs_from_path(db, resolver, path, typable);
129 None => path.segments.last().expect("resolved path has at least one element"), 162 ty.subst(&substs)
130 Some(i) => &path.segments[i - 1],
131 };
132 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
133 if let Some(remaining_index) = remaining_index {
134 if remaining_index == path.segments.len() - 1 {
135 let segment = &path.segments[remaining_index];
136 let associated_ty = match trait_ref
137 .trait_
138 .associated_type_by_name_including_super_traits(db, &segment.name)
139 {
140 Some(t) => t,
141 None => {
142 // associated type not found
143 return Ty::Unknown;
144 }
145 };
146 // FIXME handle type parameters on the segment
147 Ty::Projection(ProjectionTy { associated_ty, parameters: trait_ref.substs })
148 } else {
149 // FIXME more than one segment remaining, is this possible?
150 Ty::Unknown
151 }
152 } else {
153 // FIXME dyn Trait without the dyn
154 Ty::Unknown
155 }
156 } else {
157 let typable: TypableDef = match def.into() {
158 None => return Ty::Unknown,
159 Some(it) => it,
160 };
161 let ty = db.type_for_def(typable, Namespace::Types);
162 let substs = Ty::substs_from_path(db, resolver, path, typable);
163 ty.subst(&substs)
164 }
165 } 163 }
166 164
167 pub(super) fn substs_from_path_segment( 165 pub(super) fn substs_from_path_segment(
@@ -278,8 +276,8 @@ impl TraitRef {
278 path: &Path, 276 path: &Path,
279 explicit_self_ty: Option<Ty>, 277 explicit_self_ty: Option<Ty>,
280 ) -> Option<Self> { 278 ) -> Option<Self> {
281 let resolved = match resolver.resolve_path_without_assoc_items(db, &path).take_types()? { 279 let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? {
282 Resolution::Def(ModuleDef::Trait(tr)) => tr, 280 TypeNs::Trait(tr) => tr,
283 _ => return None, 281 _ => return None,
284 }; 282 };
285 let segment = path.segments.last().expect("path should have at least one segment"); 283 let segment = path.segments.last().expect("path should have at least one segment");