Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/body/scope.rs')
| -rw-r--r-- | crates/hir-def/src/body/scope.rs | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs index 12fc1f116d..69741c445f 100644 --- a/crates/hir-def/src/body/scope.rs +++ b/crates/hir-def/src/body/scope.rs @@ -1,14 +1,13 @@ //! Name resolution for expressions. -use std::sync::Arc; - use hir_expand::name::Name; -use la_arena::{Arena, Idx}; +use la_arena::{Arena, Idx, IdxRange, RawIdx}; use rustc_hash::FxHashMap; +use triomphe::Arc; use crate::{ body::Body, db::DefDatabase, - expr::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement}, + hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement}, BlockId, DefWithBodyId, }; @@ -17,6 +16,7 @@ pub type ScopeId = Idx<ScopeData>; #[derive(Debug, PartialEq, Eq)] pub struct ExprScopes { scopes: Arena<ScopeData>, + scope_entries: Arena<ScopeEntry>, scope_by_expr: FxHashMap<ExprId, ScopeId>, } @@ -41,7 +41,7 @@ pub struct ScopeData { parent: Option<ScopeId>, block: Option<BlockId>, label: Option<(LabelId, Name)>, - entries: Vec<ScopeEntry>, + entries: IdxRange<ScopeEntry>, } impl ExprScopes { @@ -53,7 +53,7 @@ impl ExprScopes { } pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { - &self.scopes[scope].entries + &self.scope_entries[self.scopes[scope].entries.clone()] } /// If `scope` refers to a block expression scope, returns the corresponding `BlockId`. @@ -85,10 +85,17 @@ impl ExprScopes { } } +fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> { + IdxRange::new(Idx::from_raw(RawIdx::from(idx as u32))..Idx::from_raw(RawIdx::from(idx as u32))) +} + impl ExprScopes { fn new(body: &Body) -> ExprScopes { - let mut scopes = - ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; + let mut scopes = ExprScopes { + scopes: Arena::default(), + scope_entries: Arena::default(), + scope_by_expr: FxHashMap::default(), + }; let mut root = scopes.root_scope(); scopes.add_params_bindings(body, root, &body.params); compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root); @@ -96,7 +103,12 @@ impl ExprScopes { } fn root_scope(&mut self) -> ScopeId { - self.scopes.alloc(ScopeData { parent: None, block: None, label: None, entries: vec![] }) + self.scopes.alloc(ScopeData { + parent: None, + block: None, + label: None, + entries: empty_entries(self.scope_entries.len()), + }) } fn new_scope(&mut self, parent: ScopeId) -> ScopeId { @@ -104,32 +116,38 @@ impl ExprScopes { parent: Some(parent), block: None, label: None, - entries: vec![], + entries: empty_entries(self.scope_entries.len()), }) } fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>) -> ScopeId { - self.scopes.alloc(ScopeData { parent: Some(parent), block: None, label, entries: vec![] }) + self.scopes.alloc(ScopeData { + parent: Some(parent), + block: None, + label, + entries: empty_entries(self.scope_entries.len()), + }) } fn new_block_scope( &mut self, parent: ScopeId, - block: BlockId, + block: Option<BlockId>, label: Option<(LabelId, Name)>, ) -> ScopeId { self.scopes.alloc(ScopeData { parent: Some(parent), - block: Some(block), + block, label, - entries: vec![], + entries: empty_entries(self.scope_entries.len()), }) } fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) { let Binding { name, .. } = &body.bindings[binding]; - let entry = ScopeEntry { name: name.clone(), binding }; - self.scopes[scope].entries.push(entry); + let entry = self.scope_entries.alloc(ScopeEntry { name: name.clone(), binding }); + self.scopes[scope].entries = + IdxRange::new_inclusive(self.scopes[scope].entries.start()..=entry); } fn add_pat_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { @@ -150,9 +168,9 @@ impl ExprScopes { } fn shrink_to_fit(&mut self) { - let ExprScopes { scopes, scope_by_expr } = self; + let ExprScopes { scopes, scope_entries, scope_by_expr } = self; scopes.shrink_to_fit(); - scopes.values_mut().for_each(|it| it.entries.shrink_to_fit()); + scope_entries.shrink_to_fit(); scope_by_expr.shrink_to_fit(); } } @@ -200,22 +218,16 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope scopes.set_scope(expr, scope); compute_block_scopes(statements, *tail, body, scopes, &mut scope); } - Expr::Unsafe { id, statements, tail } - | Expr::Async { id, statements, tail } - | Expr::Const { id, statements, tail } - | Expr::TryBlock { id, statements, tail } => { + Expr::Const(_) => { + // FIXME: This is broken. + } + Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => { let mut scope = scopes.new_block_scope(*scope, *id, None); // Overwrite the old scope for the block expr, so that every block scope can be found // via the block itself (important for blocks that only contain items, no expressions). scopes.set_scope(expr, scope); compute_block_scopes(statements, *tail, body, scopes, &mut scope); } - Expr::For { iterable, pat, body: body_expr, label } => { - compute_expr_scopes(*iterable, body, scopes, scope); - let mut scope = scopes.new_labeled_scope(*scope, make_label(label)); - scopes.add_pat_bindings(body, scope, *pat); - compute_expr_scopes(*body_expr, body, scopes, &mut scope); - } Expr::While { condition, body: body_expr, label } => { let mut scope = scopes.new_labeled_scope(*scope, make_label(label)); compute_expr_scopes(*condition, body, scopes, &mut scope); |