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.rs68
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);