Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/builtin/fn_macro.rs')
-rw-r--r--crates/hir-expand/src/builtin/fn_macro.rs349
1 files changed, 174 insertions, 175 deletions
diff --git a/crates/hir-expand/src/builtin/fn_macro.rs b/crates/hir-expand/src/builtin/fn_macro.rs
index b76db2e005..5b06de9875 100644
--- a/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/crates/hir-expand/src/builtin/fn_macro.rs
@@ -14,12 +14,12 @@ use syntax::{
use syntax_bridge::syntax_node_to_token_tree;
use crate::{
- builtin::quote::{dollar_crate, quote},
+ builtin::quote::{dollar_crate, quote, WithDelimiter},
db::ExpandDatabase,
hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
name,
span_map::SpanMap,
- tt::{self, DelimSpan},
+ tt::{self, DelimSpan, TtElement, TtIter},
ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId,
};
@@ -36,7 +36,7 @@ macro_rules! register_builtin {
}
impl BuiltinFnLikeExpander {
- fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree> {
+ fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::TopSubtree, Span) -> ExpandResult<tt::TopSubtree> {
match *self {
$( BuiltinFnLikeExpander::$kind => $expand, )*
}
@@ -44,7 +44,7 @@ macro_rules! register_builtin {
}
impl EagerExpander {
- fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree> {
+ fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::TopSubtree, Span) -> ExpandResult<tt::TopSubtree> {
match *self {
$( EagerExpander::$e_kind => $e_expand, )*
}
@@ -66,9 +66,9 @@ impl BuiltinFnLikeExpander {
&self,
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
- ) -> ExpandResult<tt::Subtree> {
+ ) -> ExpandResult<tt::TopSubtree> {
let span = span_with_def_site_ctxt(db, span, id);
self.expander()(db, id, tt, span)
}
@@ -83,9 +83,9 @@ impl EagerExpander {
&self,
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
- ) -> ExpandResult<tt::Subtree> {
+ ) -> ExpandResult<tt::TopSubtree> {
let span = span_with_def_site_ctxt(db, span, id);
self.expander()(db, id, tt, span)
}
@@ -146,24 +146,16 @@ register_builtin! {
(option_env, OptionEnv) => option_env_expand
}
-fn mk_pound(span: Span) -> tt::Subtree {
- crate::builtin::quote::IntoTt::to_subtree(
- vec![crate::tt::Leaf::Punct(crate::tt::Punct {
- char: '#',
- spacing: crate::tt::Spacing::Alone,
- span,
- })
- .into()],
- span,
- )
+fn mk_pound(span: Span) -> tt::Leaf {
+ crate::tt::Leaf::Punct(crate::tt::Punct { char: '#', spacing: crate::tt::Spacing::Alone, span })
}
fn module_path_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
// Just return a dummy result.
ExpandResult::ok(quote! {span =>
"module::path"
@@ -173,48 +165,48 @@ fn module_path_expand(
fn line_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
// dummy implementation for type-checking purposes
// Note that `line!` and `column!` will never be implemented properly, as they are by definition
// not incremental
- ExpandResult::ok(tt::Subtree {
- delimiter: tt::Delimiter::invisible_spanned(span),
- token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ ExpandResult::ok(tt::TopSubtree::invisible_from_leaves(
+ span,
+ [tt::Leaf::Literal(tt::Literal {
symbol: sym::INTEGER_0.clone(),
span,
kind: tt::LitKind::Integer,
suffix: Some(sym::u32.clone()),
- }))]),
- })
+ })],
+ ))
}
fn log_syntax_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
ExpandResult::ok(quote! {span =>})
}
fn trace_macros_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
ExpandResult::ok(quote! {span =>})
}
fn stringify_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
- let pretty = ::tt::pretty(&tt.token_trees);
+) -> ExpandResult<tt::TopSubtree> {
+ let pretty = ::tt::pretty(tt.token_trees().flat_tokens());
let expanded = quote! {span =>
#pretty
@@ -226,39 +218,35 @@ fn stringify_expand(
fn assert_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let call_site_span = span_with_call_site_ctxt(db, span, id);
- let mut iter = ::tt::iter::TtIter::new(tt);
+ let mut iter = tt.iter();
let cond = expect_fragment(
&mut iter,
parser::PrefixEntryPoint::Expr,
db.crate_graph()[id.lookup(db).krate].edition,
- tt::DelimSpan { open: tt.delimiter.open, close: tt.delimiter.close },
+ tt.top_subtree().delimiter.delim_span(),
);
_ = iter.expect_char(',');
- let rest = iter.as_slice();
+ let rest = iter.remaining();
let dollar_crate = dollar_crate(span);
- let expanded = match cond.value {
- Some(cond) => {
- let panic_args = rest.iter().cloned();
- let mac = if use_panic_2021(db, span) {
- quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) }
- } else {
- quote! {call_site_span => #dollar_crate::panic!(##panic_args) }
- };
- quote! {call_site_span =>{
- if !(#cond) {
- #mac;
- }
- }}
- }
- None => quote! {call_site_span =>{}},
+ let panic_args = rest.iter();
+ let mac = if use_panic_2021(db, span) {
+ quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) }
+ } else {
+ quote! {call_site_span => #dollar_crate::panic!(##panic_args) }
};
+ let value = cond.value;
+ let expanded = quote! {call_site_span =>{
+ if !(#value) {
+ #mac;
+ }
+ }};
match cond.err {
Some(err) => ExpandResult::new(expanded, err.into()),
@@ -269,9 +257,9 @@ fn assert_expand(
fn file_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
// FIXME: RA purposefully lacks knowledge of absolute file names
// so just return "".
let file_name = "file";
@@ -286,12 +274,12 @@ fn file_expand(
fn format_args_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let pound = mk_pound(span);
let mut tt = tt.clone();
- tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+ tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
ExpandResult::ok(quote! {span =>
builtin #pound format_args #tt
})
@@ -300,17 +288,17 @@ fn format_args_expand(
fn format_args_nl_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let pound = mk_pound(span);
let mut tt = tt.clone();
- tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+ tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
kind: tt::LitKind::Str,
..
- }))) = tt.token_trees.first_mut()
+ }))) = tt.0.get_mut(1)
{
*text = Symbol::intern(&format_smolstr!("{}\\n", text.as_str()));
}
@@ -322,11 +310,11 @@ fn format_args_nl_expand(
fn asm_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let mut tt = tt.clone();
- tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+ tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
let pound = mk_pound(span);
let expanded = quote! {span =>
builtin #pound asm #tt
@@ -337,9 +325,9 @@ fn asm_expand(
fn cfg_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let loc = db.lookup_intern_macro_call(id);
let expr = CfgExpr::parse(tt);
let enabled = db.crate_graph()[loc.krate].cfg_options.check(&expr) != Some(false);
@@ -350,9 +338,9 @@ fn cfg_expand(
fn panic_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let dollar_crate = dollar_crate(span);
let call_site_span = span_with_call_site_ctxt(db, span, id);
@@ -362,19 +350,18 @@ fn panic_expand(
sym::panic_2015.clone()
};
- // Expand to a macro call `$crate::panic::panic_{edition}`
- let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
-
// Pass the original arguments
- let mut subtree = tt.clone();
- subtree.delimiter = tt::Delimiter {
- open: call_site_span,
- close: call_site_span,
- kind: tt::DelimiterKind::Parenthesis,
+ let subtree = WithDelimiter {
+ delimiter: tt::Delimiter {
+ open: call_site_span,
+ close: call_site_span,
+ kind: tt::DelimiterKind::Parenthesis,
+ },
+ token_trees: tt.token_trees(),
};
- // FIXME(slow): quote! have a way to expand to builder to make this a vec!
- call.push(tt::TokenTree::Subtree(subtree));
+ // Expand to a macro call `$crate::panic::panic_{edition}`
+ let call = quote!(call_site_span =>#dollar_crate::panic::#mac! #subtree);
ExpandResult::ok(call)
}
@@ -382,9 +369,9 @@ fn panic_expand(
fn unreachable_expand(
db: &dyn ExpandDatabase,
id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let dollar_crate = dollar_crate(span);
let call_site_span = span_with_call_site_ctxt(db, span, id);
@@ -394,19 +381,16 @@ fn unreachable_expand(
sym::unreachable_2015.clone()
};
- // Expand to a macro call `$crate::panic::panic_{edition}`
- let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
-
// Pass the original arguments
let mut subtree = tt.clone();
- subtree.delimiter = tt::Delimiter {
+ *subtree.top_subtree_delimiter_mut() = tt::Delimiter {
open: call_site_span,
close: call_site_span,
kind: tt::DelimiterKind::Parenthesis,
};
- // FIXME(slow): quote! have a way to expand to builder to make this a vec!
- call.push(tt::TokenTree::Subtree(subtree));
+ // Expand to a macro call `$crate::panic::panic_{edition}`
+ let call = quote!(call_site_span =>#dollar_crate::panic::#mac! #subtree);
ExpandResult::ok(call)
}
@@ -436,11 +420,11 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
fn compile_error_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
- let err = match &*tt.token_trees {
- [tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+) -> ExpandResult<tt::TopSubtree> {
+ let err = match &*tt.0 {
+ [_, tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span: _,
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
@@ -455,9 +439,9 @@ fn compile_error_expand(
fn concat_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
call_site: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let mut err = None;
let mut text = String::new();
let mut span: Option<Span> = None;
@@ -466,19 +450,19 @@ fn concat_expand(
Some(_) => (),
None => span = Some(s),
};
- for (i, mut t) in tt.token_trees.iter().enumerate() {
+ for (i, mut t) in tt.iter().enumerate() {
// FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
// to ensure the right parsing order, so skip the parentheses here. Ideally we'd
// implement rustc's model. cc https://github.com/rust-lang/rust-analyzer/pull/10623
- if let tt::TokenTree::Subtree(tt::Subtree { delimiter: delim, token_trees }) = t {
- if let [tt] = &**token_trees {
- if delim.kind == tt::DelimiterKind::Parenthesis {
- t = tt;
+ if let TtElement::Subtree(subtree, subtree_iter) = &t {
+ if let [tt::TokenTree::Leaf(tt)] = subtree_iter.remaining().flat_tokens() {
+ if subtree.delimiter.kind == tt::DelimiterKind::Parenthesis {
+ t = TtElement::Leaf(tt);
}
}
}
match t {
- tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
+ TtElement::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
// concat works with string and char literals, so remove any quotes.
// It also works with integer, float and boolean literals, so just use the rest
// as-is.
@@ -511,28 +495,28 @@ fn concat_expand(
}
}
// handle boolean literals
- tt::TokenTree::Leaf(tt::Leaf::Ident(id))
+ TtElement::Leaf(tt::Leaf::Ident(id))
if i % 2 == 0 && (id.sym == sym::true_ || id.sym == sym::false_) =>
{
text.push_str(id.sym.as_str());
record_span(id.span);
}
- tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+ TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
_ => {
err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
}
}
}
- let span = span.unwrap_or(tt.delimiter.open);
+ let span = span.unwrap_or_else(|| tt.top_subtree().delimiter.open);
ExpandResult { value: quote!(span =>#text), err }
}
fn concat_bytes_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
call_site: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let mut bytes = String::new();
let mut err = None;
let mut span: Option<Span> = None;
@@ -541,9 +525,9 @@ fn concat_bytes_expand(
Some(_) => (),
None => span = Some(s),
};
- for (i, t) in tt.token_trees.iter().enumerate() {
+ for (i, t) in tt.iter().enumerate() {
match t {
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind,
@@ -570,10 +554,12 @@ fn concat_bytes_expand(
}
}
}
- tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
- tt::TokenTree::Subtree(tree) if tree.delimiter.kind == tt::DelimiterKind::Bracket => {
+ TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+ TtElement::Subtree(tree, tree_iter)
+ if tree.delimiter.kind == tt::DelimiterKind::Bracket =>
+ {
if let Err(e) =
- concat_bytes_expand_subtree(tree, &mut bytes, &mut record_span, call_site)
+ concat_bytes_expand_subtree(tree_iter, &mut bytes, &mut record_span, call_site)
{
err.get_or_insert(e);
break;
@@ -585,31 +571,30 @@ fn concat_bytes_expand(
}
}
}
- let span = span.unwrap_or(tt.delimiter.open);
+ let span = span.unwrap_or(tt.top_subtree().delimiter.open);
ExpandResult {
- value: tt::Subtree {
- delimiter: tt::Delimiter::invisible_spanned(span),
- token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ value: tt::TopSubtree::invisible_from_leaves(
+ span,
+ [tt::Leaf::Literal(tt::Literal {
symbol: Symbol::intern(&bytes),
span,
kind: tt::LitKind::ByteStr,
suffix: None,
- }))]
- .into(),
- },
+ })],
+ ),
err,
}
}
fn concat_bytes_expand_subtree(
- tree: &tt::Subtree,
+ tree_iter: TtIter<'_>,
bytes: &mut String,
mut record_span: impl FnMut(Span),
err_span: Span,
) -> Result<(), ExpandError> {
- for (ti, tt) in tree.token_trees.iter().enumerate() {
+ for (ti, tt) in tree_iter.enumerate() {
match tt {
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind: tt::LitKind::Byte,
@@ -620,7 +605,7 @@ fn concat_bytes_expand_subtree(
}
record_span(*span);
}
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind: tt::LitKind::Integer,
@@ -631,7 +616,7 @@ fn concat_bytes_expand_subtree(
bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32)));
}
}
- tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
+ TtElement::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
_ => {
return Err(ExpandError::other(err_span, "unexpected token"));
}
@@ -643,17 +628,17 @@ fn concat_bytes_expand_subtree(
fn concat_idents_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let mut err = None;
let mut ident = String::new();
- for (i, t) in tt.token_trees.iter().enumerate() {
+ for (i, t) in tt.iter().enumerate() {
match t {
- tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => {
+ TtElement::Leaf(tt::Leaf::Ident(id)) => {
ident.push_str(id.sym.as_str());
}
- tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+ TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
_ => {
err.get_or_insert(ExpandError::other(span, "unexpected token"));
}
@@ -685,18 +670,19 @@ fn relative_file(
}
}
-fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
- tt.token_trees
- .first()
- .ok_or(tt.delimiter.open.cover(tt.delimiter.close))
+fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
+ let delimiter = tt.top_subtree().delimiter;
+ tt.iter()
+ .next()
+ .ok_or(delimiter.open.cover(delimiter.close))
.and_then(|tt| match tt {
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind: tt::LitKind::Str,
suffix: _,
})) => Ok((unescape_str(text), *span)),
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind: tt::LitKind::StrRaw(_),
@@ -705,26 +691,30 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
// FIXME: We wrap expression fragments in parentheses which can break this expectation
// here
// Remove this once we handle none delims correctly
- tt::TokenTree::Subtree(tt) if tt.delimiter.kind == DelimiterKind::Parenthesis => {
- tt.token_trees.first().and_then(|tt| match tt {
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
- symbol: text,
- span,
- kind: tt::LitKind::Str,
- suffix: _,
- })) => Some((unescape_str(text), *span)),
- tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
- symbol: text,
- span,
- kind: tt::LitKind::StrRaw(_),
- suffix: _,
- })) => Some((text.clone(), *span)),
- _ => None,
- })
+ TtElement::Subtree(tt, mut tt_iter)
+ if tt.delimiter.kind == DelimiterKind::Parenthesis =>
+ {
+ tt_iter
+ .next()
+ .and_then(|tt| match tt {
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
+ symbol: text,
+ span,
+ kind: tt::LitKind::Str,
+ suffix: _,
+ })) => Some((unescape_str(text), *span)),
+ TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
+ symbol: text,
+ span,
+ kind: tt::LitKind::StrRaw(_),
+ suffix: _,
+ })) => Some((text.clone(), *span)),
+ _ => None,
+ })
+ .ok_or(delimiter.open.cover(delimiter.close))
}
- .ok_or(tt.delimiter.open.cover(tt.delimiter.close)),
- ::tt::TokenTree::Leaf(l) => Err(*l.span()),
- ::tt::TokenTree::Subtree(tt) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
+ TtElement::Leaf(l) => Err(*l.span()),
+ TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
})
.map_err(|span| ExpandError::other(span, "expected string literal"))
}
@@ -732,13 +722,16 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
fn include_expand(
db: &dyn ExpandDatabase,
arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let file_id = match include_input_to_file_id(db, arg_id, tt) {
Ok(it) => it,
Err(e) => {
- return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
+ return ExpandResult::new(
+ tt::TopSubtree::empty(DelimSpan { open: span, close: span }),
+ e,
+ )
}
};
let span_map = db.real_span_map(file_id);
@@ -754,7 +747,7 @@ fn include_expand(
pub fn include_input_to_file_id(
db: &dyn ExpandDatabase,
arg_id: MacroCallId,
- arg: &tt::Subtree,
+ arg: &tt::TopSubtree,
) -> Result<EditionedFileId, ExpandError> {
let (s, span) = parse_string(arg)?;
relative_file(db, arg_id, s.as_str(), false, span)
@@ -763,32 +756,35 @@ pub fn include_input_to_file_id(
fn include_bytes_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
// 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: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+ let res = tt::TopSubtree::invisible_from_leaves(
+ span,
+ [tt::Leaf::Literal(tt::Literal {
symbol: Symbol::empty(),
span,
kind: tt::LitKind::ByteStrRaw(1),
suffix: None,
- }))]),
- };
+ })],
+ );
ExpandResult::ok(res)
}
fn include_str_expand(
db: &dyn ExpandDatabase,
arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let (path, span) = match parse_string(tt) {
Ok(it) => it,
Err(e) => {
- return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
+ return ExpandResult::new(
+ tt::TopSubtree::empty(DelimSpan { open: span, close: span }),
+ e,
+ )
}
};
@@ -817,13 +813,16 @@ fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) ->
fn env_expand(
db: &dyn ExpandDatabase,
arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let (key, span) = match parse_string(tt) {
Ok(it) => it,
Err(e) => {
- return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
+ return ExpandResult::new(
+ tt::TopSubtree::empty(DelimSpan { open: span, close: span }),
+ e,
+ )
}
};
@@ -852,14 +851,14 @@ fn env_expand(
fn option_env_expand(
db: &dyn ExpandDatabase,
arg_id: MacroCallId,
- tt: &tt::Subtree,
+ tt: &tt::TopSubtree,
call_site: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
let (key, span) = match parse_string(tt) {
Ok(it) => it,
Err(e) => {
return ExpandResult::new(
- tt::Subtree::empty(DelimSpan { open: call_site, close: call_site }),
+ tt::TopSubtree::empty(DelimSpan { open: call_site, close: call_site }),
e,
)
}
@@ -879,11 +878,11 @@ fn option_env_expand(
fn quote_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
- _tt: &tt::Subtree,
+ _tt: &tt::TopSubtree,
span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
ExpandResult::new(
- tt::Subtree::empty(tt::DelimSpan { open: span, close: span }),
+ tt::TopSubtree::empty(tt::DelimSpan { open: span, close: span }),
ExpandError::other(span, "quote! is not implemented"),
)
}