Skip to content

Commit d3d47b8

Browse files
Separate the public tt API from how they're stored
And don't provide any insight into the actual storage (no references, no "cheat" methods like `flat_tokens()`), as we're going to rewrite it to be more memory efficient.
1 parent 1372157 commit d3d47b8

24 files changed

Lines changed: 350 additions & 293 deletions

File tree

crates/cfg/src/cfg_expr.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,18 @@ fn next_cfg_expr(it: &mut tt::iter::TtIter<'_>) -> Option<CfgExpr> {
197197
Some(_) => return Some(CfgExpr::Invalid),
198198
};
199199

200-
let ret = match it.peek() {
200+
let mut it_clone = it.clone();
201+
let ret = match it_clone.next() {
201202
Some(TtElement::Leaf(tt::Leaf::Punct(punct)))
202203
// Don't consume on e.g. `=>`.
203204
if punct.char == '='
204205
&& (punct.spacing == tt::Spacing::Alone
205-
|| it.remaining().flat_tokens().get(1).is_none_or(|peek2| {
206-
!matches!(peek2, tt::TokenTree::Leaf(tt::Leaf::Punct(_)))
206+
|| it_clone.peek().is_none_or(|peek2| {
207+
!matches!(peek2, tt::TtElement::Leaf(tt::Leaf::Punct(_)))
207208
})) =>
208209
{
209-
match it.remaining().flat_tokens().get(1) {
210-
Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => {
210+
match it_clone.next() {
211+
Some(tt::TtElement::Leaf(tt::Leaf::Literal(literal))) => {
211212
it.next();
212213
it.next();
213214
CfgAtom::KeyValue { key: name, value: literal.symbol.clone() }.into()

crates/hir-def/src/nameres/attr_resolution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub(super) fn attr_macro_as_call_id(
114114
let arg = match macro_attr.input.as_deref() {
115115
Some(AttrInput::TokenTree(tt)) => {
116116
let mut tt = tt.clone();
117-
tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
117+
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
118118
Some(tt)
119119
}
120120

crates/hir-def/src/nameres/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2466,8 +2466,8 @@ impl ModCollector<'_, '_> {
24662466
None => {
24672467
let explicit_name =
24682468
attrs.by_key(sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
2469-
match tt.token_trees().flat_tokens().first() {
2470-
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
2469+
match tt.token_trees().iter().next() {
2470+
Some(tt::TtElement::Leaf(tt::Leaf::Ident(name))) => Some(name),
24712471
_ => None,
24722472
}
24732473
});

crates/hir-def/src/nameres/proc_macro.rs

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
33
use hir_expand::name::{AsName, Name};
44
use intern::sym;
5+
use itertools::Itertools;
56

67
use crate::{
78
item_tree::Attrs,
8-
tt::{Leaf, TokenTree, TopSubtree, TtElement},
9+
tt::{Leaf, TopSubtree, TtElement},
910
};
1011

1112
#[derive(Debug, PartialEq, Eq)]
@@ -61,35 +62,35 @@ impl Attrs<'_> {
6162

6263
// This fn is intended for `#[proc_macro_derive(..)]` and `#[rustc_builtin_macro(..)]`, which have
6364
// the same structure.
64-
#[rustfmt::skip]
6565
pub(crate) fn parse_macro_name_and_helper_attrs(tt: &TopSubtree) -> Option<(Name, Box<[Name]>)> {
66-
match tt.token_trees().flat_tokens() {
66+
if let Some([TtElement::Leaf(Leaf::Ident(trait_name))]) =
67+
tt.token_trees().iter().collect_array()
68+
{
6769
// `#[proc_macro_derive(Trait)]`
6870
// `#[rustc_builtin_macro(Trait)]`
69-
[TokenTree::Leaf(Leaf::Ident(trait_name))] => Some((trait_name.as_name(), Box::new([]))),
70-
71+
Some((trait_name.as_name(), Box::new([])))
72+
} else if let Some(
73+
[
74+
TtElement::Leaf(Leaf::Ident(trait_name)),
75+
TtElement::Leaf(Leaf::Punct(comma)),
76+
TtElement::Leaf(Leaf::Ident(attributes)),
77+
TtElement::Subtree(_, helpers),
78+
],
79+
) = tt.token_trees().iter().collect_array()
80+
&& comma.char == ','
81+
&& attributes.sym == sym::attributes
82+
{
7183
// `#[proc_macro_derive(Trait, attributes(helper1, helper2, ...))]`
7284
// `#[rustc_builtin_macro(Trait, attributes(helper1, helper2, ...))]`
73-
[
74-
TokenTree::Leaf(Leaf::Ident(trait_name)),
75-
TokenTree::Leaf(Leaf::Punct(comma)),
76-
TokenTree::Leaf(Leaf::Ident(attributes)),
77-
TokenTree::Subtree(_),
78-
..
79-
] if comma.char == ',' && attributes.sym == sym::attributes =>
80-
{
81-
let helpers = tt::TokenTreesView::new(&tt.token_trees().flat_tokens()[3..]).try_into_subtree()?;
82-
let helpers = helpers
83-
.iter()
84-
.filter_map(|tt| match tt {
85-
TtElement::Leaf(Leaf::Ident(helper)) => Some(helper.as_name()),
86-
_ => None,
87-
})
88-
.collect::<Box<[_]>>();
89-
90-
Some((trait_name.as_name(), helpers))
91-
}
85+
let helpers = helpers
86+
.filter_map(|tt| match tt {
87+
TtElement::Leaf(Leaf::Ident(helper)) => Some(helper.as_name()),
88+
_ => None,
89+
})
90+
.collect::<Box<[_]>>();
9291

93-
_ => None,
92+
Some((trait_name.as_name(), helpers))
93+
} else {
94+
None
9495
}
9596
}

crates/hir-expand/src/attrs.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use base_db::Crate;
3636
use cfg::{CfgExpr, CfgOptions};
3737
use either::Either;
3838
use intern::{Interned, Symbol};
39+
use itertools::Itertools;
3940
use mbe::{DelimiterKind, Punct};
4041
use parser::T;
4142
use smallvec::SmallVec;
@@ -453,10 +454,10 @@ impl Attr {
453454
}
454455

455456
/// #[path(ident)]
456-
pub fn single_ident_value(&self) -> Option<&tt::Ident> {
457+
pub fn single_ident_value(&self) -> Option<tt::Ident> {
457458
match self.input.as_deref()? {
458-
AttrInput::TokenTree(tt) => match tt.token_trees().flat_tokens() {
459-
[tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
459+
AttrInput::TokenTree(tt) => match tt.token_trees().iter().collect_array() {
460+
Some([tt::TtElement::Leaf(tt::Leaf::Ident(ident))]) => Some(ident),
460461
_ => None,
461462
},
462463
_ => None,
@@ -492,7 +493,7 @@ fn parse_path_comma_token_tree<'a>(
492493
args.token_trees()
493494
.split(|tt| matches!(tt, tt::TtElement::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
494495
.filter_map(move |tts| {
495-
let span = tts.flat_tokens().first()?.first_span();
496+
let span = tts.first_span()?;
496497
Some((ModPath::from_tt(db, tts)?, span, tts))
497498
})
498499
}
@@ -611,16 +612,12 @@ impl AttrId {
611612
else {
612613
return derive_attr_range;
613614
};
614-
let (Some(first_tt), Some(last_tt)) =
615-
(derive_tts.flat_tokens().first(), derive_tts.flat_tokens().last())
615+
let (Some(first_span), Some(last_span)) = (derive_tts.first_span(), derive_tts.last_span())
616616
else {
617617
return derive_attr_range;
618618
};
619-
let start = first_tt.first_span().range.start();
620-
let end = match last_tt {
621-
tt::TokenTree::Leaf(it) => it.span().range.end(),
622-
tt::TokenTree::Subtree(it) => it.delimiter.close.range.end(),
623-
};
619+
let start = first_span.range.start();
620+
let end = last_span.range.end();
624621
TextRange::new(start, end)
625622
}
626623
}

crates/hir-expand/src/builtin/fn_macro.rs

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ fn stringify_expand(
210210
tt: &tt::TopSubtree,
211211
span: Span,
212212
) -> ExpandResult<tt::TopSubtree> {
213-
let pretty = ::tt::pretty(tt.token_trees().flat_tokens());
213+
let pretty = ::tt::pretty(tt.token_trees());
214214

215215
let expanded = quote! {span =>
216216
#pretty
@@ -283,7 +283,7 @@ fn format_args_expand(
283283
) -> ExpandResult<tt::TopSubtree> {
284284
let pound = mk_pound(span);
285285
let mut tt = tt.clone();
286-
tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
286+
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Parenthesis);
287287
ExpandResult::ok(quote! {span =>
288288
builtin #pound format_args #tt
289289
})
@@ -297,14 +297,14 @@ fn format_args_nl_expand(
297297
) -> ExpandResult<tt::TopSubtree> {
298298
let pound = mk_pound(span);
299299
let mut tt = tt.clone();
300-
tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
301-
if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
302-
symbol: text,
303-
kind: tt::LitKind::Str,
304-
..
305-
}))) = tt.0.get_mut(1)
300+
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Parenthesis);
301+
let lit = tt.as_token_trees().iter_flat_tokens().nth(1);
302+
if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(
303+
mut lit @ tt::Literal { kind: tt::LitKind::Str, .. },
304+
))) = lit
306305
{
307-
*text = Symbol::intern(&format_smolstr!("{}\\n", text.as_str()));
306+
lit.symbol = Symbol::intern(&format_smolstr!("{}\\n", lit.symbol.as_str()));
307+
tt.set_token(1, lit.into());
308308
}
309309
ExpandResult::ok(quote! {span =>
310310
builtin #pound format_args #tt
@@ -318,7 +318,7 @@ fn asm_expand(
318318
span: Span,
319319
) -> ExpandResult<tt::TopSubtree> {
320320
let mut tt = tt.clone();
321-
tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
321+
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Parenthesis);
322322
let pound = mk_pound(span);
323323
let expanded = quote! {span =>
324324
builtin #pound asm #tt
@@ -333,7 +333,7 @@ fn global_asm_expand(
333333
span: Span,
334334
) -> ExpandResult<tt::TopSubtree> {
335335
let mut tt = tt.clone();
336-
tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
336+
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Parenthesis);
337337
let pound = mk_pound(span);
338338
let expanded = quote! {span =>
339339
builtin #pound global_asm #tt
@@ -348,7 +348,7 @@ fn naked_asm_expand(
348348
span: Span,
349349
) -> ExpandResult<tt::TopSubtree> {
350350
let mut tt = tt.clone();
351-
tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
351+
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Parenthesis);
352352
let pound = mk_pound(span);
353353
let expanded = quote! {span =>
354354
builtin #pound naked_asm #tt
@@ -478,11 +478,11 @@ fn unreachable_expand(
478478

479479
// Pass the original arguments
480480
let mut subtree = tt.clone();
481-
*subtree.top_subtree_delimiter_mut() = tt::Delimiter {
481+
subtree.set_top_subtree_delimiter_kind(tt::DelimiterKind::Parenthesis);
482+
subtree.set_top_subtree_delimiter_span(tt::DelimSpan {
482483
open: call_site_span,
483484
close: call_site_span,
484-
kind: tt::DelimiterKind::Parenthesis,
485-
};
485+
});
486486

487487
// Expand to a macro call `$crate::panic::panic_{edition}`
488488
let call = quote!(call_site_span =>#dollar_crate::panic::#mac! #subtree);
@@ -518,16 +518,17 @@ fn compile_error_expand(
518518
tt: &tt::TopSubtree,
519519
span: Span,
520520
) -> ExpandResult<tt::TopSubtree> {
521-
let err = match &*tt.0 {
522-
[
523-
_,
524-
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
525-
symbol: text,
526-
span: _,
527-
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
528-
suffix: _,
529-
})),
530-
] => ExpandError::other(span, Box::from(unescape_symbol(text).as_str())),
521+
let err = match tt.iter().collect_array() {
522+
Some(
523+
[
524+
tt::TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
525+
symbol: text,
526+
span: _,
527+
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
528+
suffix: _,
529+
})),
530+
],
531+
) => ExpandError::other(span, Box::from(unescape_symbol(&text).as_str())),
531532
_ => ExpandError::other(span, "`compile_error!` argument must be a string"),
532533
};
533534

@@ -556,7 +557,7 @@ fn concat_expand(
556557
// to ensure the right parsing order, so skip the parentheses here. Ideally we'd
557558
// implement rustc's model. cc https://github.com/rust-lang/rust-analyzer/pull/10623
558559
if let TtElement::Subtree(subtree, subtree_iter) = &t
559-
&& let [tt::TokenTree::Leaf(tt)] = subtree_iter.remaining().flat_tokens()
560+
&& let Some([tt::TtElement::Leaf(tt)]) = subtree_iter.clone().collect_array()
560561
&& subtree.delimiter.kind == tt::DelimiterKind::Parenthesis
561562
{
562563
t = TtElement::Leaf(tt);
@@ -663,7 +664,7 @@ fn concat_bytes_expand(
663664
kind,
664665
suffix: _,
665666
})) => {
666-
record_span(*span);
667+
record_span(span);
667668
match kind {
668669
tt::LitKind::Byte => {
669670
if let Ok(b) = unescape_byte(text.as_str()) {
@@ -679,7 +680,7 @@ fn concat_bytes_expand(
679680
bytes.extend(text.as_str().escape_debug());
680681
}
681682
_ => {
682-
err.get_or_insert(ExpandError::other(*span, "unexpected token"));
683+
err.get_or_insert(ExpandError::other(span, "unexpected token"));
683684
break;
684685
}
685686
}
@@ -733,15 +734,15 @@ fn concat_bytes_expand_subtree(
733734
if let Ok(b) = unescape_byte(text.as_str()) {
734735
bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32)));
735736
}
736-
record_span(*span);
737+
record_span(span);
737738
}
738739
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
739740
symbol: text,
740741
span,
741742
kind: tt::LitKind::Integer,
742743
suffix: _,
743744
})) => {
744-
record_span(*span);
745+
record_span(span);
745746
if let Ok(b) = text.as_str().parse::<u8>() {
746747
bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32)));
747748
}
@@ -796,13 +797,13 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
796797
span,
797798
kind: tt::LitKind::Str,
798799
suffix: _,
799-
})) => Ok((unescape_symbol(text), *span)),
800+
})) => Ok((unescape_symbol(&text), span)),
800801
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
801802
symbol: text,
802803
span,
803804
kind: tt::LitKind::StrRaw(_),
804805
suffix: _,
805-
})) => Ok((text.clone(), *span)),
806+
})) => Ok((text.clone(), span)),
806807
TtElement::Leaf(l) => Err(*l.span()),
807808
TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
808809
}

crates/hir-expand/src/builtin/quote.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl ToTokenTree for crate::tt::SubtreeView<'_> {
163163

164164
impl ToTokenTree for crate::tt::TopSubtree {
165165
fn to_tokens(self, _: Span, builder: &mut TopSubtreeBuilder) {
166-
builder.extend_tt_dangerous(self.0);
166+
builder.extend_with_tt(self.as_token_trees());
167167
}
168168
}
169169

@@ -172,10 +172,9 @@ impl ToTokenTree for crate::tt::TtElement<'_> {
172172
match self {
173173
crate::tt::TtElement::Leaf(leaf) => builder.push(leaf.clone()),
174174
crate::tt::TtElement::Subtree(subtree, subtree_iter) => {
175-
builder.extend_tt_dangerous(
176-
std::iter::once(crate::tt::TokenTree::Subtree(subtree.clone()))
177-
.chain(subtree_iter.remaining().flat_tokens().iter().cloned()),
178-
);
175+
builder.open(subtree.delimiter.kind, subtree.delimiter.open);
176+
builder.extend_with_tt(subtree_iter.remaining());
177+
builder.close(subtree.delimiter.close);
179178
}
180179
}
181180
}

0 commit comments

Comments
 (0)