Don't allocate when traversing children

This commit is contained in:
Aleksey Kladov 2018-07-30 23:20:02 +03:00
parent 27a40e0a88
commit 70b3372921
5 changed files with 66 additions and 12 deletions

View file

@ -11,8 +11,8 @@ impl TreeRoot for Arc<SyntaxRoot> {}
impl<'a> TreeRoot for &'a SyntaxRoot {} impl<'a> TreeRoot for &'a SyntaxRoot {}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct SyntaxNode<ROOT: TreeRoot = Arc<SyntaxRoot>> { pub struct SyntaxNode<R: TreeRoot = Arc<SyntaxRoot>> {
pub(crate) root: ROOT, pub(crate) root: R,
// Guaranteed to not dangle, because `root` holds a // Guaranteed to not dangle, because `root` holds a
// strong reference to red's ancestor // strong reference to red's ancestor
red: ptr::NonNull<RedNode>, red: ptr::NonNull<RedNode>,
@ -52,7 +52,7 @@ impl SyntaxNode<Arc<SyntaxRoot>> {
} }
} }
impl<ROOT: TreeRoot> SyntaxNode<ROOT> { impl<R: TreeRoot> SyntaxNode<R> {
pub fn borrow<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { pub fn borrow<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> {
SyntaxNode { SyntaxNode {
root: &*self.root, root: &*self.root,
@ -73,20 +73,18 @@ impl<ROOT: TreeRoot> SyntaxNode<ROOT> {
self.red().green().text() self.red().green().text()
} }
pub fn children(&self) -> Vec<SyntaxNode<ROOT>> { pub fn children<'a>(&'a self) -> impl Iterator<Item=SyntaxNode<R>> + 'a {
let red = self.red(); let red = self.red();
let n_children = red.n_children(); let n_children = red.n_children();
let mut res = Vec::with_capacity(n_children); (0..n_children).map(move |i| {
for i in 0..n_children { SyntaxNode {
res.push(SyntaxNode {
root: self.root.clone(), root: self.root.clone(),
red: red.nth_child(i), red: red.nth_child(i),
}); }
} })
res
} }
pub fn parent(&self) -> Option<SyntaxNode<ROOT>> { pub fn parent(&self) -> Option<SyntaxNode<R>> {
let parent = self.red().parent()?; let parent = self.red().parent()?;
Some(SyntaxNode { Some(SyntaxNode {
root: self.root.clone(), root: self.root.clone(),
@ -99,7 +97,7 @@ impl<ROOT: TreeRoot> SyntaxNode<ROOT> {
} }
} }
impl<ROOT: TreeRoot> fmt::Debug for SyntaxNode<ROOT> { impl<R: TreeRoot> fmt::Debug for SyntaxNode<R> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
if has_short_text(self.kind()) { if has_short_text(self.kind()) {

View file

@ -0,0 +1 @@
struct S<T: 'a + ?Sized + (Copy)>;

View file

@ -0,0 +1,33 @@
FILE@[0; 35)
STRUCT_ITEM@[0; 35)
STRUCT_KW@[0; 6)
NAME@[6; 8)
WHITESPACE@[6; 7)
IDENT@[7; 8) "S"
TYPE_PARAM_LIST@[8; 33)
L_ANGLE@[8; 9)
TYPE_PARAM@[9; 32)
IDENT@[9; 10) "T"
COLON@[10; 11)
WHITESPACE@[11; 12)
LIFETIME@[12; 14) "'a"
WHITESPACE@[14; 15)
PLUS@[15; 16)
WHITESPACE@[16; 17)
QUESTION@[17; 18)
PATH@[18; 24)
PATH_SEGMENT@[18; 24)
NAME_REF@[18; 24)
IDENT@[18; 23) "Sized"
WHITESPACE@[23; 24)
PLUS@[24; 25)
WHITESPACE@[25; 26)
L_PAREN@[26; 27)
PATH@[27; 31)
PATH_SEGMENT@[27; 31)
NAME_REF@[27; 31)
IDENT@[27; 31) "Copy"
R_PAREN@[31; 32)
R_ANGLE@[32; 33)
SEMI@[33; 34)
WHITESPACE@[34; 35)

View file

@ -0,0 +1 @@
struct S<T = i32>;

View file

@ -0,0 +1,21 @@
FILE@[0; 19)
STRUCT_ITEM@[0; 19)
STRUCT_KW@[0; 6)
NAME@[6; 8)
WHITESPACE@[6; 7)
IDENT@[7; 8) "S"
TYPE_PARAM_LIST@[8; 17)
L_ANGLE@[8; 9)
TYPE_PARAM@[9; 16)
IDENT@[9; 10) "T"
WHITESPACE@[10; 11)
EQ@[11; 12)
PATH_TYPE@[12; 16)
PATH@[12; 16)
PATH_SEGMENT@[12; 16)
NAME_REF@[12; 16)
WHITESPACE@[12; 13)
IDENT@[13; 16) "i32"
R_ANGLE@[16; 17)
SEMI@[17; 18)
WHITESPACE@[18; 19)