diff options
| author | Aramis Razzaghipour <aramisnoah@gmail.com> | 2021-10-05 14:10:25 +1100 |
|---|---|---|
| committer | Aramis Razzaghipour <aramisnoah@gmail.com> | 2021-10-15 13:03:28 +1100 |
| commit | dce5c640f8f4b8fa3f9eded0c115689f85250877 (patch) | |
| tree | b3619647705cc37450de64d50e5cdba5024ce296 | |
| parent | 3a79af7e277839f803bd0304f28dbe4971ffdad6 (diff) | |
| download | rust-dce5c640f8f4b8fa3f9eded0c115689f85250877.tar.gz rust-dce5c640f8f4b8fa3f9eded0c115689f85250877.zip | |
Move `IdxRange` into `la_arena`
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | crates/hir_def/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/hir_def/src/body/scope.rs | 2 | ||||
| -rw-r--r-- | crates/hir_def/src/item_tree.rs | 62 | ||||
| -rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 18 | ||||
| -rw-r--r-- | crates/hir_expand/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/hir_ty/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/profile/Cargo.toml | 2 | ||||
| -rw-r--r-- | crates/project_model/Cargo.toml | 2 | ||||
| -rw-r--r-- | lib/arena/Cargo.toml | 2 | ||||
| -rw-r--r-- | lib/arena/src/lib.rs | 117 |
11 files changed, 137 insertions, 76 deletions
diff --git a/Cargo.lock b/Cargo.lock index 17dae55e447..6a22fcec73a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -796,7 +796,7 @@ dependencies = [ [[package]] name = "la-arena" -version = "0.2.1" +version = "0.3.0" [[package]] name = "lazy_static" diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 9573d5ac352..8f989bc0aef 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml @@ -21,7 +21,7 @@ fst = { version = "0.4", default-features = false } itertools = "0.10.0" indexmap = "1.4.0" smallvec = "1.4.0" -la-arena = { version = "0.2.0", path = "../../lib/arena" } +la-arena = { version = "0.3.0", path = "../../lib/arena" } stdx = { path = "../stdx", version = "0.0.0" } base_db = { path = "../base_db", version = "0.0.0" } diff --git a/crates/hir_def/src/body/scope.rs b/crates/hir_def/src/body/scope.rs index 8a48ad91991..82b23f2f467 100644 --- a/crates/hir_def/src/body/scope.rs +++ b/crates/hir_def/src/body/scope.rs @@ -174,7 +174,7 @@ fn compute_block_scopes( fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { let make_label = - |label: &Option<_>| label.map(|label| (label, body.labels[label].name.clone())); + |label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone())); scopes.set_scope(expr, scope); match &body[expr] { diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index b7a5758a0a2..73b00887e76 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -36,11 +36,10 @@ mod pretty; mod tests; use std::{ - any::type_name, fmt::{self, Debug}, hash::{Hash, Hasher}, marker::PhantomData, - ops::{Index, Range}, + ops::Index, sync::Arc, }; @@ -53,7 +52,7 @@ use hir_expand::{ name::{name, AsName, Name}, ExpandTo, HirFileId, InFile, }; -use la_arena::{Arena, Idx, RawIdx}; +use la_arena::{Arena, Idx, IdxRange, RawIdx}; use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -606,7 +605,7 @@ pub struct Function { pub visibility: RawVisibilityId, pub explicit_generic_params: Interned<GenericParams>, pub abi: Option<Interned<str>>, - pub params: IdRange<Param>, + pub params: IdxRange<Param>, pub ret_type: Interned<TypeRef>, pub async_ret_type: Option<Interned<TypeRef>>, pub ast_id: FileAstId<ast::Fn>, @@ -659,7 +658,7 @@ pub struct Enum { pub name: Name, pub visibility: RawVisibilityId, pub generic_params: Interned<GenericParams>, - pub variants: IdRange<Variant>, + pub variants: IdxRange<Variant>, pub ast_id: FileAstId<ast::Enum>, } @@ -947,59 +946,10 @@ pub struct Variant { pub fields: Fields, } -/// A range of densely allocated ItemTree IDs. -pub struct IdRange<T> { - range: Range<u32>, - _p: PhantomData<T>, -} - -impl<T> IdRange<T> { - fn new(range: Range<Idx<T>>) -> Self { - Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData } - } - - fn is_empty(&self) -> bool { - self.range.is_empty() - } -} - -impl<T> Iterator for IdRange<T> { - type Item = Idx<T>; - fn next(&mut self) -> Option<Self::Item> { - self.range.next().map(|raw| Idx::from_raw(raw.into())) - } -} - -impl<T> DoubleEndedIterator for IdRange<T> { - fn next_back(&mut self) -> Option<Self::Item> { - self.range.next_back().map(|raw| Idx::from_raw(raw.into())) - } -} - -impl<T> fmt::Debug for IdRange<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() - } -} - -impl<T> Clone for IdRange<T> { - fn clone(&self) -> Self { - Self { range: self.range.clone(), _p: PhantomData } - } -} - -impl<T> PartialEq for IdRange<T> { - fn eq(&self, other: &Self) -> bool { - self.range == other.range - } -} - -impl<T> Eq for IdRange<T> {} - #[derive(Debug, Clone, PartialEq, Eq)] pub enum Fields { - Record(IdRange<Field>), - Tuple(IdRange<Field>), + Record(IdxRange<Field>), + Tuple(IdxRange<Field>), Unit, } diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 9c278f5ac6b..7074210a8ae 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -229,7 +229,7 @@ impl<'a> Ctx<'a> { } } - fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdRange<Field> { + fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdxRange<Field> { let start = self.next_field_idx(); for field in fields.fields() { if let Some(data) = self.lower_record_field(&field) { @@ -238,7 +238,7 @@ impl<'a> Ctx<'a> { } } let end = self.next_field_idx(); - IdRange::new(start..end) + IdxRange::new(start..end) } fn lower_record_field(&mut self, field: &ast::RecordField) -> Option<Field> { @@ -249,7 +249,7 @@ impl<'a> Ctx<'a> { Some(res) } - fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdRange<Field> { + fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdxRange<Field> { let start = self.next_field_idx(); for (i, field) in fields.fields().enumerate() { let data = self.lower_tuple_field(i, &field); @@ -257,7 +257,7 @@ impl<'a> Ctx<'a> { self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, &self.hygiene)); } let end = self.next_field_idx(); - IdRange::new(start..end) + IdxRange::new(start..end) } fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field { @@ -273,7 +273,7 @@ impl<'a> Ctx<'a> { let generic_params = self.lower_generic_params(GenericsOwner::Union, union); let fields = match union.record_field_list() { Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)), - None => Fields::Record(IdRange::new(self.next_field_idx()..self.next_field_idx())), + None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())), }; let ast_id = self.source_ast_id_map.ast_id(union); let res = Union { name, visibility, generic_params, fields, ast_id }; @@ -287,14 +287,14 @@ impl<'a> Ctx<'a> { let variants = self.with_inherited_visibility(visibility, |this| match &enum_.variant_list() { Some(variant_list) => this.lower_variants(variant_list), - None => IdRange::new(this.next_variant_idx()..this.next_variant_idx()), + None => IdxRange::new(this.next_variant_idx()..this.next_variant_idx()), }); let ast_id = self.source_ast_id_map.ast_id(enum_); let res = Enum { name, visibility, generic_params, variants, ast_id }; Some(id(self.data().enums.alloc(res))) } - fn lower_variants(&mut self, variants: &ast::VariantList) -> IdRange<Variant> { + fn lower_variants(&mut self, variants: &ast::VariantList) -> IdxRange<Variant> { let start = self.next_variant_idx(); for variant in variants.variants() { if let Some(data) = self.lower_variant(&variant) { @@ -303,7 +303,7 @@ impl<'a> Ctx<'a> { } } let end = self.next_variant_idx(); - IdRange::new(start..end) + IdxRange::new(start..end) } fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> { @@ -358,7 +358,7 @@ impl<'a> Ctx<'a> { } } let end_param = self.next_param_idx(); - let params = IdRange::new(start_param..end_param); + let params = IdxRange::new(start_param..end_param); let ret_type = match func.ret_type().and_then(|rt| rt.ty()) { Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml index 240193f9cf1..b73a0c420fd 100644 --- a/crates/hir_expand/Cargo.toml +++ b/crates/hir_expand/Cargo.toml @@ -13,7 +13,7 @@ cov-mark = "2.0.0-pre.1" tracing = "0.1" either = "1.5.3" rustc-hash = "1.0.0" -la-arena = { version = "0.2.0", path = "../../lib/arena" } +la-arena = { version = "0.3.0", path = "../../lib/arena" } itertools = "0.10.0" base_db = { path = "../base_db", version = "0.0.0" } diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 0f1e75958a8..d05c3ee5c3f 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml @@ -20,7 +20,7 @@ scoped-tls = "1" chalk-solve = { version = "0.71", default-features = false } chalk-ir = "0.71" chalk-recursive = { version = "0.71", default-features = false } -la-arena = { version = "0.2.0", path = "../../lib/arena" } +la-arena = { version = "0.3.0", path = "../../lib/arena" } once_cell = { version = "1.5.0" } stdx = { path = "../stdx", version = "0.0.0" } diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml index 7f7a50eb446..6014ef3e1c2 100644 --- a/crates/profile/Cargo.toml +++ b/crates/profile/Cargo.toml @@ -12,7 +12,7 @@ doctest = false once_cell = "1.3.1" cfg-if = "1" libc = "0.2" -la-arena = { version = "0.2.0", path = "../../lib/arena" } +la-arena = { version = "0.3.0", path = "../../lib/arena" } countme = { version = "2.0.1", features = ["enable"] } jemalloc-ctl = { version = "0.4.1", package = "tikv-jemalloc-ctl", optional = true } diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml index 949325fc823..2cba46a59b5 100644 --- a/crates/project_model/Cargo.toml +++ b/crates/project_model/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0.106", features = ["derive"] } serde_json = "1.0.48" anyhow = "1.0.26" expect-test = "1.2.0-pre.1" -la-arena = { version = "0.2.0", path = "../../lib/arena" } +la-arena = { version = "0.3.0", path = "../../lib/arena" } cfg = { path = "../cfg", version = "0.0.0" } base_db = { path = "../base_db", version = "0.0.0" } diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml index b5b0cf5e822..23f1d9e8817 100644 --- a/lib/arena/Cargo.toml +++ b/lib/arena/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "la-arena" -version = "0.2.1" +version = "0.3.0" description = "Simple index-based arena without deletion." license = "MIT OR Apache-2.0" repository = "https://github.com/rust-analyzer/rust-analyzer" diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs index 162d556fb7f..9fe6d606234 100644 --- a/lib/arena/src/lib.rs +++ b/lib/arena/src/lib.rs @@ -7,7 +7,7 @@ use std::{ hash::{Hash, Hasher}, iter::FromIterator, marker::PhantomData, - ops::{Index, IndexMut}, + ops::{Index, IndexMut, Range, RangeInclusive}, }; mod map; @@ -89,6 +89,101 @@ impl<T> Idx<T> { } } +/// A range of densely allocated arena values. +pub struct IdxRange<T> { + range: Range<u32>, + _p: PhantomData<T>, +} + +impl<T> IdxRange<T> { + /// Creates a new index range + /// inclusive of the start value and exclusive of the end value. + /// + /// ``` + /// let mut arena = la_arena::Arena::new(); + /// let a = arena.alloc("a"); + /// let b = arena.alloc("b"); + /// let c = arena.alloc("c"); + /// let d = arena.alloc("d"); + /// + /// let range = la_arena::IdxRange::new(b..d); + /// assert_eq!(&arena[range], &["b", "c"]); + /// ``` + pub fn new(range: Range<Idx<T>>) -> Self { + Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData } + } + + /// Creates a new index range + /// inclusive of the start value and end value. + /// + /// ``` + /// let mut arena = la_arena::Arena::new(); + /// let foo = arena.alloc("foo"); + /// let bar = arena.alloc("bar"); + /// let baz = arena.alloc("baz"); + /// + /// let range = la_arena::IdxRange::new_inclusive(foo..=baz); + /// assert_eq!(&arena[range], &["foo", "bar", "baz"]); + /// + /// let range = la_arena::IdxRange::new_inclusive(foo..=foo); + /// assert_eq!(&arena[range], &["foo"]); + /// ``` + pub fn new_inclusive(range: RangeInclusive<Idx<T>>) -> Self { + Self { + range: u32::from(range.start().into_raw())..u32::from(range.end().into_raw()) + 1, + _p: PhantomData, + } + } + + /// Returns whether the index range is empty. + /// + /// ``` + /// let mut arena = la_arena::Arena::new(); + /// let one = arena.alloc(1); + /// let two = arena.alloc(2); + /// + /// assert!(la_arena::IdxRange::new(one..one).is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.range.is_empty() + } +} + +impl<T> Iterator for IdxRange<T> { + type Item = Idx<T>; + fn next(&mut self) -> Option<Self::Item> { + self.range.next().map(|raw| Idx::from_raw(raw.into())) + } +} + +impl<T> DoubleEndedIterator for IdxRange<T> { + fn next_back(&mut self) -> Option<Self::Item> { + self.range.next_back().map(|raw| Idx::from_raw(raw.into())) + } +} + +impl<T> fmt::Debug for IdxRange<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple(&format!("IdxRange::<{}>", std::any::type_name::<T>())) + .field(&self.range) + .finish() + } +} + +impl<T> Clone for IdxRange<T> { + fn clone(&self) -> Self { + Self { range: self.range.clone(), _p: PhantomData } + } +} + +impl<T> PartialEq for IdxRange<T> { + fn eq(&self, other: &Self) -> bool { + self.range == other.range + } +} + +impl<T> Eq for IdxRange<T> {} + /// Yet another index-based arena. #[derive(Clone, PartialEq, Eq, Hash)] pub struct Arena<T> { @@ -170,9 +265,9 @@ impl<T> Arena<T> { /// assert_eq!(arena[idx], 50); /// ``` pub fn alloc(&mut self, value: T) -> Idx<T> { - let idx = RawIdx(self.data.len() as u32); + let idx = self.next_idx(); self.data.push(value); - Idx::from_raw(idx) + idx } /// Returns an iterator over the arena’s elements. @@ -221,6 +316,13 @@ impl<T> Arena<T> { pub fn shrink_to_fit(&mut self) { self.data.shrink_to_fit(); } + + /// Returns the index of the next value allocated on the arena. + /// + /// This method should remain private to make creating invalid `Idx`s harder. + fn next_idx(&self) -> Idx<T> { + Idx::from_raw(RawIdx(self.data.len() as u32)) + } } impl<T> Default for Arena<T> { @@ -244,6 +346,15 @@ impl<T> IndexMut<Idx<T>> for Arena<T> { } } +impl<T> Index<IdxRange<T>> for Arena<T> { + type Output = [T]; + fn index(&self, range: IdxRange<T>) -> &[T] { + let start = range.range.start as usize; + let end = range.range.end as usize; + &self.data[start..end] + } +} + impl<T> FromIterator<T> for Arena<T> { fn from_iter<I>(iter: I) -> Self where |
