summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/mbe
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:13:23 +0000
commit20431706a863f92cb37dc512fef6e48d192aaf2c (patch)
tree2867f13f5fd5437ba628c67d7f87309ccadcd286 /src/tools/rust-analyzer/crates/mbe
parentReleasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff)
downloadrustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz
rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/mbe')
-rw-r--r--src/tools/rust-analyzer/crates/mbe/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs30
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander.rs3
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs91
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs57
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs41
7 files changed, 161 insertions, 69 deletions
diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
index 5ff3448a1..13cd89010 100644
--- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
rustc-hash = "1.1.0"
-smallvec = "1.9.0"
+smallvec = "1.10.0"
tracing = "0.1.35"
syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index ac691578d..9c92bae6a 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -8,7 +8,7 @@ use syntax::{
use test_utils::{bench, bench_fixture, skip_slow_tests};
use crate::{
- parser::{Op, RepeatKind, Separator},
+ parser::{MetaVarKind, Op, RepeatKind, Separator},
syntax_node_to_token_tree, DeclarativeMacro,
};
@@ -111,35 +111,35 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
fn collect_from_op(op: &Op, parent: &mut tt::Subtree, seed: &mut usize) {
return match op {
- Op::Var { kind, .. } => match kind.as_ref().map(|it| it.as_str()) {
- Some("ident") => parent.token_trees.push(make_ident("foo")),
- Some("ty") => parent.token_trees.push(make_ident("Foo")),
- Some("tt") => parent.token_trees.push(make_ident("foo")),
- Some("vis") => parent.token_trees.push(make_ident("pub")),
- Some("pat") => parent.token_trees.push(make_ident("foo")),
- Some("path") => parent.token_trees.push(make_ident("foo")),
- Some("literal") => parent.token_trees.push(make_literal("1")),
- Some("expr") => parent.token_trees.push(make_ident("foo")),
- Some("lifetime") => {
+ Op::Var { kind, .. } => match kind.as_ref() {
+ Some(MetaVarKind::Ident) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Ty) => parent.token_trees.push(make_ident("Foo")),
+ Some(MetaVarKind::Tt) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Vis) => parent.token_trees.push(make_ident("pub")),
+ Some(MetaVarKind::Pat) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Path) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Literal) => parent.token_trees.push(make_literal("1")),
+ Some(MetaVarKind::Expr) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Lifetime) => {
parent.token_trees.push(make_punct('\''));
parent.token_trees.push(make_ident("a"));
}
- Some("block") => {
+ Some(MetaVarKind::Block) => {
parent.token_trees.push(make_subtree(tt::DelimiterKind::Brace, None))
}
- Some("item") => {
+ Some(MetaVarKind::Item) => {
parent.token_trees.push(make_ident("fn"));
parent.token_trees.push(make_ident("foo"));
parent.token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
parent.token_trees.push(make_subtree(tt::DelimiterKind::Brace, None));
}
- Some("meta") => {
+ Some(MetaVarKind::Meta) => {
parent.token_trees.push(make_ident("foo"));
parent.token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
}
None => (),
- Some(kind) => panic!("Unhandled kind {}", kind),
+ Some(kind) => panic!("Unhandled kind {:?}", kind),
},
Op::Leaf(leaf) => parent.token_trees.push(leaf.clone().into()),
Op::Repeat { tokens, kind, separator } => {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
index 1e1bfa550..100ec6bfb 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
@@ -8,7 +8,7 @@ mod transcriber;
use rustc_hash::FxHashMap;
use syntax::SmolStr;
-use crate::{ExpandError, ExpandResult};
+use crate::{parser::MetaVarKind, ExpandError, ExpandResult};
pub(crate) fn expand_rules(
rules: &[crate::Rule],
@@ -104,6 +104,7 @@ enum Binding {
Fragment(Fragment),
Nested(Vec<Binding>),
Empty,
+ Missing(MetaVarKind),
}
#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
index c1aa14d6b..3f656df25 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -66,7 +66,7 @@ use syntax::SmolStr;
use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
- parser::{Op, RepeatKind, Separator},
+ parser::{MetaVarKind, Op, RepeatKind, Separator},
tt_iter::TtIter,
ExpandError, MetaTemplate,
};
@@ -119,6 +119,7 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
.map(|it| match it {
Binding::Fragment(_) => 1,
Binding::Empty => 1,
+ Binding::Missing(_) => 1,
Binding::Nested(it) => count(it.iter()),
})
.sum()
@@ -130,6 +131,7 @@ enum BindingKind {
Empty(SmolStr),
Optional(SmolStr),
Fragment(SmolStr, Fragment),
+ Missing(SmolStr, MetaVarKind),
Nested(usize, usize),
}
@@ -190,6 +192,10 @@ impl BindingsBuilder {
.push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
}
+ fn push_missing(&mut self, idx: &mut BindingsIdx, var: &SmolStr, kind: MetaVarKind) {
+ self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Missing(var.clone(), kind))));
+ }
+
fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) {
let BindingsIdx(idx, nidx) = self.copy(child);
self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx))));
@@ -203,17 +209,16 @@ impl BindingsBuilder {
}
fn build(self, idx: &BindingsIdx) -> Bindings {
- let mut bindings = Bindings::default();
- self.build_inner(&mut bindings, &self.nodes[idx.0]);
- bindings
+ self.build_inner(&self.nodes[idx.0])
}
- fn build_inner(&self, bindings: &mut Bindings, link_nodes: &[LinkNode<Rc<BindingKind>>]) {
+ fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind>>]) -> Bindings {
+ let mut bindings = Bindings::default();
let mut nodes = Vec::new();
self.collect_nodes(link_nodes, &mut nodes);
for cmd in nodes {
- match &**cmd {
+ match cmd {
BindingKind::Empty(name) => {
bindings.push_empty(name);
}
@@ -223,6 +228,9 @@ impl BindingsBuilder {
BindingKind::Fragment(name, fragment) => {
bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone()));
}
+ BindingKind::Missing(name, kind) => {
+ bindings.inner.insert(name.clone(), Binding::Missing(*kind));
+ }
BindingKind::Nested(idx, nested_idx) => {
let mut nested_nodes = Vec::new();
self.collect_nested(*idx, *nested_idx, &mut nested_nodes);
@@ -246,13 +254,15 @@ impl BindingsBuilder {
}
}
}
+
+ bindings
}
fn collect_nested_ref<'a>(
&'a self,
id: usize,
len: usize,
- nested_refs: &mut Vec<&'a Vec<LinkNode<Rc<BindingKind>>>>,
+ nested_refs: &mut Vec<&'a [LinkNode<Rc<BindingKind>>]>,
) {
self.nested[id].iter().take(len).for_each(|it| match it {
LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
@@ -262,26 +272,16 @@ impl BindingsBuilder {
fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) {
let last = &self.nodes[idx];
- let mut nested_refs = Vec::new();
+ let mut nested_refs: Vec<&[_]> = Vec::new();
self.nested[nested_idx].iter().for_each(|it| match *it {
LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]),
LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs),
});
nested_refs.push(last);
-
- nested_refs.into_iter().for_each(|iter| {
- let mut child_bindings = Bindings::default();
- self.build_inner(&mut child_bindings, iter);
- nested.push(child_bindings)
- })
+ nested.extend(nested_refs.into_iter().map(|iter| self.build_inner(iter)));
}
- fn collect_nodes_ref<'a>(
- &'a self,
- id: usize,
- len: usize,
- nodes: &mut Vec<&'a Rc<BindingKind>>,
- ) {
+ fn collect_nodes_ref<'a>(&'a self, id: usize, len: usize, nodes: &mut Vec<&'a BindingKind>) {
self.nodes[id].iter().take(len).for_each(|it| match it {
LinkNode::Node(it) => nodes.push(it),
LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
@@ -291,7 +291,7 @@ impl BindingsBuilder {
fn collect_nodes<'a>(
&'a self,
link_nodes: &'a [LinkNode<Rc<BindingKind>>],
- nodes: &mut Vec<&'a Rc<BindingKind>>,
+ nodes: &mut Vec<&'a BindingKind>,
) {
link_nodes.iter().for_each(|it| match it {
LinkNode::Node(it) => nodes.push(it),
@@ -386,10 +386,10 @@ fn match_loop_inner<'t>(
let op = match item.dot.peek() {
None => {
// We are at or past the end of the matcher of `item`.
- if item.up.is_some() {
+ if let Some(up) = &item.up {
if item.sep_parsed.is_none() {
// Get the `up` matcher
- let mut new_pos = *item.up.clone().unwrap();
+ let mut new_pos = (**up).clone();
new_pos.bindings = bindings_builder.copy(&new_pos.bindings);
// Add matches from this repetition to the `matches` of `up`
bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings);
@@ -402,7 +402,7 @@ fn match_loop_inner<'t>(
// Check if we need a separator.
// We check the separator one by one
- let sep_idx = *item.sep_parsed.as_ref().unwrap_or(&0);
+ let sep_idx = item.sep_parsed.unwrap_or(0);
let sep_len = item.sep.as_ref().map_or(0, Separator::tt_count);
if item.sep.is_some() && sep_idx != sep_len {
let sep = item.sep.as_ref().unwrap();
@@ -467,9 +467,9 @@ fn match_loop_inner<'t>(
}
}
OpDelimited::Op(Op::Var { kind, name, .. }) => {
- if let Some(kind) = kind {
+ if let &Some(kind) = kind {
let mut fork = src.clone();
- let match_res = match_meta_var(kind.as_str(), &mut fork);
+ let match_res = match_meta_var(kind, &mut fork);
match match_res.err {
None => {
// Some meta variables are optional (e.g. vis)
@@ -484,8 +484,15 @@ fn match_loop_inner<'t>(
}
Some(err) => {
res.add_err(err);
- if let Some(fragment) = match_res.value {
- bindings_builder.push_fragment(&mut item.bindings, name, fragment);
+ match match_res.value {
+ Some(fragment) => bindings_builder.push_fragment(
+ &mut item.bindings,
+ name,
+ fragment,
+ ),
+ None => {
+ bindings_builder.push_missing(&mut item.bindings, name, kind)
+ }
}
item.is_error = true;
error_items.push(item);
@@ -677,20 +684,20 @@ fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter<'_>) -> Result<(), ExpandError> {
}
}
-fn match_meta_var(kind: &str, input: &mut TtIter<'_>) -> ExpandResult<Option<Fragment>> {
+fn match_meta_var(kind: MetaVarKind, input: &mut TtIter<'_>) -> ExpandResult<Option<Fragment>> {
let fragment = match kind {
- "path" => parser::PrefixEntryPoint::Path,
- "ty" => parser::PrefixEntryPoint::Ty,
+ MetaVarKind::Path => parser::PrefixEntryPoint::Path,
+ MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
// FIXME: These two should actually behave differently depending on the edition.
//
// https://doc.rust-lang.org/edition-guide/rust-2021/or-patterns-macro-rules.html
- "pat" | "pat_param" => parser::PrefixEntryPoint::Pat,
- "stmt" => parser::PrefixEntryPoint::Stmt,
- "block" => parser::PrefixEntryPoint::Block,
- "meta" => parser::PrefixEntryPoint::MetaItem,
- "item" => parser::PrefixEntryPoint::Item,
- "vis" => parser::PrefixEntryPoint::Vis,
- "expr" => {
+ MetaVarKind::Pat | MetaVarKind::PatParam => parser::PrefixEntryPoint::Pat,
+ MetaVarKind::Stmt => parser::PrefixEntryPoint::Stmt,
+ MetaVarKind::Block => parser::PrefixEntryPoint::Block,
+ MetaVarKind::Meta => parser::PrefixEntryPoint::MetaItem,
+ MetaVarKind::Item => parser::PrefixEntryPoint::Item,
+ MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
+ MetaVarKind::Expr => {
// `expr` should not match underscores.
// HACK: Macro expansion should not be done using "rollback and try another alternative".
// rustc [explicitly checks the next token][0].
@@ -707,17 +714,17 @@ fn match_meta_var(kind: &str, input: &mut TtIter<'_>) -> ExpandResult<Option<Fra
}
_ => {
let tt_result = match kind {
- "ident" => input
+ MetaVarKind::Ident => input
.expect_ident()
.map(|ident| tt::Leaf::from(ident.clone()).into())
.map_err(|()| ExpandError::binding_error("expected ident")),
- "tt" => input
+ MetaVarKind::Tt => input
.expect_tt()
.map_err(|()| ExpandError::binding_error("expected token tree")),
- "lifetime" => input
+ MetaVarKind::Lifetime => input
.expect_lifetime()
.map_err(|()| ExpandError::binding_error("expected lifetime")),
- "literal" => {
+ MetaVarKind::Literal => {
let neg = input.eat_char('-');
input
.expect_literal()
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
index 7bcc84740..cbb59ab8e 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -6,7 +6,7 @@ use tt::{Delimiter, Subtree};
use crate::{
expander::{Binding, Bindings, Fragment},
- parser::{Op, RepeatKind, Separator},
+ parser::{MetaVarKind, Op, RepeatKind, Separator},
ExpandError, ExpandResult, MetaTemplate,
};
@@ -15,7 +15,7 @@ impl Bindings {
self.inner.contains_key(name)
}
- fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
+ fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<Fragment, ExpandError> {
macro_rules! binding_err {
($($arg:tt)*) => { ExpandError::binding_error(format!($($arg)*)) };
}
@@ -26,6 +26,7 @@ impl Bindings {
nesting_state.hit = true;
b = match b {
Binding::Fragment(_) => break,
+ Binding::Missing(_) => break,
Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| {
nesting_state.at_end = true;
binding_err!("could not find nested binding `{name}`")
@@ -37,7 +38,55 @@ impl Bindings {
};
}
match b {
- Binding::Fragment(it) => Ok(it),
+ Binding::Fragment(it) => Ok(it.clone()),
+ // emit some reasonable default expansion for missing bindings,
+ // this gives better recovery than emitting the `$fragment-name` verbatim
+ Binding::Missing(it) => Ok(match it {
+ MetaVarKind::Stmt => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
+ id: tt::TokenId::unspecified(),
+ char: ';',
+ spacing: tt::Spacing::Alone,
+ })))
+ }
+ MetaVarKind::Block => Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
+ delimiter: Some(tt::Delimiter {
+ id: tt::TokenId::unspecified(),
+ kind: tt::DelimiterKind::Brace,
+ }),
+ token_trees: vec![],
+ })),
+ // FIXME: Meta and Item should get proper defaults
+ MetaVarKind::Meta | MetaVarKind::Item | MetaVarKind::Tt | MetaVarKind::Vis => {
+ Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
+ delimiter: None,
+ token_trees: vec![],
+ }))
+ }
+ MetaVarKind::Path
+ | MetaVarKind::Ty
+ | MetaVarKind::Pat
+ | MetaVarKind::PatParam
+ | MetaVarKind::Expr
+ | MetaVarKind::Ident => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+ text: SmolStr::new_inline("missing"),
+ id: tt::TokenId::unspecified(),
+ })))
+ }
+ MetaVarKind::Lifetime => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+ text: SmolStr::new_inline("'missing"),
+ id: tt::TokenId::unspecified(),
+ })))
+ }
+ MetaVarKind::Literal => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+ text: SmolStr::new_inline("\"missing\""),
+ id: tt::TokenId::unspecified(),
+ })))
+ }
+ }),
Binding::Nested(_) => {
Err(binding_err!("expected simple binding, found nested binding `{name}`"))
}
@@ -157,7 +206,7 @@ fn expand_var(ctx: &mut ExpandCtx<'_>, v: &SmolStr, id: tt::TokenId) -> ExpandRe
} else {
ctx.bindings.get(v, &mut ctx.nesting).map_or_else(
|e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
- |b| ExpandResult::ok(b.clone()),
+ |it| ExpandResult::ok(it),
)
}
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
index 79da84f4a..c4f0fa20d 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
@@ -21,7 +21,7 @@ mod token_map;
use std::fmt;
use crate::{
- parser::{MetaTemplate, Op},
+ parser::{MetaTemplate, MetaVarKind, Op},
tt_iter::TtIter,
};
@@ -291,9 +291,9 @@ fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
// Checks that no repetition which could match an empty token
// https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
let lsh_is_empty_seq = separator.is_none() && subtree.iter().all(|child_op| {
- match child_op {
+ match *child_op {
// vis is optional
- Op::Var { kind: Some(kind), .. } => kind == "vis",
+ Op::Var { kind: Some(kind), .. } => kind == MetaVarKind::Vis,
Op::Repeat {
kind: parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne,
..
diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index acb4be584..351c359b7 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
@@ -50,7 +50,7 @@ impl MetaTemplate {
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum Op {
- Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
+ Var { name: SmolStr, kind: Option<MetaVarKind>, id: tt::TokenId },
Ignore { name: SmolStr, id: tt::TokenId },
Index { depth: u32 },
Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
@@ -65,6 +65,24 @@ pub(crate) enum RepeatKind {
ZeroOrOne,
}
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub(crate) enum MetaVarKind {
+ Path,
+ Ty,
+ Pat,
+ PatParam,
+ Stmt,
+ Block,
+ Meta,
+ Item,
+ Vis,
+ Expr,
+ Ident,
+ Tt,
+ Lifetime,
+ Literal,
+}
+
#[derive(Clone, Debug, Eq)]
pub(crate) enum Separator {
Literal(tt::Literal),
@@ -179,13 +197,30 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
Ok(res)
}
-fn eat_fragment_kind(src: &mut TtIter<'_>, mode: Mode) -> Result<Option<SmolStr>, ParseError> {
+fn eat_fragment_kind(src: &mut TtIter<'_>, mode: Mode) -> Result<Option<MetaVarKind>, ParseError> {
if let Mode::Pattern = mode {
src.expect_char(':').map_err(|()| ParseError::unexpected("missing fragment specifier"))?;
let ident = src
.expect_ident()
.map_err(|()| ParseError::unexpected("missing fragment specifier"))?;
- return Ok(Some(ident.text.clone()));
+ let kind = match ident.text.as_str() {
+ "path" => MetaVarKind::Path,
+ "ty" => MetaVarKind::Ty,
+ "pat" => MetaVarKind::Pat,
+ "pat_param" => MetaVarKind::PatParam,
+ "stmt" => MetaVarKind::Stmt,
+ "block" => MetaVarKind::Block,
+ "meta" => MetaVarKind::Meta,
+ "item" => MetaVarKind::Item,
+ "vis" => MetaVarKind::Vis,
+ "expr" => MetaVarKind::Expr,
+ "ident" => MetaVarKind::Ident,
+ "tt" => MetaVarKind::Tt,
+ "lifetime" => MetaVarKind::Lifetime,
+ "literal" => MetaVarKind::Literal,
+ _ => return Ok(None),
+ };
+ return Ok(Some(kind));
};
Ok(None)
}