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.rs | 117 |
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) { |