diff options
Diffstat (limited to 'crates/ra_hir/src/resolve.rs')
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 139 |
1 files changed, 124 insertions, 15 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 79b92180a..eca8e0596 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -14,9 +14,9 @@ use crate::{ | |||
14 | code_model::Crate, | 14 | code_model::Crate, |
15 | db::{DefDatabase, HirDatabase}, | 15 | db::{DefDatabase, HirDatabase}, |
16 | expr::{ExprScopes, PatId, ScopeId}, | 16 | expr::{ExprScopes, PatId, ScopeId}, |
17 | generics::GenericParams, | 17 | generics::{GenericParams, HasGenericParams}, |
18 | Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef, | 18 | Adt, Const, Container, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, |
19 | PerNs, Static, Struct, Trait, TypeAlias, | 19 | MacroDef, Module, ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #[derive(Debug, Clone, Default)] | 22 | #[derive(Debug, Clone, Default)] |
@@ -43,7 +43,7 @@ pub(crate) enum Scope { | |||
43 | /// All the items and imported names of a module | 43 | /// All the items and imported names of a module |
44 | ModuleScope(ModuleItemMap), | 44 | ModuleScope(ModuleItemMap), |
45 | /// Brings the generic parameters of an item into scope | 45 | /// Brings the generic parameters of an item into scope |
46 | GenericParams(Arc<GenericParams>), | 46 | GenericParams { def: GenericDef, params: Arc<GenericParams> }, |
47 | /// Brings `Self` in `impl` block into scope | 47 | /// Brings `Self` in `impl` block into scope |
48 | ImplBlockScope(ImplBlock), | 48 | ImplBlockScope(ImplBlock), |
49 | /// Brings `Self` in enum, struct and union definitions into scope | 49 | /// Brings `Self` in enum, struct and union definitions into scope |
@@ -141,9 +141,9 @@ impl Resolver { | |||
141 | for scope in self.scopes.iter().rev() { | 141 | for scope in self.scopes.iter().rev() { |
142 | match scope { | 142 | match scope { |
143 | Scope::ExprScope(_) => continue, | 143 | Scope::ExprScope(_) => continue, |
144 | Scope::GenericParams(_) | Scope::ImplBlockScope(_) if skip_to_mod => continue, | 144 | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, |
145 | 145 | ||
146 | Scope::GenericParams(params) => { | 146 | Scope::GenericParams { params, .. } => { |
147 | if let Some(param) = params.find_by_name(first_name) { | 147 | if let Some(param) = params.find_by_name(first_name) { |
148 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 148 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; |
149 | return Some((TypeNs::GenericParam(param.idx), idx)); | 149 | return Some((TypeNs::GenericParam(param.idx), idx)); |
@@ -212,7 +212,7 @@ impl Resolver { | |||
212 | match scope { | 212 | match scope { |
213 | Scope::AdtScope(_) | 213 | Scope::AdtScope(_) |
214 | | Scope::ExprScope(_) | 214 | | Scope::ExprScope(_) |
215 | | Scope::GenericParams(_) | 215 | | Scope::GenericParams { .. } |
216 | | Scope::ImplBlockScope(_) | 216 | | Scope::ImplBlockScope(_) |
217 | if skip_to_mod => | 217 | if skip_to_mod => |
218 | { | 218 | { |
@@ -232,13 +232,13 @@ impl Resolver { | |||
232 | } | 232 | } |
233 | Scope::ExprScope(_) => continue, | 233 | Scope::ExprScope(_) => continue, |
234 | 234 | ||
235 | Scope::GenericParams(params) if n_segments > 1 => { | 235 | Scope::GenericParams { params, .. } if n_segments > 1 => { |
236 | if let Some(param) = params.find_by_name(first_name) { | 236 | if let Some(param) = params.find_by_name(first_name) { |
237 | let ty = TypeNs::GenericParam(param.idx); | 237 | let ty = TypeNs::GenericParam(param.idx); |
238 | return Some(ResolveValueResult::Partial(ty, 1)); | 238 | return Some(ResolveValueResult::Partial(ty, 1)); |
239 | } | 239 | } |
240 | } | 240 | } |
241 | Scope::GenericParams(_) => continue, | 241 | Scope::GenericParams { .. } => continue, |
242 | 242 | ||
243 | Scope::ImplBlockScope(impl_) if n_segments > 1 => { | 243 | Scope::ImplBlockScope(impl_) if n_segments > 1 => { |
244 | if first_name == &name::SELF_TYPE { | 244 | if first_name == &name::SELF_TYPE { |
@@ -361,7 +361,7 @@ impl Resolver { | |||
361 | self.scopes | 361 | self.scopes |
362 | .iter() | 362 | .iter() |
363 | .filter_map(|scope| match scope { | 363 | .filter_map(|scope| match scope { |
364 | Scope::GenericParams(params) => Some(params), | 364 | Scope::GenericParams { params, .. } => Some(params), |
365 | _ => None, | 365 | _ => None, |
366 | }) | 366 | }) |
367 | .flat_map(|params| params.where_predicates.iter()) | 367 | .flat_map(|params| params.where_predicates.iter()) |
@@ -369,7 +369,7 @@ impl Resolver { | |||
369 | 369 | ||
370 | pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> { | 370 | pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> { |
371 | self.scopes.iter().find_map(|scope| match scope { | 371 | self.scopes.iter().find_map(|scope| match scope { |
372 | Scope::GenericParams(params) => Some(params.def), | 372 | Scope::GenericParams { def, .. } => Some(*def), |
373 | _ => None, | 373 | _ => None, |
374 | }) | 374 | }) |
375 | } | 375 | } |
@@ -381,8 +381,17 @@ impl Resolver { | |||
381 | self | 381 | self |
382 | } | 382 | } |
383 | 383 | ||
384 | pub(crate) fn push_generic_params_scope(self, params: Arc<GenericParams>) -> Resolver { | 384 | pub(crate) fn push_generic_params_scope( |
385 | self.push_scope(Scope::GenericParams(params)) | 385 | self, |
386 | db: &impl DefDatabase, | ||
387 | def: GenericDef, | ||
388 | ) -> Resolver { | ||
389 | let params = def.generic_params(db); | ||
390 | if params.params.is_empty() { | ||
391 | self | ||
392 | } else { | ||
393 | self.push_scope(Scope::GenericParams { def, params }) | ||
394 | } | ||
386 | } | 395 | } |
387 | 396 | ||
388 | pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver { | 397 | pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver { |
@@ -457,8 +466,8 @@ impl Scope { | |||
457 | }); | 466 | }); |
458 | } | 467 | } |
459 | } | 468 | } |
460 | Scope::GenericParams(gp) => { | 469 | Scope::GenericParams { params, .. } => { |
461 | for param in &gp.params { | 470 | for param in params.params.iter() { |
462 | f(param.name.clone(), ScopeDef::GenericParam(param.idx)) | 471 | f(param.name.clone(), ScopeDef::GenericParam(param.idx)) |
463 | } | 472 | } |
464 | } | 473 | } |
@@ -477,3 +486,103 @@ impl Scope { | |||
477 | } | 486 | } |
478 | } | 487 | } |
479 | } | 488 | } |
489 | |||
490 | pub(crate) trait HasResolver { | ||
491 | /// Builds a resolver for type references inside this def. | ||
492 | fn resolver(self, db: &impl DefDatabase) -> Resolver; | ||
493 | } | ||
494 | |||
495 | impl HasResolver for Module { | ||
496 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
497 | let def_map = db.crate_def_map(self.id.krate); | ||
498 | Resolver::default().push_module_scope(def_map, self.id.module_id) | ||
499 | } | ||
500 | } | ||
501 | |||
502 | impl HasResolver for Trait { | ||
503 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
504 | self.module(db).resolver(db).push_generic_params_scope(db, self.into()) | ||
505 | } | ||
506 | } | ||
507 | |||
508 | impl<T: Into<Adt>> HasResolver for T { | ||
509 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
510 | let def = self.into(); | ||
511 | def.module(db) | ||
512 | .resolver(db) | ||
513 | .push_generic_params_scope(db, def.into()) | ||
514 | .push_scope(Scope::AdtScope(def)) | ||
515 | } | ||
516 | } | ||
517 | |||
518 | impl HasResolver for Function { | ||
519 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
520 | self.container(db) | ||
521 | .map(|c| c.resolver(db)) | ||
522 | .unwrap_or_else(|| self.module(db).resolver(db)) | ||
523 | .push_generic_params_scope(db, self.into()) | ||
524 | } | ||
525 | } | ||
526 | |||
527 | impl HasResolver for DefWithBody { | ||
528 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
529 | match self { | ||
530 | DefWithBody::Const(c) => c.resolver(db), | ||
531 | DefWithBody::Function(f) => f.resolver(db), | ||
532 | DefWithBody::Static(s) => s.resolver(db), | ||
533 | } | ||
534 | } | ||
535 | } | ||
536 | |||
537 | impl HasResolver for Const { | ||
538 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
539 | self.container(db).map(|c| c.resolver(db)).unwrap_or_else(|| self.module(db).resolver(db)) | ||
540 | } | ||
541 | } | ||
542 | |||
543 | impl HasResolver for Static { | ||
544 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
545 | self.module(db).resolver(db) | ||
546 | } | ||
547 | } | ||
548 | |||
549 | impl HasResolver for TypeAlias { | ||
550 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
551 | self.container(db) | ||
552 | .map(|ib| ib.resolver(db)) | ||
553 | .unwrap_or_else(|| self.module(db).resolver(db)) | ||
554 | .push_generic_params_scope(db, self.into()) | ||
555 | } | ||
556 | } | ||
557 | |||
558 | impl HasResolver for Container { | ||
559 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
560 | match self { | ||
561 | Container::Trait(trait_) => trait_.resolver(db), | ||
562 | Container::ImplBlock(impl_block) => impl_block.resolver(db), | ||
563 | } | ||
564 | } | ||
565 | } | ||
566 | |||
567 | impl HasResolver for GenericDef { | ||
568 | fn resolver(self, db: &impl DefDatabase) -> crate::Resolver { | ||
569 | match self { | ||
570 | GenericDef::Function(inner) => inner.resolver(db), | ||
571 | GenericDef::Adt(adt) => adt.resolver(db), | ||
572 | GenericDef::Trait(inner) => inner.resolver(db), | ||
573 | GenericDef::TypeAlias(inner) => inner.resolver(db), | ||
574 | GenericDef::ImplBlock(inner) => inner.resolver(db), | ||
575 | GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db), | ||
576 | GenericDef::Const(inner) => inner.resolver(db), | ||
577 | } | ||
578 | } | ||
579 | } | ||
580 | |||
581 | impl HasResolver for ImplBlock { | ||
582 | fn resolver(self, db: &impl DefDatabase) -> Resolver { | ||
583 | self.module(db) | ||
584 | .resolver(db) | ||
585 | .push_generic_params_scope(db, self.into()) | ||
586 | .push_impl_block_scope(self) | ||
587 | } | ||
588 | } | ||