Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/expander/transcriber.rs')
-rw-r--r--crates/mbe/src/expander/transcriber.rs39
1 files changed, 24 insertions, 15 deletions
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs
index 7710ea7938..ec277ba72e 100644
--- a/crates/mbe/src/expander/transcriber.rs
+++ b/crates/mbe/src/expander/transcriber.rs
@@ -1,14 +1,14 @@
//! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
-use intern::{sym, Symbol};
+use intern::{Symbol, sym};
use span::{Edition, Span};
-use tt::{iter::TtElement, Delimiter, TopSubtreeBuilder};
+use tt::{Delimiter, TopSubtreeBuilder, iter::TtElement};
use crate::{
+ ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate,
expander::{Binding, Bindings, Fragment},
parser::{ConcatMetaVarExprElem, MetaVarKind, Op, RepeatKind, Separator},
- ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate,
};
impl<'t> Bindings<'t> {
@@ -80,7 +80,7 @@ impl<'t> Bindings<'t> {
| MetaVarKind::Expr(_)
| MetaVarKind::Ident => {
builder.push(tt::Leaf::Ident(tt::Ident {
- sym: sym::missing.clone(),
+ sym: sym::missing,
span,
is_raw: tt::IdentIsRaw::No,
}));
@@ -93,7 +93,7 @@ impl<'t> Bindings<'t> {
spacing: tt::Spacing::Joint,
}),
tt::Leaf::Ident(tt::Ident {
- sym: sym::missing.clone(),
+ sym: sym::missing,
span,
is_raw: tt::IdentIsRaw::No,
}),
@@ -101,7 +101,7 @@ impl<'t> Bindings<'t> {
}
MetaVarKind::Literal => {
builder.push(tt::Leaf::Ident(tt::Ident {
- sym: sym::missing.clone(),
+ sym: sym::missing,
span,
is_raw: tt::IdentIsRaw::No,
}));
@@ -210,8 +210,11 @@ fn expand_subtree(
}
Op::Ignore { name, id } => {
// Expand the variable, but ignore the result. This registers the repetition count.
- // FIXME: Any emitted errors are dropped.
- let _ = ctx.bindings.get_fragment(name, *id, &mut ctx.nesting, marker);
+ let e = ctx.bindings.get_fragment(name, *id, &mut ctx.nesting, marker).err();
+ // FIXME: The error gets dropped if there were any previous errors.
+ // This should be reworked in a way where the errors can be combined
+ // and reported rather than storing the first error encountered.
+ err = err.or(e);
}
Op::Index { depth } => {
let index =
@@ -239,9 +242,7 @@ fn expand_subtree(
let mut binding = match ctx.bindings.get(name, ctx.call_site) {
Ok(b) => b,
Err(e) => {
- if err.is_none() {
- err = Some(e);
- }
+ err = err.or(Some(e));
continue;
}
};
@@ -331,7 +332,10 @@ fn expand_subtree(
}
_ => {
if err.is_none() {
- err = Some(ExpandError::binding_error(var.span, "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`"))
+ err = Some(ExpandError::binding_error(
+ var.span,
+ "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`",
+ ))
}
continue;
}
@@ -386,8 +390,13 @@ fn expand_var(
match ctx.bindings.get_fragment(v, id, &mut ctx.nesting, marker) {
Ok(fragment) => {
match fragment {
- Fragment::Tokens(tt) => builder.extend_with_tt(tt.strip_invisible()),
- Fragment::TokensOwned(tt) => builder.extend_with_tt(tt.view().strip_invisible()),
+ // rustc spacing is not like ours. Ours is like proc macros', it dictates how puncts will actually be joined.
+ // rustc uses them mostly for pretty printing. So we have to deviate a bit from what rustc does here.
+ // Basically, a metavariable can never be joined with whatever after it.
+ Fragment::Tokens(tt) => builder.extend_with_tt_alone(tt.strip_invisible()),
+ Fragment::TokensOwned(tt) => {
+ builder.extend_with_tt_alone(tt.view().strip_invisible())
+ }
Fragment::Expr(sub) => {
let sub = sub.strip_invisible();
let mut span = id;
@@ -399,7 +408,7 @@ fn expand_var(
if wrap_in_parens {
builder.open(tt::DelimiterKind::Parenthesis, span);
}
- builder.extend_with_tt(sub);
+ builder.extend_with_tt_alone(sub);
if wrap_in_parens {
builder.close(span);
}