aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs8
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs10
-rw-r--r--crates/ra_ide_api/src/completion/complete_pattern.rs14
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs5
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs95
13 files changed, 534 insertions, 464 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");
diff --git a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
index 6fcef4a72..0cbe4abf7 100644
--- a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
+++ b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
@@ -3,11 +3,11 @@ use crate::completion::{CompletionContext, Completions};
3pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) { 3pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
4 // Show only macros in top level. 4 // Show only macros in top level.
5 if ctx.is_new_item { 5 if ctx.is_new_item {
6 for (name, res) in ctx.analyzer.all_names(ctx.db) { 6 ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
7 if res.get_macros().is_some() { 7 if let hir::ScopeDef::MacroDef(mac) = res {
8 acc.add_resolution(ctx, name.to_string(), &res.only_macros()); 8 acc.add_macro(ctx, Some(name.to_string()), mac);
9 } 9 }
10 } 10 })
11 } 11 }
12} 12}
13 13
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 4d3414f33..5ee2864dc 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -1,4 +1,4 @@
1use hir::{Adt, Either, Resolution}; 1use hir::{Adt, Either, PathResolution};
2use ra_syntax::AstNode; 2use ra_syntax::AstNode;
3use test_utils::tested_by; 3use test_utils::tested_by;
4 4
@@ -9,15 +9,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
9 Some(path) => path.clone(), 9 Some(path) => path.clone(),
10 _ => return, 10 _ => return,
11 }; 11 };
12 let def = match ctx.analyzer.resolve_hir_path(ctx.db, &path).take_types() { 12 let def = match dbg!(ctx.analyzer.resolve_hir_path(ctx.db, &path)) {
13 Some(Resolution::Def(def)) => def, 13 Some(PathResolution::Def(def)) => def,
14 _ => return, 14 _ => return,
15 }; 15 };
16 match def { 16 match def {
17 hir::ModuleDef::Module(module) => { 17 hir::ModuleDef::Module(module) => {
18 let module_scope = module.scope(ctx.db); 18 let module_scope = module.scope(ctx.db);
19 for (name, res) in module_scope.entries() { 19 for (name, res) in module_scope.entries() {
20 if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.as_ref().take_types() { 20 if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.take_types() {
21 if ctx.use_item_syntax.is_some() { 21 if ctx.use_item_syntax.is_some() {
22 tested_by!(dont_complete_primitive_in_use); 22 tested_by!(dont_complete_primitive_in_use);
23 continue; 23 continue;
@@ -34,7 +34,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
34 } 34 }
35 } 35 }
36 } 36 }
37 acc.add_resolution(ctx, name.to_string(), &res.def.map(hir::Resolution::Def)); 37 acc.add_resolution(ctx, name.to_string(), &res.def.into());
38 } 38 }
39 } 39 }
40 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { 40 hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
diff --git a/crates/ra_ide_api/src/completion/complete_pattern.rs b/crates/ra_ide_api/src/completion/complete_pattern.rs
index fb7f9feb8..c17b5b7ee 100644
--- a/crates/ra_ide_api/src/completion/complete_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_pattern.rs
@@ -7,22 +7,20 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
7 } 7 }
8 // FIXME: ideally, we should look at the type we are matching against and 8 // FIXME: ideally, we should look at the type we are matching against and
9 // suggest variants + auto-imports 9 // suggest variants + auto-imports
10 let names = ctx.analyzer.all_names(ctx.db); 10 ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
11 for (name, res) in names.into_iter() { 11 let def = match &res {
12 let r = res.as_ref(); 12 hir::ScopeDef::ModuleDef(def) => def,
13 let def = match r.take_types().or_else(|| r.take_values()) { 13 _ => return,
14 Some(hir::Resolution::Def(def)) => def,
15 _ => continue,
16 }; 14 };
17 match def { 15 match def {
18 hir::ModuleDef::Adt(hir::Adt::Enum(..)) 16 hir::ModuleDef::Adt(hir::Adt::Enum(..))
19 | hir::ModuleDef::EnumVariant(..) 17 | hir::ModuleDef::EnumVariant(..)
20 | hir::ModuleDef::Const(..) 18 | hir::ModuleDef::Const(..)
21 | hir::ModuleDef::Module(..) => (), 19 | hir::ModuleDef::Module(..) => (),
22 _ => continue, 20 _ => return,
23 } 21 }
24 acc.add_resolution(ctx, name.to_string(), &res) 22 acc.add_resolution(ctx, name.to_string(), &res)
25 } 23 });
26} 24}
27 25
28#[cfg(test)] 26#[cfg(test)]
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 2ea22876f..c1f48b026 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -10,8 +10,9 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
10 return; 10 return;
11 } 11 }
12 12
13 let names = ctx.analyzer.all_names(ctx.db); 13 ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
14 names.into_iter().for_each(|(name, res)| acc.add_resolution(ctx, name.to_string(), &res)); 14 acc.add_resolution(ctx, name.to_string(), &res)
15 });
15 16
16 // auto-import 17 // auto-import
17 // We fetch ident from the original file, because we need to pre-filter auto-imports 18 // We fetch ident from the original file, because we need to pre-filter auto-imports
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 95bbd34b7..31b887492 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,5 +1,5 @@
1//! This modules takes care of rendering various defenitions as completion items. 1//! This modules takes care of rendering various definitions as completion items.
2use hir::{Docs, HasSource, HirDisplay, PerNs, Resolution, Ty, TypeWalk}; 2use hir::{Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
3use join_to_string::join; 3use join_to_string::join;
4use ra_syntax::ast::NameOwner; 4use ra_syntax::ast::NameOwner;
5use test_utils::tested_by; 5use test_utils::tested_by;
@@ -39,61 +39,77 @@ impl Completions {
39 &mut self, 39 &mut self,
40 ctx: &CompletionContext, 40 ctx: &CompletionContext,
41 local_name: String, 41 local_name: String,
42 resolution: &PerNs<Resolution>, 42 resolution: &ScopeDef,
43 ) { 43 ) {
44 use hir::ModuleDef::*; 44 use hir::ModuleDef::*;
45 45
46 if let Some(macro_) = resolution.get_macros() { 46 // if let Some(macro_) = resolution.get_macros() {
47 self.add_macro(ctx, Some(local_name.clone()), macro_); 47 // self.add_macro(ctx, Some(local_name.clone()), macro_);
48 } 48 // }
49 49
50 let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values()); 50 // let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values());
51 let def = match def { 51 // let def = match def {
52 // Only insert once if it is just a macro name 52 // // Only insert once if it is just a macro name
53 None if resolution.get_macros().is_some() => return, 53 // None if resolution.get_macros().is_some() => return,
54 None => { 54 // None => {
55 self.add(CompletionItem::new( 55 // self.add(CompletionItem::new(
56 CompletionKind::Reference, 56 // CompletionKind::Reference,
57 ctx.source_range(), 57 // ctx.source_range(),
58 local_name, 58 // local_name,
59 )); 59 // ));
60 return; 60 // return;
61 } 61 // }
62 Some(it) => it, 62 // Some(it) => it,
63 }; 63 // };
64 let mut completion_kind = CompletionKind::Reference; 64 let mut completion_kind = CompletionKind::Reference;
65 let (kind, docs) = match def { 65 let (kind, docs) = match resolution {
66 Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)), 66 ScopeDef::ModuleDef(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)),
67 Resolution::Def(Function(func)) => { 67 ScopeDef::ModuleDef(Function(func)) => {
68 return self.add_function_with_name(ctx, Some(local_name), *func); 68 return self.add_function_with_name(ctx, Some(local_name), *func);
69 } 69 }
70 Resolution::Def(Adt(hir::Adt::Struct(it))) => { 70 ScopeDef::ModuleDef(Adt(hir::Adt::Struct(it))) => {
71 (CompletionItemKind::Struct, it.docs(ctx.db)) 71 (CompletionItemKind::Struct, it.docs(ctx.db))
72 } 72 }
73 Resolution::Def(Adt(hir::Adt::Union(it))) => { 73 ScopeDef::ModuleDef(Adt(hir::Adt::Union(it))) => {
74 (CompletionItemKind::Struct, it.docs(ctx.db)) 74 (CompletionItemKind::Struct, it.docs(ctx.db))
75 } 75 }
76 Resolution::Def(Adt(hir::Adt::Enum(it))) => (CompletionItemKind::Enum, it.docs(ctx.db)), 76 ScopeDef::ModuleDef(Adt(hir::Adt::Enum(it))) => {
77 Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), 77 (CompletionItemKind::Enum, it.docs(ctx.db))
78 Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)), 78 }
79 Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)), 79 ScopeDef::ModuleDef(EnumVariant(it)) => {
80 Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)), 80 (CompletionItemKind::EnumVariant, it.docs(ctx.db))
81 Resolution::Def(TypeAlias(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), 81 }
82 Resolution::Def(BuiltinType(..)) => { 82 ScopeDef::ModuleDef(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)),
83 ScopeDef::ModuleDef(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)),
84 ScopeDef::ModuleDef(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)),
85 ScopeDef::ModuleDef(TypeAlias(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)),
86 ScopeDef::ModuleDef(BuiltinType(..)) => {
83 completion_kind = CompletionKind::BuiltinType; 87 completion_kind = CompletionKind::BuiltinType;
84 (CompletionItemKind::BuiltinType, None) 88 (CompletionItemKind::BuiltinType, None)
85 } 89 }
86 Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None), 90 ScopeDef::GenericParam(..) => (CompletionItemKind::TypeParam, None),
87 Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None), 91 ScopeDef::LocalBinding(..) => (CompletionItemKind::Binding, None),
88 Resolution::SelfType(..) => ( 92 ScopeDef::SelfType(..) => (
89 CompletionItemKind::TypeParam, // (does this need its own kind?) 93 CompletionItemKind::TypeParam, // (does this need its own kind?)
90 None, 94 None,
91 ), 95 ),
96 ScopeDef::MacroDef(mac) => {
97 self.add_macro(ctx, Some(local_name.clone()), *mac);
98 return;
99 }
100 ScopeDef::Unknown => {
101 self.add(CompletionItem::new(
102 CompletionKind::Reference,
103 ctx.source_range(),
104 local_name,
105 ));
106 return;
107 }
92 }; 108 };
93 109
94 let mut completion_item = 110 let mut completion_item =
95 CompletionItem::new(completion_kind, ctx.source_range(), local_name); 111 CompletionItem::new(completion_kind, ctx.source_range(), local_name);
96 if let Resolution::LocalBinding(pat_id) = def { 112 if let ScopeDef::LocalBinding(pat_id) = resolution {
97 let ty = ctx 113 let ty = ctx
98 .analyzer 114 .analyzer
99 .type_of_pat_by_id(ctx.db, pat_id.clone()) 115 .type_of_pat_by_id(ctx.db, pat_id.clone())
@@ -108,7 +124,12 @@ impl Completions {
108 self.add_function_with_name(ctx, None, func) 124 self.add_function_with_name(ctx, None, func)
109 } 125 }
110 126
111 fn add_macro(&mut self, ctx: &CompletionContext, name: Option<String>, macro_: hir::MacroDef) { 127 pub(crate) fn add_macro(
128 &mut self,
129 ctx: &CompletionContext,
130 name: Option<String>,
131 macro_: hir::MacroDef,
132 ) {
112 let ast_node = macro_.source(ctx.db).ast; 133 let ast_node = macro_.source(ctx.db).ast;
113 if let Some(name) = name { 134 if let Some(name) = name {
114 let detail = macro_label(&ast_node); 135 let detail = macro_label(&ast_node);