Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/expander/matcher.rs')
-rw-r--r--crates/mbe/src/expander/matcher.rs117
1 files changed, 79 insertions, 38 deletions
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 3762d20bab..e69d7d14e2 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -70,7 +70,7 @@ use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
expect_fragment,
parser::{MetaVarKind, Op, RepeatKind, Separator},
- ExpandError, MetaTemplate, ValueResult,
+ ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
};
impl Bindings {
@@ -510,11 +510,17 @@ fn match_loop_inner<'t>(
if matches!(rhs, tt::Leaf::Literal(it) if it.symbol == lhs.symbol) {
item.dot.next();
} else {
- res.add_err(ExpandError::UnexpectedToken);
+ res.add_err(ExpandError::new(
+ *rhs.span(),
+ ExpandErrorKind::UnexpectedToken,
+ ));
item.is_error = true;
}
} else {
- res.add_err(ExpandError::binding_error(format!("expected literal: `{lhs}`")));
+ res.add_err(ExpandError::binding_error(
+ src.clone().next().map_or(delim_span.close, |it| it.first_span()),
+ format!("expected literal: `{lhs}`"),
+ ));
item.is_error = true;
}
try_push!(next_items, item);
@@ -524,11 +530,17 @@ fn match_loop_inner<'t>(
if matches!(rhs, tt::Leaf::Ident(it) if it.sym == lhs.sym) {
item.dot.next();
} else {
- res.add_err(ExpandError::UnexpectedToken);
+ res.add_err(ExpandError::new(
+ *rhs.span(),
+ ExpandErrorKind::UnexpectedToken,
+ ));
item.is_error = true;
}
} else {
- res.add_err(ExpandError::binding_error(format!("expected ident: `{lhs}`")));
+ res.add_err(ExpandError::binding_error(
+ src.clone().next().map_or(delim_span.close, |it| it.first_span()),
+ format!("expected ident: `{lhs}`"),
+ ));
item.is_error = true;
}
try_push!(next_items, item);
@@ -538,8 +550,8 @@ fn match_loop_inner<'t>(
let error = if let Ok(rhs) = fork.expect_glued_punct() {
let first_is_single_quote = rhs[0].char == '\'';
let lhs = lhs.iter().map(|it| it.char);
- let rhs = rhs.iter().map(|it| it.char);
- if lhs.clone().eq(rhs) {
+ let rhs_ = rhs.iter().map(|it| it.char);
+ if lhs.clone().eq(rhs_) {
// HACK: here we use `meta_result` to pass `TtIter` back to caller because
// it might have been advanced multiple times. `ValueResult` is
// insignificant.
@@ -552,13 +564,19 @@ fn match_loop_inner<'t>(
if first_is_single_quote {
// If the first punct token is a single quote, that's a part of a lifetime
// ident, not a punct.
- ExpandError::UnexpectedToken
+ ExpandError::new(
+ rhs.get(1).map_or(rhs[0].span, |it| it.span),
+ ExpandErrorKind::UnexpectedToken,
+ )
} else {
let lhs = lhs.collect::<String>();
- ExpandError::binding_error(format!("expected punct: `{lhs}`"))
+ ExpandError::binding_error(rhs[0].span, format!("expected punct: `{lhs}`"))
}
} else {
- ExpandError::UnexpectedToken
+ ExpandError::new(
+ src.clone().next().map_or(delim_span.close, |it| it.first_span()),
+ ExpandErrorKind::UnexpectedToken,
+ )
};
res.add_err(error);
@@ -651,7 +669,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition)
if let Some(item) = error_recover_item {
res.bindings = bindings_builder.build(&item);
}
- res.add_err(ExpandError::UnexpectedToken);
+ res.add_err(ExpandError::new(span.open, ExpandErrorKind::UnexpectedToken));
}
return res;
}
@@ -670,7 +688,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition)
src = it;
res.unmatched_tts += src.len();
}
- res.add_err(ExpandError::LeftoverTokens);
+ res.add_err(ExpandError::new(span.open, ExpandErrorKind::LeftoverTokens));
if let Some(error_recover_item) = error_recover_item {
res.bindings = bindings_builder.build(&error_recover_item);
@@ -746,9 +764,10 @@ fn match_meta_var(
) -> ExpandResult<Option<Fragment>> {
let fragment = match kind {
MetaVarKind::Path => {
- return expect_fragment(input, parser::PrefixEntryPoint::Path, edition).map(|it| {
- it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
- });
+ return expect_fragment(input, parser::PrefixEntryPoint::Path, edition, delim_span)
+ .map(|it| {
+ it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
+ });
}
MetaVarKind::Expr => {
// `expr` should not match underscores, let expressions, or inline const. The latter
@@ -763,37 +782,54 @@ fn match_meta_var(
|| it.sym == sym::let_
|| it.sym == sym::const_ =>
{
- return ExpandResult::only_err(ExpandError::NoMatchingRule)
+ return ExpandResult::only_err(ExpandError::new(
+ it.span,
+ ExpandErrorKind::NoMatchingRule,
+ ))
}
_ => {}
};
- return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition).map(|tt| {
- tt.map(|tt| match tt {
- tt::TokenTree::Leaf(leaf) => tt::Subtree {
- delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
- token_trees: Box::new([leaf.into()]),
- },
- tt::TokenTree::Subtree(mut s) => {
- if s.delimiter.kind == tt::DelimiterKind::Invisible {
- s.delimiter.kind = tt::DelimiterKind::Parenthesis;
+ return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition, delim_span)
+ .map(|tt| {
+ tt.map(|tt| match tt {
+ tt::TokenTree::Leaf(leaf) => tt::Subtree {
+ delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
+ token_trees: Box::new([leaf.into()]),
+ },
+ tt::TokenTree::Subtree(mut s) => {
+ if s.delimiter.kind == tt::DelimiterKind::Invisible {
+ s.delimiter.kind = tt::DelimiterKind::Parenthesis;
+ }
+ s
}
- s
- }
- })
- .map(Fragment::Expr)
- });
+ })
+ .map(Fragment::Expr)
+ });
}
MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
+ let span = input.next_span();
let tt_result = match kind {
MetaVarKind::Ident => input
.expect_ident()
.map(|ident| tt::Leaf::from(ident.clone()).into())
- .map_err(|()| ExpandError::binding_error("expected ident")),
- MetaVarKind::Tt => {
- expect_tt(input).map_err(|()| ExpandError::binding_error("expected token tree"))
- }
- MetaVarKind::Lifetime => expect_lifetime(input)
- .map_err(|()| ExpandError::binding_error("expected lifetime")),
+ .map_err(|()| {
+ ExpandError::binding_error(
+ span.unwrap_or(delim_span.close),
+ "expected ident",
+ )
+ }),
+ MetaVarKind::Tt => expect_tt(input).map_err(|()| {
+ ExpandError::binding_error(
+ span.unwrap_or(delim_span.close),
+ "expected token tree",
+ )
+ }),
+ MetaVarKind::Lifetime => expect_lifetime(input).map_err(|()| {
+ ExpandError::binding_error(
+ span.unwrap_or(delim_span.close),
+ "expected lifetime",
+ )
+ }),
MetaVarKind::Literal => {
let neg = eat_char(input, '-');
input
@@ -808,7 +844,12 @@ fn match_meta_var(
}),
}
})
- .map_err(|()| ExpandError::binding_error("expected literal"))
+ .map_err(|()| {
+ ExpandError::binding_error(
+ span.unwrap_or(delim_span.close),
+ "expected literal",
+ )
+ })
}
_ => unreachable!(),
};
@@ -823,7 +864,7 @@ fn match_meta_var(
MetaVarKind::Item => parser::PrefixEntryPoint::Item,
MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
};
- expect_fragment(input, fragment, edition).map(|it| it.map(Fragment::Tokens))
+ expect_fragment(input, fragment, edition, delim_span).map(|it| it.map(Fragment::Tokens))
}
fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {