Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/expander.rs')
-rw-r--r--crates/mbe/src/expander.rs42
1 files changed, 30 insertions, 12 deletions
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs
index f910f9f9d7..25e05df7b7 100644
--- a/crates/mbe/src/expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -7,20 +7,29 @@ mod transcriber;
use intern::Symbol;
use rustc_hash::FxHashMap;
-use span::{Edition, Span};
+use span::Span;
-use crate::{ExpandError, ExpandErrorKind, ExpandResult, MatchedArmIndex, parser::MetaVarKind};
+use crate::{
+ ExpandError, ExpandErrorKind, ExpandResult, MacroCallStyle, MatchedArmIndex,
+ parser::MetaVarKind,
+};
pub(crate) fn expand_rules(
+ db: &dyn salsa::Database,
rules: &[crate::Rule],
- input: &tt::TopSubtree<Span>,
+ input: &tt::TopSubtree,
marker: impl Fn(&mut Span) + Copy,
+ call_style: MacroCallStyle,
call_site: Span,
- def_site_edition: Edition,
-) -> ExpandResult<(tt::TopSubtree<Span>, MatchedArmIndex)> {
+) -> ExpandResult<(tt::TopSubtree, MatchedArmIndex)> {
let mut match_: Option<(matcher::Match<'_>, &crate::Rule, usize)> = None;
for (idx, rule) in rules.iter().enumerate() {
- let new_match = matcher::match_(&rule.lhs, input, def_site_edition);
+ // Skip any rules that aren't relevant to the call style (fn-like/attr/derive).
+ if call_style != rule.style {
+ continue;
+ }
+
+ let new_match = matcher::match_(db, &rule.lhs, input);
if new_match.err.is_none() {
// If we find a rule that applies without errors, we're done.
@@ -119,7 +128,10 @@ enum Fragment<'a> {
#[default]
Empty,
/// token fragments are just copy-pasted into the output
- Tokens(tt::TokenTreesView<'a, Span>),
+ Tokens {
+ tree: tt::TokenTreesView<'a>,
+ origin: TokensOrigin,
+ },
/// Expr ast fragments are surrounded with `()` on transcription to preserve precedence.
/// Note that this impl is different from the one currently in `rustc` --
/// `rustc` doesn't translate fragments into token trees at all.
@@ -129,7 +141,7 @@ enum Fragment<'a> {
/// tricky to handle in the parser, and rustc doesn't handle those either.
///
/// The span of the outer delimiters is marked on transcription.
- Expr(tt::TokenTreesView<'a, Span>),
+ Expr(tt::TokenTreesView<'a>),
/// There are roughly two types of paths: paths in expression context, where a
/// separator `::` between an identifier and its following generic argument list
/// is mandatory, and paths in type context, where `::` can be omitted.
@@ -139,18 +151,24 @@ enum Fragment<'a> {
/// and is trasncribed as an expression-context path, verbatim transcription
/// would cause a syntax error. We need to fix it up just before transcribing;
/// see `transcriber::fix_up_and_push_path_tt()`.
- Path(tt::TokenTreesView<'a, Span>),
- TokensOwned(tt::TopSubtree<Span>),
+ Path(tt::TokenTreesView<'a>),
+ TokensOwned(tt::TopSubtree),
}
impl Fragment<'_> {
fn is_empty(&self) -> bool {
match self {
Fragment::Empty => true,
- Fragment::Tokens(it) => it.len() == 0,
+ Fragment::Tokens { tree, .. } => tree.len() == 0,
Fragment::Expr(it) => it.len() == 0,
Fragment::Path(it) => it.len() == 0,
- Fragment::TokensOwned(it) => it.0.is_empty(),
+ Fragment::TokensOwned(_) => false, // A `TopSubtree` is never empty
}
}
}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum TokensOrigin {
+ Raw,
+ Ast,
+}