aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/resolve.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/resolve.rs')
-rw-r--r--crates/ra_hir/src/resolve.rs405
1 files changed, 233 insertions, 172 deletions
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 }