Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1a33168

Browse files
committed
Auto merge of rust-lang#14573 - Veykril:expr-scopes, r=Veykril
internal: Allocate ExprScopes ScopeEntries in a single arena instead of per ScopeData
2 parents c479804 + ce0896b commit 1a33168

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

crates/hir-def/src/body/scope.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::sync::Arc;
33

44
use hir_expand::name::Name;
5-
use la_arena::{Arena, Idx};
5+
use la_arena::{Arena, Idx, IdxRange, RawIdx};
66
use rustc_hash::FxHashMap;
77

88
use crate::{
@@ -17,6 +17,7 @@ pub type ScopeId = Idx<ScopeData>;
1717
#[derive(Debug, PartialEq, Eq)]
1818
pub struct ExprScopes {
1919
scopes: Arena<ScopeData>,
20+
scope_entries: Arena<ScopeEntry>,
2021
scope_by_expr: FxHashMap<ExprId, ScopeId>,
2122
}
2223

@@ -41,7 +42,7 @@ pub struct ScopeData {
4142
parent: Option<ScopeId>,
4243
block: Option<BlockId>,
4344
label: Option<(LabelId, Name)>,
44-
entries: Vec<ScopeEntry>,
45+
entries: IdxRange<ScopeEntry>,
4546
}
4647

4748
impl ExprScopes {
@@ -53,7 +54,7 @@ impl ExprScopes {
5354
}
5455

5556
pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
56-
&self.scopes[scope].entries
57+
&self.scope_entries[self.scopes[scope].entries.clone()]
5758
}
5859

5960
/// If `scope` refers to a block expression scope, returns the corresponding `BlockId`.
@@ -85,31 +86,48 @@ impl ExprScopes {
8586
}
8687
}
8788

89+
fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
90+
IdxRange::new(Idx::from_raw(RawIdx::from(idx as u32))..Idx::from_raw(RawIdx::from(idx as u32)))
91+
}
92+
8893
impl ExprScopes {
8994
fn new(body: &Body) -> ExprScopes {
90-
let mut scopes =
91-
ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() };
95+
let mut scopes = ExprScopes {
96+
scopes: Arena::default(),
97+
scope_entries: Arena::default(),
98+
scope_by_expr: FxHashMap::default(),
99+
};
92100
let mut root = scopes.root_scope();
93101
scopes.add_params_bindings(body, root, &body.params);
94102
compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root);
95103
scopes
96104
}
97105

98106
fn root_scope(&mut self) -> ScopeId {
99-
self.scopes.alloc(ScopeData { parent: None, block: None, label: None, entries: vec![] })
107+
self.scopes.alloc(ScopeData {
108+
parent: None,
109+
block: None,
110+
label: None,
111+
entries: empty_entries(self.scope_entries.len()),
112+
})
100113
}
101114

102115
fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
103116
self.scopes.alloc(ScopeData {
104117
parent: Some(parent),
105118
block: None,
106119
label: None,
107-
entries: vec![],
120+
entries: empty_entries(self.scope_entries.len()),
108121
})
109122
}
110123

111124
fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>) -> ScopeId {
112-
self.scopes.alloc(ScopeData { parent: Some(parent), block: None, label, entries: vec![] })
125+
self.scopes.alloc(ScopeData {
126+
parent: Some(parent),
127+
block: None,
128+
label,
129+
entries: empty_entries(self.scope_entries.len()),
130+
})
113131
}
114132

115133
fn new_block_scope(
@@ -118,13 +136,19 @@ impl ExprScopes {
118136
block: Option<BlockId>,
119137
label: Option<(LabelId, Name)>,
120138
) -> ScopeId {
121-
self.scopes.alloc(ScopeData { parent: Some(parent), block, label, entries: vec![] })
139+
self.scopes.alloc(ScopeData {
140+
parent: Some(parent),
141+
block,
142+
label,
143+
entries: empty_entries(self.scope_entries.len()),
144+
})
122145
}
123146

124147
fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) {
125148
let Binding { name, .. } = &body.bindings[binding];
126-
let entry = ScopeEntry { name: name.clone(), binding };
127-
self.scopes[scope].entries.push(entry);
149+
let entry = self.scope_entries.alloc(ScopeEntry { name: name.clone(), binding });
150+
self.scopes[scope].entries =
151+
IdxRange::new_inclusive(self.scopes[scope].entries.start()..=entry);
128152
}
129153

130154
fn add_pat_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
@@ -145,9 +169,9 @@ impl ExprScopes {
145169
}
146170

147171
fn shrink_to_fit(&mut self) {
148-
let ExprScopes { scopes, scope_by_expr } = self;
172+
let ExprScopes { scopes, scope_entries, scope_by_expr } = self;
149173
scopes.shrink_to_fit();
150-
scopes.values_mut().for_each(|it| it.entries.shrink_to_fit());
174+
scope_entries.shrink_to_fit();
151175
scope_by_expr.shrink_to_fit();
152176
}
153177
}

lib/la-arena/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ pub use map::{ArenaMap, Entry, OccupiedEntry, VacantEntry};
1919
pub struct RawIdx(u32);
2020

2121
impl From<RawIdx> for u32 {
22+
#[inline]
2223
fn from(raw: RawIdx) -> u32 {
2324
raw.0
2425
}
2526
}
2627

2728
impl From<u32> for RawIdx {
29+
#[inline]
2830
fn from(idx: u32) -> RawIdx {
2931
RawIdx(idx)
3032
}
@@ -160,6 +162,16 @@ impl<T> IdxRange<T> {
160162
pub fn is_empty(&self) -> bool {
161163
self.range.is_empty()
162164
}
165+
166+
/// Returns the start of the index range.
167+
pub fn start(&self) -> Idx<T> {
168+
Idx::from_raw(RawIdx::from(self.range.start))
169+
}
170+
171+
/// Returns the start of the index range.
172+
pub fn end(&self) -> Idx<T> {
173+
Idx::from_raw(RawIdx::from(self.range.end))
174+
}
163175
}
164176

165177
impl<T> Iterator for IdxRange<T> {

0 commit comments

Comments
 (0)