Skip to content

Commit 21bd8a4

Browse files
committed
mbe: Add fragment type fn to parse a function
1 parent caccb4d commit 21bd8a4

22 files changed

+132
-18
lines changed

compiler/rustc_ast/src/token.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ pub enum NonterminalKind {
11011101
Path,
11021102
Vis,
11031103
TT,
1104+
Fn,
11041105
}
11051106

11061107
impl NonterminalKind {
@@ -1138,6 +1139,7 @@ impl NonterminalKind {
11381139
sym::path => NonterminalKind::Path,
11391140
sym::vis => NonterminalKind::Vis,
11401141
sym::tt => NonterminalKind::TT,
1142+
kw::Fn => NonterminalKind::Fn,
11411143
_ => return None,
11421144
})
11431145
}
@@ -1159,6 +1161,7 @@ impl NonterminalKind {
11591161
NonterminalKind::Path => sym::path,
11601162
NonterminalKind::Vis => sym::vis,
11611163
NonterminalKind::TT => sym::tt,
1164+
NonterminalKind::Fn => kw::Fn,
11621165
}
11631166
}
11641167
}

compiler/rustc_expand/src/mbe/macro_rules.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
15501550
IsInFollow::Yes
15511551
} else {
15521552
match kind {
1553-
NonterminalKind::Item => {
1553+
NonterminalKind::Item | NonterminalKind::Fn => {
15541554
// since items *must* be followed by either a `;` or a `}`, we can
15551555
// accept anything after them
15561556
IsInFollow::Yes

compiler/rustc_expand/src/mbe/quoted.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetiti
1414

1515
pub(crate) const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
1616
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, \
17-
`meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility";
17+
`meta`, `tt`, `item`, `fn`, and `vis`, along with `expr_2021` and `pat_param` for edition compatibility";
1818

1919
/// Which part of a macro rule we're parsing
2020
#[derive(Copy, Clone)]
@@ -142,6 +142,10 @@ fn parse(
142142
});
143143
NonterminalKind::TT
144144
});
145+
if matches!(kind, NonterminalKind::Fn) && !features.macro_fragments_more() {
146+
let msg = "macro `:fn` and `:adt` fragments are unstable";
147+
feature_err(sess, sym::macro_fragments_more, span, msg).emit();
148+
}
145149
result.push(TokenTree::MetaVarDecl { span, name: ident, kind });
146150
} else {
147151
// Whether it's none or some other tree, it doesn't belong to

compiler/rustc_expand/src/mbe/transcribe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ fn transcribe_pnr<'tx>(
437437
let kind = token::NtLifetime(*ident, *is_raw);
438438
TokenTree::token_alone(kind, sp)
439439
}
440-
ParseNtResult::Item(item) => {
440+
ParseNtResult::Item(item) | ParseNtResult::Fn(item) => {
441441
mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item))
442442
}
443443
ParseNtResult::Block(block) => {

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ declare_features! (
557557
(unstable, macro_attr, "CURRENT_RUSTC_VERSION", Some(83527)),
558558
/// Allow `macro_rules!` derive rules
559559
(unstable, macro_derive, "CURRENT_RUSTC_VERSION", Some(143549)),
560+
/// Allow `macro_rules!` fragments `:fn` and `:adt`
561+
(incomplete, macro_fragments_more, "CURRENT_RUSTC_VERSION", Some(147023)),
560562
/// Give access to additional metadata about declarative macro meta-variables.
561563
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
562564
/// Provides a way to concatenate identifiers using metavariable expressions.

compiler/rustc_parse/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ parse_no_digits_literal = no valid digits found for number
721721
parse_non_string_abi_literal = non-string ABI literal
722722
.suggestion = specify the ABI with a string literal
723723
724+
parse_nonterminal_expected_fn = expected a function
724725
parse_nonterminal_expected_ident = expected ident, found `{$token}`
725726
parse_nonterminal_expected_item_keyword = expected an item keyword
726727
parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`

compiler/rustc_parse/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,8 @@ pub(crate) enum UnexpectedNonterminal {
21692169
Item(#[primary_span] Span),
21702170
#[diag(parse_nonterminal_expected_statement)]
21712171
Statement(#[primary_span] Span),
2172+
#[diag(parse_nonterminal_expected_fn)]
2173+
Fn(#[primary_span] Span),
21722174
#[diag(parse_nonterminal_expected_ident)]
21732175
Ident {
21742176
#[primary_span]

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,7 @@ pub enum ParseNtResult {
16691669
Ident(Ident, IdentIsRaw),
16701670
Lifetime(Ident, IdentIsRaw),
16711671
Item(Box<ast::Item>),
1672+
Fn(Box<ast::Item>),
16721673
Block(Box<ast::Block>),
16731674
Stmt(Box<ast::Stmt>),
16741675
Pat(Box<ast::Pat>, NtPatKind),

compiler/rustc_parse/src/parser/nonterminal.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_ast::ItemKind;
12
use rustc_ast::token::NtExprKind::*;
23
use rustc_ast::token::NtPatKind::*;
34
use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, NonterminalKind, Token};
@@ -101,9 +102,10 @@ impl<'a> Parser<'a> {
101102
token::Lifetime(..) | token::NtLifetime(..) => true,
102103
_ => false,
103104
},
104-
NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
105-
token.kind.close_delim().is_none()
106-
}
105+
NonterminalKind::TT
106+
| NonterminalKind::Item
107+
| NonterminalKind::Stmt
108+
| NonterminalKind::Fn => token.kind.close_delim().is_none(),
107109
}
108110
}
109111

@@ -122,6 +124,15 @@ impl<'a> Parser<'a> {
122124
Some(item) => Ok(ParseNtResult::Item(item)),
123125
None => Err(self.dcx().create_err(UnexpectedNonterminal::Item(self.token.span))),
124126
},
127+
NonterminalKind::Fn => {
128+
if let Some(item) = self.parse_item(ForceCollect::Yes)?
129+
&& let ItemKind::Fn(_) = item.kind
130+
{
131+
Ok(ParseNtResult::Fn(item))
132+
} else {
133+
Err(self.dcx().create_err(UnexpectedNonterminal::Fn(self.token.span)))
134+
}
135+
}
125136
NonterminalKind::Block => {
126137
// While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`),
127138
// the ':block' matcher does not support them

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,7 @@ symbols! {
13451345
macro_derive,
13461346
macro_escape,
13471347
macro_export,
1348+
macro_fragments_more,
13481349
macro_lifetime_matcher,
13491350
macro_literal_matcher,
13501351
macro_metavar_expr,

0 commit comments

Comments
 (0)