mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Swap Subtree::token_trees from Vec to boxed slice
This commit is contained in:
parent
8f6a72871e
commit
8011b56827
22 changed files with 194 additions and 158 deletions
|
@ -2125,7 +2125,7 @@ impl ModCollector<'_, '_> {
|
|||
|
||||
let is_export = export_attr.exists();
|
||||
let local_inner = if is_export {
|
||||
export_attr.tt_values().flat_map(|it| &it.token_trees).any(|it| match it {
|
||||
export_attr.tt_values().flat_map(|it| it.token_trees.iter()).any(|it| match it {
|
||||
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
|
||||
ident.text.contains("local_inner_macros")
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ impl RawAttrs {
|
|||
.filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)));
|
||||
|
||||
let cfg_options = &crate_graph[krate].cfg_options;
|
||||
let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
|
||||
let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) };
|
||||
let cfg = CfgExpr::parse(&cfg);
|
||||
if cfg_options.check(&cfg) == Some(false) {
|
||||
smallvec![]
|
||||
|
|
|
@ -137,5 +137,8 @@ pub fn pseudo_derive_attr_expansion(
|
|||
token_trees.extend(tt.iter().cloned());
|
||||
token_trees.push(mk_leaf(']'));
|
||||
}
|
||||
ExpandResult::ok(tt::Subtree { delimiter: tt.delimiter, token_trees })
|
||||
ExpandResult::ok(tt::Subtree {
|
||||
delimiter: tt.delimiter,
|
||||
token_trees: token_trees.into_boxed_slice(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -155,10 +155,10 @@ fn line_expand(
|
|||
// not incremental
|
||||
ExpandResult::ok(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(span),
|
||||
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
|
||||
token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
|
||||
text: "0u32".into(),
|
||||
span,
|
||||
}))],
|
||||
}))]),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -208,11 +208,11 @@ fn assert_expand(
|
|||
[cond, panic_args @ ..] => {
|
||||
let comma = tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(call_site_span),
|
||||
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
|
||||
token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
|
||||
char: ',',
|
||||
spacing: tt::Spacing::Alone,
|
||||
span: call_site_span,
|
||||
}))],
|
||||
}))]),
|
||||
};
|
||||
let cond = cond.clone();
|
||||
let panic_args = itertools::Itertools::intersperse(panic_args.iter().cloned(), comma);
|
||||
|
@ -359,7 +359,12 @@ fn panic_expand(
|
|||
close: call_site_span,
|
||||
kind: tt::DelimiterKind::Parenthesis,
|
||||
};
|
||||
call.token_trees.push(tt::TokenTree::Subtree(subtree));
|
||||
|
||||
// FIXME(slow): quote! have a way to expand to builder to make this a vec!
|
||||
let mut mutable_trees = std::mem::take(&mut call.token_trees).into_vec();
|
||||
mutable_trees.push(tt::TokenTree::Subtree(subtree));
|
||||
call.token_trees = mutable_trees.into_boxed_slice();
|
||||
|
||||
ExpandResult::ok(call)
|
||||
}
|
||||
|
||||
|
@ -388,7 +393,12 @@ fn unreachable_expand(
|
|||
close: call_site_span,
|
||||
kind: tt::DelimiterKind::Parenthesis,
|
||||
};
|
||||
call.token_trees.push(tt::TokenTree::Subtree(subtree));
|
||||
|
||||
// FIXME(slow): quote! have a way to expand to builder to make this a vec!
|
||||
let mut mutable_trees = std::mem::take(&mut call.token_trees).into_vec();
|
||||
mutable_trees.push(tt::TokenTree::Subtree(subtree));
|
||||
call.token_trees = mutable_trees.into_boxed_slice();
|
||||
|
||||
ExpandResult::ok(call)
|
||||
}
|
||||
|
||||
|
@ -675,10 +685,10 @@ fn include_bytes_expand(
|
|||
// FIXME: actually read the file here if the user asked for macro expansion
|
||||
let res = tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(span),
|
||||
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
|
||||
token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
|
||||
text: r#"b"""#.into(),
|
||||
span,
|
||||
}))],
|
||||
}))]),
|
||||
};
|
||||
ExpandResult::ok(res)
|
||||
}
|
||||
|
|
|
@ -524,7 +524,7 @@ fn macro_expand(
|
|||
return ExpandResult {
|
||||
value: CowArc::Owned(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||
token_trees: Vec::new(),
|
||||
token_trees: Box::new([]),
|
||||
}),
|
||||
// FIXME: We should make sure to enforce an invariant that invalid macro
|
||||
// calls do not reach this call path!
|
||||
|
@ -586,7 +586,7 @@ fn macro_expand(
|
|||
return value.map(|()| {
|
||||
CowArc::Owned(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -601,7 +601,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
|
|||
return ExpandResult {
|
||||
value: Arc::new(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||
token_trees: Vec::new(),
|
||||
token_trees: Box::new([]),
|
||||
}),
|
||||
// FIXME: We should make sure to enforce an invariant that invalid macro
|
||||
// calls do not reach this call path!
|
||||
|
@ -635,7 +635,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
|
|||
return value.map(|()| {
|
||||
Arc::new(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ pub(crate) fn reverse_fixups(tt: &mut Subtree, undo_info: &SyntaxFixupUndoInfo)
|
|||
}
|
||||
|
||||
fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
|
||||
let tts = std::mem::take(&mut tt.token_trees);
|
||||
let tts = std::mem::take(&mut tt.token_trees).into_vec();
|
||||
tt.token_trees = tts
|
||||
.into_iter()
|
||||
// delete all fake nodes
|
||||
|
@ -343,7 +343,7 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
|
|||
// we have a fake node here, we need to replace it again with the original
|
||||
let original = undo_info[u32::from(leaf.span().range.start()) as usize].clone();
|
||||
if original.delimiter.kind == tt::DelimiterKind::Invisible {
|
||||
original.token_trees.into()
|
||||
SmallVec::from(original.token_trees.into_vec())
|
||||
} else {
|
||||
SmallVec::from_const([original.into()])
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ mod tests {
|
|||
fn check_subtree_eq(a: &tt::Subtree, b: &tt::Subtree) -> bool {
|
||||
a.delimiter.kind == b.delimiter.kind
|
||||
&& a.token_trees.len() == b.token_trees.len()
|
||||
&& a.token_trees.iter().zip(&b.token_trees).all(|(a, b)| check_tt_eq(a, b))
|
||||
&& a.token_trees.iter().zip(b.token_trees.iter()).all(|(a, b)| check_tt_eq(a, b))
|
||||
}
|
||||
|
||||
fn check_tt_eq(a: &tt::TokenTree, b: &tt::TokenTree) -> bool {
|
||||
|
|
|
@ -66,6 +66,7 @@ pub mod tt {
|
|||
pub type Delimiter = ::tt::Delimiter<Span>;
|
||||
pub type DelimSpan = ::tt::DelimSpan<Span>;
|
||||
pub type Subtree = ::tt::Subtree<Span>;
|
||||
pub type SubtreeBuilder = ::tt::SubtreeBuilder<Span>;
|
||||
pub type Leaf = ::tt::Leaf<Span>;
|
||||
pub type Literal = ::tt::Literal<Span>;
|
||||
pub type Punct = ::tt::Punct<Span>;
|
||||
|
@ -760,7 +761,7 @@ impl ExpansionInfo {
|
|||
(
|
||||
Arc::new(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||
token_trees: Vec::new(),
|
||||
token_trees: Box::new([]),
|
||||
}),
|
||||
SyntaxFixupUndoInfo::NONE,
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ macro_rules! __quote {
|
|||
open: $span,
|
||||
close: $span,
|
||||
},
|
||||
token_trees: $crate::quote::IntoTt::to_tokens(children),
|
||||
token_trees: $crate::quote::IntoTt::to_tokens(children).into_boxed_slice(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -146,7 +146,7 @@ impl IntoTt for Vec<crate::tt::TokenTree> {
|
|||
fn to_subtree(self, span: Span) -> crate::tt::Subtree {
|
||||
crate::tt::Subtree {
|
||||
delimiter: crate::tt::Delimiter::invisible_spanned(span),
|
||||
token_trees: self,
|
||||
token_trees: self.into_boxed_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,8 +296,9 @@ mod tests {
|
|||
// }
|
||||
let struct_name = mk_ident("Foo");
|
||||
let fields = [mk_ident("name"), mk_ident("id")];
|
||||
let fields =
|
||||
fields.iter().flat_map(|it| quote!(DUMMY =>#it: self.#it.clone(), ).token_trees);
|
||||
let fields = fields
|
||||
.iter()
|
||||
.flat_map(|it| quote!(DUMMY =>#it: self.#it.clone(), ).token_trees.into_vec());
|
||||
|
||||
let list = crate::tt::Subtree {
|
||||
delimiter: crate::tt::Delimiter {
|
||||
|
|
|
@ -100,17 +100,19 @@ fn invocation_fixtures(
|
|||
// So we just skip any error cases and try again
|
||||
let mut try_cnt = 0;
|
||||
loop {
|
||||
let mut subtree = tt::Subtree {
|
||||
let mut token_trees = Vec::new();
|
||||
for op in rule.lhs.iter() {
|
||||
collect_from_op(op, &mut token_trees, &mut seed);
|
||||
}
|
||||
|
||||
let subtree = tt::Subtree {
|
||||
delimiter: tt::Delimiter {
|
||||
open: DUMMY,
|
||||
close: DUMMY,
|
||||
kind: tt::DelimiterKind::Invisible,
|
||||
},
|
||||
token_trees: vec![],
|
||||
token_trees: token_trees.into_boxed_slice(),
|
||||
};
|
||||
for op in rule.lhs.iter() {
|
||||
collect_from_op(op, &mut subtree, &mut seed);
|
||||
}
|
||||
if it.expand(&subtree, |_| (), true, DUMMY).err.is_none() {
|
||||
res.push((name.clone(), subtree));
|
||||
break;
|
||||
|
@ -127,45 +129,45 @@ fn invocation_fixtures(
|
|||
|
||||
fn collect_from_op(
|
||||
op: &Op<DummyTestSpanData>,
|
||||
parent: &mut tt::Subtree<DummyTestSpanData>,
|
||||
token_trees: &mut Vec<tt::TokenTree<DummyTestSpanData>>,
|
||||
seed: &mut usize,
|
||||
) {
|
||||
return match op {
|
||||
Op::Var { kind, .. } => match kind.as_ref() {
|
||||
Some(MetaVarKind::Ident) => parent.token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Ty) => parent.token_trees.push(make_ident("Foo")),
|
||||
Some(MetaVarKind::Tt) => parent.token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Vis) => parent.token_trees.push(make_ident("pub")),
|
||||
Some(MetaVarKind::Pat) => parent.token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Path) => parent.token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Literal) => parent.token_trees.push(make_literal("1")),
|
||||
Some(MetaVarKind::Expr) => parent.token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Ident) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Ty) => token_trees.push(make_ident("Foo")),
|
||||
Some(MetaVarKind::Tt) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Vis) => token_trees.push(make_ident("pub")),
|
||||
Some(MetaVarKind::Pat) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Path) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Literal) => token_trees.push(make_literal("1")),
|
||||
Some(MetaVarKind::Expr) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Lifetime) => {
|
||||
parent.token_trees.push(make_punct('\''));
|
||||
parent.token_trees.push(make_ident("a"));
|
||||
token_trees.push(make_punct('\''));
|
||||
token_trees.push(make_ident("a"));
|
||||
}
|
||||
Some(MetaVarKind::Block) => {
|
||||
parent.token_trees.push(make_subtree(tt::DelimiterKind::Brace, None))
|
||||
token_trees.push(make_subtree(tt::DelimiterKind::Brace, None))
|
||||
}
|
||||
Some(MetaVarKind::Item) => {
|
||||
parent.token_trees.push(make_ident("fn"));
|
||||
parent.token_trees.push(make_ident("foo"));
|
||||
parent.token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
|
||||
parent.token_trees.push(make_subtree(tt::DelimiterKind::Brace, None));
|
||||
token_trees.push(make_ident("fn"));
|
||||
token_trees.push(make_ident("foo"));
|
||||
token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
|
||||
token_trees.push(make_subtree(tt::DelimiterKind::Brace, None));
|
||||
}
|
||||
Some(MetaVarKind::Meta) => {
|
||||
parent.token_trees.push(make_ident("foo"));
|
||||
parent.token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
|
||||
token_trees.push(make_ident("foo"));
|
||||
token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
|
||||
}
|
||||
|
||||
None => (),
|
||||
Some(kind) => panic!("Unhandled kind {kind:?}"),
|
||||
},
|
||||
Op::Literal(it) => parent.token_trees.push(tt::Leaf::from(it.clone()).into()),
|
||||
Op::Ident(it) => parent.token_trees.push(tt::Leaf::from(it.clone()).into()),
|
||||
Op::Literal(it) => token_trees.push(tt::Leaf::from(it.clone()).into()),
|
||||
Op::Ident(it) => token_trees.push(tt::Leaf::from(it.clone()).into()),
|
||||
Op::Punct(puncts) => {
|
||||
for punct in puncts {
|
||||
parent.token_trees.push(tt::Leaf::from(*punct).into());
|
||||
token_trees.push(tt::Leaf::from(*punct).into());
|
||||
}
|
||||
}
|
||||
Op::Repeat { tokens, kind, separator } => {
|
||||
|
@ -177,20 +179,20 @@ fn invocation_fixtures(
|
|||
};
|
||||
for i in 0..cnt {
|
||||
for it in tokens.iter() {
|
||||
collect_from_op(it, parent, seed);
|
||||
collect_from_op(it, token_trees, seed);
|
||||
}
|
||||
if i + 1 != cnt {
|
||||
if let Some(sep) = separator {
|
||||
match sep {
|
||||
Separator::Literal(it) => {
|
||||
parent.token_trees.push(tt::Leaf::Literal(it.clone()).into())
|
||||
token_trees.push(tt::Leaf::Literal(it.clone()).into())
|
||||
}
|
||||
Separator::Ident(it) => {
|
||||
parent.token_trees.push(tt::Leaf::Ident(it.clone()).into())
|
||||
token_trees.push(tt::Leaf::Ident(it.clone()).into())
|
||||
}
|
||||
Separator::Puncts(puncts) => {
|
||||
for it in puncts {
|
||||
parent.token_trees.push(tt::Leaf::Punct(*it).into())
|
||||
token_trees.push(tt::Leaf::Punct(*it).into())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -199,11 +201,15 @@ fn invocation_fixtures(
|
|||
}
|
||||
}
|
||||
Op::Subtree { tokens, delimiter } => {
|
||||
let mut subtree = tt::Subtree { delimiter: *delimiter, token_trees: Vec::new() };
|
||||
let mut subtree = Vec::new();
|
||||
tokens.iter().for_each(|it| {
|
||||
collect_from_op(it, &mut subtree, seed);
|
||||
});
|
||||
parent.token_trees.push(subtree.into());
|
||||
|
||||
let subtree =
|
||||
tt::Subtree { delimiter: *delimiter, token_trees: subtree.into_boxed_slice() };
|
||||
|
||||
token_trees.push(subtree.into());
|
||||
}
|
||||
Op::Ignore { .. } | Op::Index { .. } | Op::Count { .. } | Op::Length { .. } => {}
|
||||
};
|
||||
|
@ -230,7 +236,7 @@ fn invocation_fixtures(
|
|||
) -> tt::TokenTree<DummyTestSpanData> {
|
||||
tt::Subtree {
|
||||
delimiter: tt::Delimiter { open: DUMMY, close: DUMMY, kind },
|
||||
token_trees: token_trees.unwrap_or_default(),
|
||||
token_trees: token_trees.map(Vec::into_boxed_slice).unwrap_or_default(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ pub(crate) fn expand_rules<S: Span>(
|
|||
ExpandResult::new(
|
||||
tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(call_site),
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
},
|
||||
ExpandError::NoMatchingRule,
|
||||
)
|
||||
|
|
|
@ -798,7 +798,7 @@ fn match_meta_var<S: Span>(
|
|||
tt.map(|tt| match tt {
|
||||
tt::TokenTree::Leaf(leaf) => tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
|
||||
token_trees: vec![leaf.into()],
|
||||
token_trees: Box::new([leaf.into()]),
|
||||
},
|
||||
tt::TokenTree::Subtree(mut s) => {
|
||||
if s.delimiter.kind == tt::DelimiterKind::Invisible {
|
||||
|
@ -832,7 +832,7 @@ fn match_meta_var<S: Span>(
|
|||
None => lit.into(),
|
||||
Some(neg) => tt::TokenTree::Subtree(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(*literal.span()),
|
||||
token_trees: vec![neg, lit.into()],
|
||||
token_trees: Box::new([neg, lit.into()]),
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
@ -989,10 +989,10 @@ impl<S: Span> TtIter<'_, S> {
|
|||
close: ident.span,
|
||||
kind: tt::DelimiterKind::Invisible,
|
||||
},
|
||||
token_trees: vec![
|
||||
token_trees: Box::new([
|
||||
tt::Leaf::Punct(*punct).into(),
|
||||
tt::Leaf::Ident(ident.clone()).into(),
|
||||
],
|
||||
]),
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ impl<S: Span> Bindings<S> {
|
|||
close: span,
|
||||
kind: tt::DelimiterKind::Brace,
|
||||
},
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
})),
|
||||
// FIXME: Meta and Item should get proper defaults
|
||||
MetaVarKind::Meta | MetaVarKind::Item | MetaVarKind::Tt | MetaVarKind::Vis => {
|
||||
|
@ -349,11 +349,11 @@ fn expand_var<S: Span>(
|
|||
// We just treat it a normal tokens
|
||||
let tt = tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(id),
|
||||
token_trees: vec![
|
||||
token_trees: Box::new([
|
||||
tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id })
|
||||
.into(),
|
||||
tt::Leaf::from(tt::Ident { text: v.clone(), span: id }).into(),
|
||||
],
|
||||
]),
|
||||
}
|
||||
.into();
|
||||
ExpandResult::ok(Fragment::Tokens(tt))
|
||||
|
@ -406,7 +406,7 @@ fn expand_repeat<S: Span>(
|
|||
value: Fragment::Tokens(
|
||||
tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(ctx.call_site),
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
|
@ -455,7 +455,7 @@ fn expand_repeat<S: Span>(
|
|||
// e.g {Delimiter:None> ['>'] /Delimiter:None>}
|
||||
let tt = tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(ctx.call_site),
|
||||
token_trees: buf,
|
||||
token_trees: buf.into_boxed_slice(),
|
||||
}
|
||||
.into();
|
||||
|
||||
|
@ -486,7 +486,7 @@ fn push_fragment<S: Span>(
|
|||
|
||||
fn push_subtree<S>(buf: &mut Vec<tt::TokenTree<S>>, tt: tt::Subtree<S>) {
|
||||
match tt.delimiter.kind {
|
||||
tt::DelimiterKind::Invisible => buf.extend(tt.token_trees),
|
||||
tt::DelimiterKind::Invisible => buf.extend(Vec::from(tt.token_trees)),
|
||||
_ => buf.push(tt.into()),
|
||||
}
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ fn fix_up_and_push_path_tt<S: Span>(
|
|||
// Note that we only need to fix up the top-level `TokenTree`s because the
|
||||
// context of the paths in the descendant `Subtree`s won't be changed by the
|
||||
// mbe transcription.
|
||||
for tt in subtree.token_trees {
|
||||
for tt in Vec::from(subtree.token_trees) {
|
||||
if prev_was_ident {
|
||||
// Pedantically, `(T) -> U` in `FnOnce(T) -> U` is treated as a generic
|
||||
// argument list and thus needs `::` between it and `FnOnce`. However in
|
||||
|
|
|
@ -130,7 +130,7 @@ where
|
|||
tt::Subtree {
|
||||
delimiter: tt::Delimiter { kind: tt::DelimiterKind::Invisible, .. },
|
||||
token_trees,
|
||||
} => TokenBuffer::from_tokens(token_trees.as_slice()),
|
||||
} => TokenBuffer::from_tokens(token_trees),
|
||||
_ => TokenBuffer::from_subtree(tt),
|
||||
};
|
||||
let parser_input = to_parser_input(&buffer);
|
||||
|
@ -227,14 +227,14 @@ where
|
|||
C: TokenConverter<S>,
|
||||
S: Span,
|
||||
{
|
||||
let entry = tt::Subtree {
|
||||
let entry = tt::SubtreeBuilder {
|
||||
delimiter: tt::Delimiter::invisible_spanned(conv.call_site()),
|
||||
token_trees: vec![],
|
||||
};
|
||||
let mut stack = NonEmptyVec::new(entry);
|
||||
|
||||
while let Some((token, abs_range)) = conv.bump() {
|
||||
let tt::Subtree { delimiter, token_trees } = stack.last_mut();
|
||||
let tt::SubtreeBuilder { delimiter, token_trees } = stack.last_mut();
|
||||
|
||||
let tt = match token.as_leaf() {
|
||||
Some(leaf) => tt::TokenTree::Leaf(leaf.clone()),
|
||||
|
@ -260,7 +260,7 @@ where
|
|||
if matches!(expected, Some(expected) if expected == kind) {
|
||||
if let Some(mut subtree) = stack.pop() {
|
||||
subtree.delimiter.close = conv.span_for(abs_range);
|
||||
stack.last_mut().token_trees.push(subtree.into());
|
||||
stack.last_mut().token_trees.push(subtree.build().into());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ where
|
|||
// Start a new subtree
|
||||
if let Some(kind) = delim {
|
||||
let open = conv.span_for(abs_range);
|
||||
stack.push(tt::Subtree {
|
||||
stack.push(tt::SubtreeBuilder {
|
||||
delimiter: tt::Delimiter {
|
||||
open,
|
||||
// will be overwritten on subtree close above
|
||||
|
@ -361,7 +361,7 @@ where
|
|||
parent.token_trees.extend(entry.token_trees);
|
||||
}
|
||||
|
||||
let subtree = stack.into_last();
|
||||
let subtree = stack.into_last().build();
|
||||
if let [tt::TokenTree::Subtree(first)] = &*subtree.token_trees {
|
||||
first.clone()
|
||||
} else {
|
||||
|
@ -454,7 +454,7 @@ fn convert_doc_comment<S: Copy>(
|
|||
};
|
||||
|
||||
// Make `doc="\" Comments\""
|
||||
let meta_tkns = vec![mk_ident("doc"), mk_punct('='), mk_doc_literal(&comment)];
|
||||
let meta_tkns = Box::new([mk_ident("doc"), mk_punct('='), mk_doc_literal(&comment)]);
|
||||
|
||||
// Make `#![]`
|
||||
let mut token_trees = Vec::with_capacity(3);
|
||||
|
|
|
@ -180,7 +180,7 @@ impl<'a, S: Span> TtIter<'a, S> {
|
|||
[] | [_] => res.pop(),
|
||||
[first, ..] => Some(tt::TokenTree::Subtree(tt::Subtree {
|
||||
delimiter: tt::Delimiter::invisible_spanned(first.first_span()),
|
||||
token_trees: res,
|
||||
token_trees: res.into_boxed_slice(),
|
||||
})),
|
||||
};
|
||||
ExpandResult { value: res, err }
|
||||
|
|
|
@ -187,7 +187,67 @@ mod tests {
|
|||
file_id: FileId::from_raw(0),
|
||||
ast_id: ErasedFileAstId::from_raw(RawIdx::from(0)),
|
||||
};
|
||||
let mut subtree = Subtree {
|
||||
|
||||
let token_trees = Box::new([
|
||||
TokenTree::Leaf(
|
||||
Ident {
|
||||
text: "struct".into(),
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(0), TextSize::of("struct")),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
TokenTree::Leaf(
|
||||
Ident {
|
||||
text: "Foo".into(),
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(5), TextSize::of("Foo")),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
TokenTree::Leaf(Leaf::Literal(Literal {
|
||||
text: "Foo".into(),
|
||||
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(8), TextSize::of("Foo")),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
})),
|
||||
TokenTree::Leaf(Leaf::Punct(Punct {
|
||||
char: '@',
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(11), TextSize::of('@')),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
spacing: Spacing::Joint,
|
||||
})),
|
||||
TokenTree::Subtree(Subtree {
|
||||
delimiter: Delimiter {
|
||||
open: Span {
|
||||
range: TextRange::at(TextSize::new(12), TextSize::of('{')),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
close: Span {
|
||||
range: TextRange::at(TextSize::new(13), TextSize::of('}')),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
kind: DelimiterKind::Brace,
|
||||
},
|
||||
token_trees: Box::new([]),
|
||||
}),
|
||||
]);
|
||||
|
||||
Subtree {
|
||||
delimiter: Delimiter {
|
||||
open: Span {
|
||||
range: TextRange::empty(TextSize::new(0)),
|
||||
|
@ -201,65 +261,8 @@ mod tests {
|
|||
},
|
||||
kind: DelimiterKind::Invisible,
|
||||
},
|
||||
token_trees: Vec::new(),
|
||||
};
|
||||
subtree.token_trees.push(TokenTree::Leaf(
|
||||
Ident {
|
||||
text: "struct".into(),
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(0), TextSize::of("struct")),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
subtree.token_trees.push(TokenTree::Leaf(
|
||||
Ident {
|
||||
text: "Foo".into(),
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(5), TextSize::of("Foo")),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
subtree.token_trees.push(TokenTree::Leaf(Leaf::Literal(Literal {
|
||||
text: "Foo".into(),
|
||||
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(8), TextSize::of("Foo")),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
})));
|
||||
subtree.token_trees.push(TokenTree::Leaf(Leaf::Punct(Punct {
|
||||
char: '@',
|
||||
span: Span {
|
||||
range: TextRange::at(TextSize::new(11), TextSize::of('@')),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
spacing: Spacing::Joint,
|
||||
})));
|
||||
subtree.token_trees.push(TokenTree::Subtree(Subtree {
|
||||
delimiter: Delimiter {
|
||||
open: Span {
|
||||
range: TextRange::at(TextSize::new(12), TextSize::of('{')),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
close: Span {
|
||||
range: TextRange::at(TextSize::new(13), TextSize::of('}')),
|
||||
anchor,
|
||||
ctx: SyntaxContextId::ROOT,
|
||||
},
|
||||
kind: DelimiterKind::Brace,
|
||||
},
|
||||
token_trees: vec![],
|
||||
}));
|
||||
subtree
|
||||
token_trees,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -370,7 +370,7 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> {
|
|||
|
||||
self.subtree[idx].tt = [first_tt as u32, (first_tt + n_tt) as u32];
|
||||
|
||||
for child in &subtree.token_trees {
|
||||
for child in subtree.token_trees.iter() {
|
||||
let idx_tag = match child {
|
||||
tt::TokenTree::Subtree(it) => {
|
||||
let idx = self.enqueue(it);
|
||||
|
|
|
@ -104,7 +104,7 @@ impl server::TokenStream for RaSpanServer {
|
|||
delimiter: delim_to_internal(group.delimiter, group.span),
|
||||
token_trees: match group.stream {
|
||||
Some(stream) => stream.into_iter().collect(),
|
||||
None => Vec::new(),
|
||||
None => Box::new([]),
|
||||
},
|
||||
};
|
||||
let tree = tt::TokenTree::from(group);
|
||||
|
@ -221,7 +221,7 @@ impl server::TokenStream for RaSpanServer {
|
|||
stream: if subtree.token_trees.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(subtree.token_trees.into_iter().collect())
|
||||
Some(subtree.token_trees.into_vec().into_iter().collect())
|
||||
},
|
||||
span: bridge::DelimSpan::from_single(subtree.delimiter.open),
|
||||
}),
|
||||
|
|
|
@ -94,7 +94,7 @@ impl server::TokenStream for TokenIdServer {
|
|||
delimiter: delim_to_internal(group.delimiter, group.span),
|
||||
token_trees: match group.stream {
|
||||
Some(stream) => stream.into_iter().collect(),
|
||||
None => Vec::new(),
|
||||
None => Box::new([]),
|
||||
},
|
||||
};
|
||||
let tree = TokenTree::from(group);
|
||||
|
@ -206,7 +206,7 @@ impl server::TokenStream for TokenIdServer {
|
|||
stream: if subtree.token_trees.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(TokenStream { token_trees: subtree.token_trees })
|
||||
Some(TokenStream { token_trees: subtree.token_trees.into_vec() })
|
||||
},
|
||||
span: bridge::DelimSpan::from_single(subtree.delimiter.open),
|
||||
}),
|
||||
|
@ -338,7 +338,7 @@ mod tests {
|
|||
close: tt::TokenId(0),
|
||||
kind: tt::DelimiterKind::Brace,
|
||||
},
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
@ -354,10 +354,10 @@ mod tests {
|
|||
close: tt::TokenId(0),
|
||||
kind: tt::DelimiterKind::Parenthesis,
|
||||
},
|
||||
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
|
||||
token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
|
||||
text: "a".into(),
|
||||
span: tt::TokenId(0),
|
||||
}))],
|
||||
}))]),
|
||||
});
|
||||
|
||||
let t1 = TokenStream::from_str("(a)", tt::TokenId(0)).unwrap();
|
||||
|
|
|
@ -15,14 +15,14 @@ impl<S> Default for TokenStream<S> {
|
|||
|
||||
impl<S> TokenStream<S> {
|
||||
pub(crate) fn new() -> Self {
|
||||
TokenStream { token_trees: vec![] }
|
||||
TokenStream::default()
|
||||
}
|
||||
|
||||
pub(crate) fn with_subtree(subtree: tt::Subtree<S>) -> Self {
|
||||
if subtree.delimiter.kind != tt::DelimiterKind::Invisible {
|
||||
TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
|
||||
} else {
|
||||
TokenStream { token_trees: subtree.token_trees }
|
||||
TokenStream { token_trees: subtree.token_trees.into_vec() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ impl<S> TokenStream<S> {
|
|||
close: call_site,
|
||||
kind: tt::DelimiterKind::Invisible,
|
||||
},
|
||||
token_trees: self.token_trees,
|
||||
token_trees: self.token_trees.into_boxed_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ impl<S> Extend<TokenStream<S>> for TokenStream<S> {
|
|||
tt::TokenTree::Subtree(subtree)
|
||||
if subtree.delimiter.kind == tt::DelimiterKind::Invisible =>
|
||||
{
|
||||
self.token_trees.extend(subtree.token_trees);
|
||||
self.token_trees.extend(subtree.token_trees.into_vec().into_iter());
|
||||
}
|
||||
_ => {
|
||||
self.token_trees.push(tkn);
|
||||
|
|
|
@ -598,7 +598,7 @@ impl ProcMacroExpander for MirrorProcMacroExpander {
|
|||
};
|
||||
token_trees.push(tt);
|
||||
}
|
||||
Subtree { delimiter: input.delimiter, token_trees }
|
||||
Subtree { delimiter: input.delimiter, token_trees: token_trees.into_boxed_slice() }
|
||||
}
|
||||
Ok(traverse(input))
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ impl<'t, Span> TokenBuffer<'t, Span> {
|
|||
|
||||
for (child_idx, (subtree, tt)) in children {
|
||||
let idx = TokenBuffer::new_inner(
|
||||
subtree.token_trees.as_slice(),
|
||||
&*subtree.token_trees,
|
||||
buffers,
|
||||
Some(EntryPtr(EntryId(res), child_idx + 1)),
|
||||
);
|
||||
|
|
|
@ -23,10 +23,10 @@ pub enum TokenTree<S> {
|
|||
}
|
||||
impl_from!(Leaf<S>, Subtree<S> for TokenTree);
|
||||
impl<S: Span> TokenTree<S> {
|
||||
pub const fn empty(span: S) -> Self {
|
||||
pub fn empty(span: S) -> Self {
|
||||
Self::Subtree(Subtree {
|
||||
delimiter: Delimiter::invisible_spanned(span),
|
||||
token_trees: vec![],
|
||||
token_trees: Box::new([]),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ impl<S: Span> TokenTree<S> {
|
|||
match self {
|
||||
TokenTree::Leaf(_) => Subtree {
|
||||
delimiter: Delimiter::invisible_delim_spanned(span),
|
||||
token_trees: vec![self],
|
||||
token_trees: Box::new([self]),
|
||||
},
|
||||
TokenTree::Subtree(s) => s,
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ impl_from!(Literal<S>, Punct<S>, Ident<S> for Leaf);
|
|||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Subtree<S> {
|
||||
pub delimiter: Delimiter<S>,
|
||||
pub token_trees: Vec<TokenTree<S>>,
|
||||
pub token_trees: Box<[TokenTree<S>]>,
|
||||
}
|
||||
|
||||
impl<S: Span> Subtree<S> {
|
||||
pub const fn empty(span: DelimSpan<S>) -> Self {
|
||||
Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: vec![] }
|
||||
pub fn empty(span: DelimSpan<S>) -> Self {
|
||||
Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: Box::new([]) }
|
||||
}
|
||||
|
||||
pub fn visit_ids(&mut self, f: &mut impl FnMut(S) -> S) {
|
||||
|
@ -91,6 +91,18 @@ impl<S: Span> Subtree<S> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct SubtreeBuilder<S> {
|
||||
pub delimiter: Delimiter<S>,
|
||||
pub token_trees: Vec<TokenTree<S>>,
|
||||
}
|
||||
|
||||
impl<S> SubtreeBuilder<S> {
|
||||
pub fn build(self) -> Subtree<S> {
|
||||
Subtree { delimiter: self.delimiter, token_trees: self.token_trees.into_boxed_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct DelimSpan<S> {
|
||||
pub open: S,
|
||||
|
@ -241,7 +253,7 @@ impl<S> fmt::Display for Subtree<S> {
|
|||
};
|
||||
f.write_str(l)?;
|
||||
let mut needs_space = false;
|
||||
for tt in &self.token_trees {
|
||||
for tt in self.token_trees.iter() {
|
||||
if needs_space {
|
||||
f.write_str(" ")?;
|
||||
}
|
||||
|
@ -316,7 +328,7 @@ impl<S> Subtree<S> {
|
|||
let mut res = String::new();
|
||||
res.push_str(delim.0);
|
||||
let mut last = None;
|
||||
for child in &self.token_trees {
|
||||
for child in self.token_trees.iter() {
|
||||
let s = match child {
|
||||
TokenTree::Leaf(it) => {
|
||||
let s = match it {
|
||||
|
|
Loading…
Reference in a new issue