diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-19 17:47:43 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-19 17:47:43 +0000 |
commit | 1ba03c6995015b3143a417ed07437f0c9028a97d (patch) | |
tree | ce3eb047dd9fe9005750a3b1417d95b1aa8fe01e /crates/ra_arena | |
parent | 988f1dda6bde576ec2457dd97a7525014609c771 (diff) | |
parent | f840fcb2f525c13809d6a736e434155edf075a06 (diff) |
Merge #3656
3656: Simplify arenas r=matklad a=matklad
At the moment, Arena is paranetrized by two types: index and data. The original motivation was to allow index to be defined in the downstream crate, so that you can add inherent impls to the index.
However, it seems like we've never actually used that capability, so perhaps we should switch to a generic Index impl? This PR tries this out, switching only `raw.rs` and parts of `hir_def`.
wdyt?
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_arena')
-rw-r--r-- | crates/ra_arena/src/lib.rs | 101 | ||||
-rw-r--r-- | crates/ra_arena/src/map.rs | 32 |
2 files changed, 79 insertions, 54 deletions
diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs index fc0f7c12f..ea98d5444 100644 --- a/crates/ra_arena/src/lib.rs +++ b/crates/ra_arena/src/lib.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::{ | 3 | use std::{ |
4 | fmt, | 4 | fmt, |
5 | hash::{Hash, Hasher}, | ||
5 | iter::FromIterator, | 6 | iter::FromIterator, |
6 | marker::PhantomData, | 7 | marker::PhantomData, |
7 | ops::{Index, IndexMut}, | 8 | ops::{Index, IndexMut}, |
@@ -36,86 +37,110 @@ impl fmt::Display for RawId { | |||
36 | } | 37 | } |
37 | } | 38 | } |
38 | 39 | ||
39 | #[derive(Clone, PartialEq, Eq)] | 40 | pub struct Idx<T> { |
40 | pub struct Arena<ID, T> { | 41 | raw: RawId, |
41 | data: Vec<T>, | 42 | _ty: PhantomData<fn() -> T>, |
42 | _ty: PhantomData<ID>, | ||
43 | } | 43 | } |
44 | 44 | ||
45 | impl<ID: ArenaId, T: fmt::Debug> fmt::Debug for Arena<ID, T> { | 45 | impl<T> Clone for Idx<T> { |
46 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 46 | fn clone(&self) -> Self { |
47 | fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish() | 47 | *self |
48 | } | 48 | } |
49 | } | 49 | } |
50 | impl<T> Copy for Idx<T> {} | ||
50 | 51 | ||
51 | #[macro_export] | 52 | impl<T> PartialEq for Idx<T> { |
52 | macro_rules! impl_arena_id { | 53 | fn eq(&self, other: &Idx<T>) -> bool { |
53 | ($name:ident) => { | 54 | self.raw == other.raw |
54 | impl $crate::ArenaId for $name { | 55 | } |
55 | fn from_raw(raw: $crate::RawId) -> Self { | 56 | } |
56 | $name(raw) | 57 | impl<T> Eq for Idx<T> {} |
57 | } | 58 | |
58 | fn into_raw(self) -> $crate::RawId { | 59 | impl<T> Hash for Idx<T> { |
59 | self.0 | 60 | fn hash<H: Hasher>(&self, state: &mut H) { |
60 | } | 61 | self.raw.hash(state) |
62 | } | ||
63 | } | ||
64 | |||
65 | impl<T> fmt::Debug for Idx<T> { | ||
66 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
67 | let mut type_name = std::any::type_name::<T>(); | ||
68 | if let Some(idx) = type_name.rfind(':') { | ||
69 | type_name = &type_name[idx + 1..] | ||
61 | } | 70 | } |
62 | }; | 71 | write!(f, "Idx::<{}>({})", type_name, self.raw) |
72 | } | ||
63 | } | 73 | } |
64 | 74 | ||
65 | pub trait ArenaId { | 75 | impl<T> Idx<T> { |
66 | fn from_raw(raw: RawId) -> Self; | 76 | pub fn from_raw(raw: RawId) -> Self { |
67 | fn into_raw(self) -> RawId; | 77 | Idx { raw, _ty: PhantomData } |
78 | } | ||
79 | pub fn into_raw(self) -> RawId { | ||
80 | self.raw | ||
81 | } | ||
82 | } | ||
83 | |||
84 | #[derive(Clone, PartialEq, Eq)] | ||
85 | pub struct Arena<T> { | ||
86 | data: Vec<T>, | ||
68 | } | 87 | } |
69 | 88 | ||
70 | impl<ID, T> Arena<ID, T> { | 89 | impl<T: fmt::Debug> fmt::Debug for Arena<T> { |
71 | pub const fn new() -> Arena<ID, T> { | 90 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
72 | Arena { data: Vec::new(), _ty: PhantomData } | 91 | fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish() |
73 | } | 92 | } |
74 | } | 93 | } |
75 | 94 | ||
76 | impl<ID: ArenaId, T> Arena<ID, T> { | 95 | impl<T> Arena<T> { |
96 | pub const fn new() -> Arena<T> { | ||
97 | Arena { data: Vec::new() } | ||
98 | } | ||
99 | |||
77 | pub fn len(&self) -> usize { | 100 | pub fn len(&self) -> usize { |
78 | self.data.len() | 101 | self.data.len() |
79 | } | 102 | } |
80 | pub fn is_empty(&self) -> bool { | 103 | pub fn is_empty(&self) -> bool { |
81 | self.data.is_empty() | 104 | self.data.is_empty() |
82 | } | 105 | } |
83 | pub fn alloc(&mut self, value: T) -> ID { | 106 | pub fn alloc(&mut self, value: T) -> Idx<T> { |
84 | let id = RawId(self.data.len() as u32); | 107 | let id = RawId(self.data.len() as u32); |
85 | self.data.push(value); | 108 | self.data.push(value); |
86 | ID::from_raw(id) | 109 | Idx::from_raw(id) |
87 | } | 110 | } |
88 | pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> + ExactSizeIterator + DoubleEndedIterator { | 111 | pub fn iter( |
89 | self.data.iter().enumerate().map(|(idx, value)| (ID::from_raw(RawId(idx as u32)), value)) | 112 | &self, |
113 | ) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator { | ||
114 | self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value)) | ||
90 | } | 115 | } |
91 | } | 116 | } |
92 | 117 | ||
93 | impl<ID: ArenaId, T> Default for Arena<ID, T> { | 118 | impl<T> Default for Arena<T> { |
94 | fn default() -> Arena<ID, T> { | 119 | fn default() -> Arena<T> { |
95 | Arena { data: Vec::new(), _ty: PhantomData } | 120 | Arena { data: Vec::new() } |
96 | } | 121 | } |
97 | } | 122 | } |
98 | 123 | ||
99 | impl<ID: ArenaId, T> Index<ID> for Arena<ID, T> { | 124 | impl<T> Index<Idx<T>> for Arena<T> { |
100 | type Output = T; | 125 | type Output = T; |
101 | fn index(&self, idx: ID) -> &T { | 126 | fn index(&self, idx: Idx<T>) -> &T { |
102 | let idx = idx.into_raw().0 as usize; | 127 | let idx = idx.into_raw().0 as usize; |
103 | &self.data[idx] | 128 | &self.data[idx] |
104 | } | 129 | } |
105 | } | 130 | } |
106 | 131 | ||
107 | impl<ID: ArenaId, T> IndexMut<ID> for Arena<ID, T> { | 132 | impl<T> IndexMut<Idx<T>> for Arena<T> { |
108 | fn index_mut(&mut self, idx: ID) -> &mut T { | 133 | fn index_mut(&mut self, idx: Idx<T>) -> &mut T { |
109 | let idx = idx.into_raw().0 as usize; | 134 | let idx = idx.into_raw().0 as usize; |
110 | &mut self.data[idx] | 135 | &mut self.data[idx] |
111 | } | 136 | } |
112 | } | 137 | } |
113 | 138 | ||
114 | impl<ID: ArenaId, T> FromIterator<T> for Arena<ID, T> { | 139 | impl<T> FromIterator<T> for Arena<T> { |
115 | fn from_iter<I>(iter: I) -> Self | 140 | fn from_iter<I>(iter: I) -> Self |
116 | where | 141 | where |
117 | I: IntoIterator<Item = T>, | 142 | I: IntoIterator<Item = T>, |
118 | { | 143 | { |
119 | Arena { data: Vec::from_iter(iter), _ty: PhantomData } | 144 | Arena { data: Vec::from_iter(iter) } |
120 | } | 145 | } |
121 | } | 146 | } |
diff --git a/crates/ra_arena/src/map.rs b/crates/ra_arena/src/map.rs index b73d4e365..5e764113d 100644 --- a/crates/ra_arena/src/map.rs +++ b/crates/ra_arena/src/map.rs | |||
@@ -2,17 +2,17 @@ | |||
2 | 2 | ||
3 | use std::marker::PhantomData; | 3 | use std::marker::PhantomData; |
4 | 4 | ||
5 | use super::ArenaId; | 5 | use crate::Idx; |
6 | 6 | ||
7 | /// A map from arena IDs to some other type. Space requirement is O(highest ID). | 7 | /// A map from arena IDs to some other type. Space requirement is O(highest ID). |
8 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | 8 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
9 | pub struct ArenaMap<ID, T> { | 9 | pub struct ArenaMap<ID, V> { |
10 | v: Vec<Option<T>>, | 10 | v: Vec<Option<V>>, |
11 | _ty: PhantomData<ID>, | 11 | _ty: PhantomData<ID>, |
12 | } | 12 | } |
13 | 13 | ||
14 | impl<ID: ArenaId, T> ArenaMap<ID, T> { | 14 | impl<T, V> ArenaMap<Idx<T>, V> { |
15 | pub fn insert(&mut self, id: ID, t: T) { | 15 | pub fn insert(&mut self, id: Idx<T>, t: V) { |
16 | let idx = Self::to_idx(id); | 16 | let idx = Self::to_idx(id); |
17 | if self.v.capacity() <= idx { | 17 | if self.v.capacity() <= idx { |
18 | self.v.reserve(idx + 1 - self.v.capacity()); | 18 | self.v.reserve(idx + 1 - self.v.capacity()); |
@@ -25,43 +25,43 @@ impl<ID: ArenaId, T> ArenaMap<ID, T> { | |||
25 | self.v[idx] = Some(t); | 25 | self.v[idx] = Some(t); |
26 | } | 26 | } |
27 | 27 | ||
28 | pub fn get(&self, id: ID) -> Option<&T> { | 28 | pub fn get(&self, id: Idx<T>) -> Option<&V> { |
29 | self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref()) | 29 | self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref()) |
30 | } | 30 | } |
31 | 31 | ||
32 | pub fn get_mut(&mut self, id: ID) -> Option<&mut T> { | 32 | pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> { |
33 | self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut()) | 33 | self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut()) |
34 | } | 34 | } |
35 | 35 | ||
36 | pub fn values(&self) -> impl Iterator<Item = &T> { | 36 | pub fn values(&self) -> impl Iterator<Item = &V> { |
37 | self.v.iter().filter_map(|o| o.as_ref()) | 37 | self.v.iter().filter_map(|o| o.as_ref()) |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn values_mut(&mut self) -> impl Iterator<Item = &mut T> { | 40 | pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> { |
41 | self.v.iter_mut().filter_map(|o| o.as_mut()) | 41 | self.v.iter_mut().filter_map(|o| o.as_mut()) |
42 | } | 42 | } |
43 | 43 | ||
44 | pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> { | 44 | pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> { |
45 | self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?))) | 45 | self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?))) |
46 | } | 46 | } |
47 | 47 | ||
48 | fn to_idx(id: ID) -> usize { | 48 | fn to_idx(id: Idx<T>) -> usize { |
49 | u32::from(id.into_raw()) as usize | 49 | u32::from(id.into_raw()) as usize |
50 | } | 50 | } |
51 | 51 | ||
52 | fn from_idx(idx: usize) -> ID { | 52 | fn from_idx(idx: usize) -> Idx<T> { |
53 | ID::from_raw((idx as u32).into()) | 53 | Idx::from_raw((idx as u32).into()) |
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | impl<ID: ArenaId, T> std::ops::Index<ID> for ArenaMap<ID, T> { | 57 | impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> { |
58 | type Output = T; | 58 | type Output = T; |
59 | fn index(&self, id: ID) -> &T { | 59 | fn index(&self, id: Idx<V>) -> &T { |
60 | self.v[Self::to_idx(id)].as_ref().unwrap() | 60 | self.v[Self::to_idx(id)].as_ref().unwrap() |
61 | } | 61 | } |
62 | } | 62 | } |
63 | 63 | ||
64 | impl<ID, T> Default for ArenaMap<ID, T> { | 64 | impl<T, V> Default for ArenaMap<Idx<V>, T> { |
65 | fn default() -> Self { | 65 | fn default() -> Self { |
66 | ArenaMap { v: Vec::new(), _ty: PhantomData } | 66 | ArenaMap { v: Vec::new(), _ty: PhantomData } |
67 | } | 67 | } |