diff --git a/src/ast.rs b/src/ast.rs index 643bea9ca..f98a796d4 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -439,7 +439,7 @@ fn allows_keyword(&self, kw: ParseKeyword) -> bool { pub trait List: Node { type ContentsNode: Node + Default; fn contents(&self) -> &[Box]; - fn contents_mut(&mut self) -> &mut Vec>; + fn contents_mut(&mut self) -> &mut Box<[Box]>; /// Return our count. fn count(&self) -> usize { self.contents().len() @@ -636,7 +636,8 @@ macro_rules! define_list_node { #[derive(Default, Debug)] pub struct $name { parent: Option<*const dyn Node>, - list_contents: Vec>, + // Note we box the nodes themselves, for pointer stability. + list_contents: Box<[Box<$contents>]>, } implement_node!($name, list, $type); impl List for $name { @@ -644,7 +645,7 @@ impl List for $name { fn contents(&self) -> &[Box] { &self.list_contents } - fn contents_mut(&mut self) -> &mut Vec> { + fn contents_mut(&mut self) -> &mut Box<[Box]> { &mut self.list_contents } } @@ -3547,7 +3548,6 @@ fn populate_list(&mut self, list: &mut ListType, exhaust_stream: } // We're going to populate a vector with our nodes. - // Later on we will copy this to the heap with a single allocation. let mut contents = vec![]; loop { @@ -3614,7 +3614,7 @@ fn populate_list(&mut self, list: &mut ListType, exhaust_stream: "Contents size out of bounds" ); assert!(list.contents().is_empty(), "List should still be empty"); - *list.contents_mut() = contents; + *list.contents_mut() = contents.into_boxed_slice(); } FLOGF!(