|
1 | 1 | //! Name resolution façade. |
2 | | -use std::{hash::BuildHasherDefault, sync::Arc}; |
| 2 | +use std::{fmt, hash::BuildHasherDefault, sync::Arc}; |
3 | 3 |
|
4 | 4 | use base_db::CrateId; |
5 | 5 | use hir_expand::name::{name, Name}; |
@@ -36,19 +36,34 @@ pub struct Resolver { |
36 | 36 | module_scope: ModuleItemMap, |
37 | 37 | } |
38 | 38 |
|
39 | | -#[derive(Debug, Clone)] |
| 39 | +#[derive(Clone)] |
40 | 40 | struct ModuleItemMap { |
41 | 41 | def_map: Arc<DefMap>, |
42 | 42 | module_id: LocalModuleId, |
43 | 43 | } |
44 | 44 |
|
45 | | -#[derive(Debug, Clone)] |
| 45 | +impl fmt::Debug for ModuleItemMap { |
| 46 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 47 | + f.debug_struct("ModuleItemMap").field("module_id", &self.module_id).finish() |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +#[derive(Clone)] |
46 | 52 | struct ExprScope { |
47 | 53 | owner: DefWithBodyId, |
48 | 54 | expr_scopes: Arc<ExprScopes>, |
49 | 55 | scope_id: ScopeId, |
50 | 56 | } |
51 | 57 |
|
| 58 | +impl fmt::Debug for ExprScope { |
| 59 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 60 | + f.debug_struct("ExprScope") |
| 61 | + .field("owner", &self.owner) |
| 62 | + .field("scope_id", &self.scope_id) |
| 63 | + .finish() |
| 64 | + } |
| 65 | +} |
| 66 | + |
52 | 67 | #[derive(Debug, Clone)] |
53 | 68 | enum Scope { |
54 | 69 | /// All the items and imported names of a module |
@@ -478,8 +493,72 @@ impl Resolver { |
478 | 493 | _ => None, |
479 | 494 | }) |
480 | 495 | } |
| 496 | + /// `expr_id` is required to be an expression id that comes after the top level expression scope in the given resolver |
| 497 | + #[must_use] |
| 498 | + pub fn update_to_inner_scope( |
| 499 | + &mut self, |
| 500 | + db: &dyn DefDatabase, |
| 501 | + owner: DefWithBodyId, |
| 502 | + expr_id: ExprId, |
| 503 | + ) -> UpdateGuard { |
| 504 | + #[inline(always)] |
| 505 | + fn append_expr_scope( |
| 506 | + db: &dyn DefDatabase, |
| 507 | + resolver: &mut Resolver, |
| 508 | + owner: DefWithBodyId, |
| 509 | + expr_scopes: &Arc<ExprScopes>, |
| 510 | + scope_id: ScopeId, |
| 511 | + ) { |
| 512 | + resolver.scopes.push(Scope::ExprScope(ExprScope { |
| 513 | + owner, |
| 514 | + expr_scopes: expr_scopes.clone(), |
| 515 | + scope_id, |
| 516 | + })); |
| 517 | + if let Some(block) = expr_scopes.block(scope_id) { |
| 518 | + if let Some(def_map) = db.block_def_map(block) { |
| 519 | + let root = def_map.root(); |
| 520 | + resolver |
| 521 | + .scopes |
| 522 | + .push(Scope::BlockScope(ModuleItemMap { def_map, module_id: root })); |
| 523 | + // FIXME: This adds as many module scopes as there are blocks, but resolving in each |
| 524 | + // already traverses all parents, so this is O(n²). I think we could only store the |
| 525 | + // innermost module scope instead? |
| 526 | + } |
| 527 | + } |
| 528 | + } |
| 529 | + |
| 530 | + let start = self.scopes.len(); |
| 531 | + let innermost_scope = self.scopes().next(); |
| 532 | + match innermost_scope { |
| 533 | + Some(&Scope::ExprScope(ExprScope { scope_id, ref expr_scopes, owner })) => { |
| 534 | + let expr_scopes = expr_scopes.clone(); |
| 535 | + let scope_chain = expr_scopes |
| 536 | + .scope_chain(expr_scopes.scope_for(expr_id)) |
| 537 | + .take_while(|&it| it != scope_id); |
| 538 | + for scope_id in scope_chain { |
| 539 | + append_expr_scope(db, self, owner, &expr_scopes, scope_id); |
| 540 | + } |
| 541 | + } |
| 542 | + _ => { |
| 543 | + let expr_scopes = db.expr_scopes(owner); |
| 544 | + let scope_chain = expr_scopes.scope_chain(expr_scopes.scope_for(expr_id)); |
| 545 | + |
| 546 | + for scope_id in scope_chain { |
| 547 | + append_expr_scope(db, self, owner, &expr_scopes, scope_id); |
| 548 | + } |
| 549 | + } |
| 550 | + } |
| 551 | + self.scopes[start..].reverse(); |
| 552 | + UpdateGuard(start) |
| 553 | + } |
| 554 | + |
| 555 | + pub fn reset_to_guard(&mut self, UpdateGuard(start): UpdateGuard) { |
| 556 | + self.scopes.truncate(start); |
| 557 | + } |
481 | 558 | } |
482 | 559 |
|
| 560 | +pub struct UpdateGuard(usize); |
| 561 | + |
483 | 562 | impl Resolver { |
484 | 563 | fn scopes(&self) -> impl Iterator<Item = &Scope> { |
485 | 564 | self.scopes.iter().rev() |
@@ -576,19 +655,30 @@ impl Scope { |
576 | 655 | } |
577 | 656 | } |
578 | 657 |
|
579 | | -// needs arbitrary_self_types to be a method... or maybe move to the def? |
580 | 658 | pub fn resolver_for_expr(db: &dyn DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver { |
| 659 | + let r = owner.resolver(db); |
581 | 660 | let scopes = db.expr_scopes(owner); |
582 | | - resolver_for_scope(db, owner, scopes.scope_for(expr_id)) |
| 661 | + let scope_id = scopes.scope_for(expr_id); |
| 662 | + resolver_for_scope_(db, scopes, scope_id, r, owner) |
583 | 663 | } |
584 | 664 |
|
585 | 665 | pub fn resolver_for_scope( |
586 | 666 | db: &dyn DefDatabase, |
587 | 667 | owner: DefWithBodyId, |
588 | 668 | scope_id: Option<ScopeId>, |
589 | 669 | ) -> Resolver { |
590 | | - let mut r = owner.resolver(db); |
| 670 | + let r = owner.resolver(db); |
591 | 671 | let scopes = db.expr_scopes(owner); |
| 672 | + resolver_for_scope_(db, scopes, scope_id, r, owner) |
| 673 | +} |
| 674 | + |
| 675 | +fn resolver_for_scope_( |
| 676 | + db: &dyn DefDatabase, |
| 677 | + scopes: Arc<ExprScopes>, |
| 678 | + scope_id: Option<ScopeId>, |
| 679 | + mut r: Resolver, |
| 680 | + owner: DefWithBodyId, |
| 681 | +) -> Resolver { |
592 | 682 | let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); |
593 | 683 | r.scopes.reserve(scope_chain.len()); |
594 | 684 |
|
|
0 commit comments