mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #153702 - SpriteOvO:guard-matcher, r=davidtwco
Add macro matcher for `guard` fragment specifier Tracking issue #153104 This PR implements a new `guard` macro matcher to match `if-let` guards (specifically [`MatchArmGuard`](https://github.com/rust-lang/reference/blob/50a1075e879be75aeec436252c84eef0fad489f4/src/expressions/match-expr.md#match-guards)). In the upcoming PR, we can use this new matcher in the `matches!` and `assert_matches!` macros to support their use with `if-let` guards. (see #152313) The original `Expr` used to represent a guard has been wrapped in a new `Guard` type, allowing us to carry the span information of the leading `if` keyword. However, it might be even better to include the `if` keyword in the `Guard` type as well? I've left a FIXME comment in the code.
This commit is contained in:
@@ -938,7 +938,7 @@ pub enum PatKind {
|
||||
Never,
|
||||
|
||||
/// A guard pattern (e.g., `x if guard(x)`).
|
||||
Guard(Box<Pat>, Box<Expr>),
|
||||
Guard(Box<Pat>, Box<Guard>),
|
||||
|
||||
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
|
||||
Paren(Box<Pat>),
|
||||
@@ -1346,7 +1346,7 @@ pub struct Arm {
|
||||
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`.
|
||||
pub pat: Box<Pat>,
|
||||
/// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`.
|
||||
pub guard: Option<Box<Expr>>,
|
||||
pub guard: Option<Box<Guard>>,
|
||||
/// Match arm body. Omitted if the pattern is a never pattern.
|
||||
pub body: Option<Box<Expr>>,
|
||||
pub span: Span,
|
||||
@@ -3954,6 +3954,18 @@ impl ConstBlockItem {
|
||||
pub const IDENT: Ident = Ident { name: kw::Underscore, span: DUMMY_SP };
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct Guard {
|
||||
pub cond: Expr,
|
||||
pub span_with_leading_if: Span,
|
||||
}
|
||||
|
||||
impl Guard {
|
||||
pub fn span(&self) -> Span {
|
||||
self.cond.span
|
||||
}
|
||||
}
|
||||
|
||||
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum ItemKind {
|
||||
|
||||
@@ -94,6 +94,7 @@ pub enum MetaVarKind {
|
||||
},
|
||||
Path,
|
||||
Vis,
|
||||
Guard,
|
||||
TT,
|
||||
}
|
||||
|
||||
@@ -114,6 +115,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
MetaVarKind::Meta { .. } => sym::meta,
|
||||
MetaVarKind::Path => sym::path,
|
||||
MetaVarKind::Vis => sym::vis,
|
||||
MetaVarKind::Guard => sym::guard,
|
||||
MetaVarKind::TT => sym::tt,
|
||||
};
|
||||
write!(f, "{sym}")
|
||||
@@ -1124,6 +1126,7 @@ pub enum NonterminalKind {
|
||||
Meta,
|
||||
Path,
|
||||
Vis,
|
||||
Guard,
|
||||
TT,
|
||||
}
|
||||
|
||||
@@ -1161,6 +1164,7 @@ pub fn from_symbol(
|
||||
sym::meta => NonterminalKind::Meta,
|
||||
sym::path => NonterminalKind::Path,
|
||||
sym::vis => NonterminalKind::Vis,
|
||||
sym::guard => NonterminalKind::Guard,
|
||||
sym::tt => NonterminalKind::TT,
|
||||
_ => return None,
|
||||
})
|
||||
@@ -1182,6 +1186,7 @@ fn symbol(self) -> Symbol {
|
||||
NonterminalKind::Meta => sym::meta,
|
||||
NonterminalKind::Path => sym::path,
|
||||
NonterminalKind::Vis => sym::vis,
|
||||
NonterminalKind::Guard => sym::guard,
|
||||
NonterminalKind::TT => sym::tt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +442,7 @@ pub fn ctxt(&self) -> Option<FnCtxt> {
|
||||
FormatArguments,
|
||||
FormatPlaceholder,
|
||||
GenericParamKind,
|
||||
Guard,
|
||||
Impl,
|
||||
ImplPolarity,
|
||||
Inline,
|
||||
|
||||
@@ -640,7 +640,7 @@ fn wrap_in_try_constructor(
|
||||
|
||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||
let pat = self.lower_pat(&arm.pat);
|
||||
let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
|
||||
let guard = arm.guard.as_ref().map(|guard| self.lower_expr(&guard.cond));
|
||||
let hir_id = self.next_id();
|
||||
let span = self.lower_span(arm.span);
|
||||
self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm);
|
||||
@@ -663,7 +663,7 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||
} else if let Some(body) = &arm.body {
|
||||
self.dcx().emit_err(NeverPatternWithBody { span: body.span });
|
||||
} else if let Some(g) = &arm.guard {
|
||||
self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
|
||||
self.dcx().emit_err(NeverPatternWithGuard { span: g.span() });
|
||||
}
|
||||
|
||||
// We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never
|
||||
|
||||
@@ -133,8 +133,11 @@ fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
|
||||
self.lower_range_end(end, e2.is_some()),
|
||||
);
|
||||
}
|
||||
PatKind::Guard(inner, cond) => {
|
||||
break hir::PatKind::Guard(self.lower_pat(inner), self.lower_expr(cond));
|
||||
PatKind::Guard(inner, guard) => {
|
||||
break hir::PatKind::Guard(
|
||||
self.lower_pat(inner),
|
||||
self.lower_expr(&guard.cond),
|
||||
);
|
||||
}
|
||||
PatKind::Slice(pats) => break self.lower_pat_slice(pats),
|
||||
PatKind::Rest => {
|
||||
|
||||
@@ -1943,12 +1943,12 @@ fn print_pat(&mut self, pat: &ast::Pat) {
|
||||
self.print_expr(e, FixupContext::default());
|
||||
}
|
||||
}
|
||||
PatKind::Guard(subpat, condition) => {
|
||||
PatKind::Guard(subpat, guard) => {
|
||||
self.popen();
|
||||
self.print_pat(subpat);
|
||||
self.space();
|
||||
self.word_space("if");
|
||||
self.print_expr(condition, FixupContext::default());
|
||||
self.print_expr(&guard.cond, FixupContext::default());
|
||||
self.pclose();
|
||||
}
|
||||
PatKind::Slice(elts) => {
|
||||
|
||||
@@ -891,9 +891,9 @@ fn print_arm(&mut self, arm: &ast::Arm) {
|
||||
self.print_outer_attributes(&arm.attrs);
|
||||
self.print_pat(&arm.pat);
|
||||
self.space();
|
||||
if let Some(e) = &arm.guard {
|
||||
if let Some(guard) = &arm.guard {
|
||||
self.word_space("if");
|
||||
self.print_expr(e, FixupContext::default());
|
||||
self.print_expr(&guard.cond, FixupContext::default());
|
||||
self.space();
|
||||
}
|
||||
|
||||
|
||||
@@ -724,7 +724,7 @@ pub fn compile_declarative_macro(
|
||||
let args = p.parse_token_tree();
|
||||
check_args_parens(sess, sym::attr, &args);
|
||||
let args = parse_one_tt(args, RulePart::Pattern, sess, node_id, features, edition);
|
||||
check_emission(check_lhs(sess, node_id, &args));
|
||||
check_emission(check_lhs(sess, features, node_id, &args));
|
||||
if let Some(guar) = check_no_eof(sess, &p, "expected macro attr body") {
|
||||
return dummy_syn_ext(guar);
|
||||
}
|
||||
@@ -773,7 +773,7 @@ pub fn compile_declarative_macro(
|
||||
};
|
||||
let lhs_tt = p.parse_token_tree();
|
||||
let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition);
|
||||
check_emission(check_lhs(sess, node_id, &lhs_tt));
|
||||
check_emission(check_lhs(sess, features, node_id, &lhs_tt));
|
||||
if let Err(e) = p.expect(exp!(FatArrow)) {
|
||||
return dummy_syn_ext(e.emit());
|
||||
}
|
||||
@@ -870,21 +870,27 @@ fn check_args_empty(sess: &Session, args: &tokenstream::TokenTree) -> Result<(),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> {
|
||||
let e1 = check_lhs_nt_follows(sess, node_id, lhs);
|
||||
fn check_lhs(
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
node_id: NodeId,
|
||||
lhs: &mbe::TokenTree,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let e1 = check_lhs_nt_follows(sess, features, node_id, lhs);
|
||||
let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
|
||||
e1.and(e2)
|
||||
}
|
||||
|
||||
fn check_lhs_nt_follows(
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
node_id: NodeId,
|
||||
lhs: &mbe::TokenTree,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// lhs is going to be like TokenTree::Delimited(...), where the
|
||||
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
||||
if let mbe::TokenTree::Delimited(.., delimited) = lhs {
|
||||
check_matcher(sess, node_id, &delimited.tts)
|
||||
check_matcher(sess, features, node_id, &delimited.tts)
|
||||
} else {
|
||||
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
|
||||
Err(sess.dcx().span_err(lhs.span(), msg))
|
||||
@@ -989,12 +995,13 @@ fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed
|
||||
|
||||
fn check_matcher(
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
node_id: NodeId,
|
||||
matcher: &[mbe::TokenTree],
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let first_sets = FirstSets::new(matcher);
|
||||
let empty_suffix = TokenSet::empty();
|
||||
check_matcher_core(sess, node_id, &first_sets, matcher, &empty_suffix)?;
|
||||
check_matcher_core(sess, features, node_id, &first_sets, matcher, &empty_suffix)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1331,6 +1338,7 @@ fn add_all(&mut self, other: &Self) {
|
||||
// see `FirstSets::new`.
|
||||
fn check_matcher_core<'tt>(
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
node_id: NodeId,
|
||||
first_sets: &FirstSets<'tt>,
|
||||
matcher: &'tt [mbe::TokenTree],
|
||||
@@ -1369,6 +1377,17 @@ fn check_matcher_core<'tt>(
|
||||
| TokenTree::MetaVar(..)
|
||||
| TokenTree::MetaVarDecl { .. }
|
||||
| TokenTree::MetaVarExpr(..) => {
|
||||
if let TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } = token
|
||||
&& !features.macro_guard_matcher()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::macro_guard_matcher,
|
||||
token.span(),
|
||||
"`guard` fragments in macro are unstable",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
if token_can_be_followed_by_any(token) {
|
||||
// don't need to track tokens that work with any,
|
||||
last.replace_with_irrelevant();
|
||||
@@ -1385,7 +1404,7 @@ fn check_matcher_core<'tt>(
|
||||
d.delim.as_close_token_kind(),
|
||||
span.close,
|
||||
));
|
||||
check_matcher_core(sess, node_id, first_sets, &d.tts, &my_suffix)?;
|
||||
check_matcher_core(sess, features, node_id, first_sets, &d.tts, &my_suffix)?;
|
||||
// don't track non NT tokens
|
||||
last.replace_with_irrelevant();
|
||||
|
||||
@@ -1417,7 +1436,14 @@ fn check_matcher_core<'tt>(
|
||||
// At this point, `suffix_first` is built, and
|
||||
// `my_suffix` is some TokenSet that we can use
|
||||
// for checking the interior of `seq_rep`.
|
||||
let next = check_matcher_core(sess, node_id, first_sets, &seq_rep.tts, my_suffix)?;
|
||||
let next = check_matcher_core(
|
||||
sess,
|
||||
features,
|
||||
node_id,
|
||||
first_sets,
|
||||
&seq_rep.tts,
|
||||
my_suffix,
|
||||
)?;
|
||||
if next.maybe_empty {
|
||||
last.add_all(&next);
|
||||
} else {
|
||||
@@ -1609,7 +1635,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
|
||||
}
|
||||
}
|
||||
NonterminalKind::Pat(PatParam { .. }) => {
|
||||
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
|
||||
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`if let`", "`in`"];
|
||||
match tok {
|
||||
TokenTree::Token(token) => match token.kind {
|
||||
FatArrow | Comma | Eq | Or => IsInFollow::Yes,
|
||||
@@ -1618,11 +1644,12 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
|
||||
}
|
||||
_ => IsInFollow::No(TOKENS),
|
||||
},
|
||||
TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } => IsInFollow::Yes,
|
||||
_ => IsInFollow::No(TOKENS),
|
||||
}
|
||||
}
|
||||
NonterminalKind::Pat(PatWithOr) => {
|
||||
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
|
||||
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`if let`", "`in`"];
|
||||
match tok {
|
||||
TokenTree::Token(token) => match token.kind {
|
||||
FatArrow | Comma | Eq => IsInFollow::Yes,
|
||||
@@ -1631,6 +1658,17 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
|
||||
}
|
||||
_ => IsInFollow::No(TOKENS),
|
||||
},
|
||||
TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } => IsInFollow::Yes,
|
||||
_ => IsInFollow::No(TOKENS),
|
||||
}
|
||||
}
|
||||
NonterminalKind::Guard => {
|
||||
const TOKENS: &[&str] = &["`=>`", "`,`", "`{`"];
|
||||
match tok {
|
||||
TokenTree::Token(token) => match token.kind {
|
||||
FatArrow | Comma | OpenBrace => IsInFollow::Yes,
|
||||
_ => IsInFollow::No(TOKENS),
|
||||
},
|
||||
_ => IsInFollow::No(TOKENS),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||
use rustc_span::{
|
||||
Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, sym, with_metavar_spans,
|
||||
BytePos, Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, kw, sym,
|
||||
with_metavar_spans,
|
||||
};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
@@ -556,6 +557,19 @@ fn transcribe_pnr<'tx>(
|
||||
ParseNtResult::Vis(vis) => {
|
||||
mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis))
|
||||
}
|
||||
ParseNtResult::Guard(guard) => {
|
||||
// FIXME(macro_guard_matcher):
|
||||
// Perhaps it would be better to treat the leading `if` as part of `ast::Guard` during parsing?
|
||||
// Currently they are separate, but in macros we match and emit the leading `if` for `:guard` matchers, which creates some inconsistency.
|
||||
|
||||
let leading_if_span =
|
||||
guard.span_with_leading_if.with_hi(guard.span_with_leading_if.lo() + BytePos(2));
|
||||
let mut ts =
|
||||
TokenStream::token_alone(token::Ident(kw::If, IdentIsRaw::No), leading_if_span);
|
||||
ts.push_stream(TokenStream::from_ast(&guard.cond));
|
||||
|
||||
mk_delimited(guard.span_with_leading_if, MetaVarKind::Guard, ts)
|
||||
}
|
||||
};
|
||||
|
||||
tscx.result.push(tt);
|
||||
|
||||
@@ -569,6 +569,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(unstable, macro_attr, "1.91.0", Some(143547)),
|
||||
/// Allow `macro_rules!` derive rules
|
||||
(unstable, macro_derive, "1.91.0", Some(143549)),
|
||||
/// Allow `$x:guard` matcher in macros
|
||||
(unstable, macro_guard_matcher, "CURRENT_RUSTC_VERSION", Some(153104)),
|
||||
/// Give access to additional metadata about declarative macro meta-variables.
|
||||
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
|
||||
/// Provides a way to concatenate identifiers using metavariable expressions.
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind,
|
||||
BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl,
|
||||
FnRetTy, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param, RangeLimits,
|
||||
StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
|
||||
FnRetTy, Guard, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param,
|
||||
RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
|
||||
};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
|
||||
@@ -2767,7 +2767,7 @@ pub fn parse_expr_cond(
|
||||
|
||||
/// Parses a `let $pat = $expr` pseudo-expression.
|
||||
fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
|
||||
let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
|
||||
let recovered: Recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
|
||||
let err = errors::ExpectedExpressionFoundLet {
|
||||
span: self.token.span,
|
||||
reason: errors::ForbiddenLetReason::OtherForbidden,
|
||||
@@ -3463,20 +3463,54 @@ pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Expr>>> {
|
||||
pub(crate) fn eat_metavar_guard(&mut self) -> Option<Box<Guard>> {
|
||||
self.eat_metavar_seq_with_matcher(
|
||||
|mv_kind| matches!(mv_kind, MetaVarKind::Guard),
|
||||
|this| this.parse_match_arm_guard(),
|
||||
)
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Guard>>> {
|
||||
if let Some(guard) = self.eat_metavar_guard() {
|
||||
return Ok(Some(guard));
|
||||
}
|
||||
|
||||
if !self.eat_keyword(exp!(If)) {
|
||||
// No match arm guard present.
|
||||
return Ok(None);
|
||||
}
|
||||
self.expect_match_arm_guard_cond(ForceCollect::No).map(Some)
|
||||
}
|
||||
|
||||
let mut cond = self.parse_match_guard_condition()?;
|
||||
pub(crate) fn expect_match_arm_guard(
|
||||
&mut self,
|
||||
force_collect: ForceCollect,
|
||||
) -> PResult<'a, Box<Guard>> {
|
||||
if let Some(guard) = self.eat_metavar_guard() {
|
||||
return Ok(guard);
|
||||
}
|
||||
|
||||
self.expect_keyword(exp!(If))?;
|
||||
self.expect_match_arm_guard_cond(force_collect)
|
||||
}
|
||||
|
||||
fn expect_match_arm_guard_cond(
|
||||
&mut self,
|
||||
force_collect: ForceCollect,
|
||||
) -> PResult<'a, Box<Guard>> {
|
||||
let leading_if_span = self.prev_token.span;
|
||||
|
||||
let mut cond = self.parse_match_guard_condition(force_collect)?;
|
||||
let cond_span = cond.span;
|
||||
|
||||
CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
|
||||
|
||||
Ok(Some(cond))
|
||||
let guard = Guard { cond: *cond, span_with_leading_if: leading_if_span.to(cond_span) };
|
||||
Ok(Box::new(guard))
|
||||
}
|
||||
|
||||
fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr>>)> {
|
||||
fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Guard>>)> {
|
||||
if self.token == token::OpenParen {
|
||||
let left = self.token.span;
|
||||
let pat = self.parse_pat_no_top_guard(
|
||||
@@ -3492,10 +3526,10 @@ fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr
|
||||
// FIXME(guard_patterns): convert this to a normal guard instead
|
||||
let span = pat.span;
|
||||
let ast::PatKind::Paren(subpat) = pat.kind else { unreachable!() };
|
||||
let ast::PatKind::Guard(_, mut cond) = subpat.kind else { unreachable!() };
|
||||
self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
|
||||
let ast::PatKind::Guard(_, mut guard) = subpat.kind else { unreachable!() };
|
||||
self.psess.gated_spans.ungate_last(sym::guard_patterns, guard.span());
|
||||
let mut checker = CondChecker::new(self, LetChainsPolicy::AlwaysAllowed);
|
||||
checker.visit_expr(&mut cond);
|
||||
checker.visit_expr(&mut guard.cond);
|
||||
|
||||
let right = self.prev_token.span;
|
||||
self.dcx().emit_err(errors::ParenthesesInMatchPat {
|
||||
@@ -3503,14 +3537,10 @@ fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr
|
||||
sugg: errors::ParenthesesInMatchPatSugg { left, right },
|
||||
});
|
||||
|
||||
Ok((
|
||||
self.mk_pat(span, ast::PatKind::Wild),
|
||||
(if let Some(guar) = checker.found_incorrect_let_chain {
|
||||
Some(self.mk_expr_err(cond.span, guar))
|
||||
} else {
|
||||
Some(cond)
|
||||
}),
|
||||
))
|
||||
if let Some(guar) = checker.found_incorrect_let_chain {
|
||||
guard.cond = *self.mk_expr_err(guard.span(), guar);
|
||||
}
|
||||
Ok((self.mk_pat(span, ast::PatKind::Wild), Some(guard)))
|
||||
} else {
|
||||
Ok((pat, self.parse_match_arm_guard()?))
|
||||
}
|
||||
@@ -3526,33 +3556,47 @@ fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_match_guard_condition(&mut self) -> PResult<'a, Box<Expr>> {
|
||||
fn parse_match_guard_condition(
|
||||
&mut self,
|
||||
force_collect: ForceCollect,
|
||||
) -> PResult<'a, Box<Expr>> {
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) {
|
||||
Ok((expr, _)) => Ok(expr),
|
||||
Err(mut err) => {
|
||||
if self.prev_token == token::OpenBrace {
|
||||
let sugg_sp = self.prev_token.span.shrink_to_lo();
|
||||
// Consume everything within the braces, let's avoid further parse
|
||||
// errors.
|
||||
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
|
||||
let msg = "you might have meant to start a match arm after the match guard";
|
||||
if self.eat(exp!(CloseBrace)) {
|
||||
let applicability = if self.token != token::FatArrow {
|
||||
// We have high confidence that we indeed didn't have a struct
|
||||
// literal in the match guard, but rather we had some operation
|
||||
// that ended in a path, immediately followed by a block that was
|
||||
// meant to be the match arm.
|
||||
Applicability::MachineApplicable
|
||||
} else {
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
|
||||
let expr = self.collect_tokens(
|
||||
None,
|
||||
AttrWrapper::empty(),
|
||||
force_collect,
|
||||
|this, _empty_attrs| {
|
||||
match this
|
||||
.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs)
|
||||
{
|
||||
Ok((expr, _)) => Ok((expr, Trailing::No, UsePreAttrPos::No)),
|
||||
Err(mut err) => {
|
||||
if this.prev_token == token::OpenBrace {
|
||||
let sugg_sp = this.prev_token.span.shrink_to_lo();
|
||||
// Consume everything within the braces, let's avoid further parse
|
||||
// errors.
|
||||
this.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
|
||||
let msg =
|
||||
"you might have meant to start a match arm after the match guard";
|
||||
if this.eat(exp!(CloseBrace)) {
|
||||
let applicability = if this.token != token::FatArrow {
|
||||
// We have high confidence that we indeed didn't have a struct
|
||||
// literal in the match guard, but rather we had some operation
|
||||
// that ended in a path, immediately followed by a block that was
|
||||
// meant to be the match arm.
|
||||
Applicability::MachineApplicable
|
||||
} else {
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
)?;
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
pub(crate) fn is_builtin(&self) -> bool {
|
||||
|
||||
@@ -1788,4 +1788,5 @@ pub enum ParseNtResult {
|
||||
Meta(Box<ast::AttrItem>),
|
||||
Path(Box<ast::Path>),
|
||||
Vis(Box<ast::Visibility>),
|
||||
Guard(Box<ast::Guard>),
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
|
||||
|
||||
MetaVarKind::Item
|
||||
| MetaVarKind::Block
|
||||
| MetaVarKind::Vis => false,
|
||||
| MetaVarKind::Vis
|
||||
| MetaVarKind::Guard => false,
|
||||
|
||||
MetaVarKind::Ident
|
||||
| MetaVarKind::Lifetime
|
||||
@@ -86,7 +87,8 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
|
||||
| MetaVarKind::Ty { .. }
|
||||
| MetaVarKind::Meta { .. }
|
||||
| MetaVarKind::Path
|
||||
| MetaVarKind::Vis => false,
|
||||
| MetaVarKind::Vis
|
||||
| MetaVarKind::Guard => false,
|
||||
MetaVarKind::Lifetime | MetaVarKind::Ident | MetaVarKind::TT => {
|
||||
unreachable!()
|
||||
}
|
||||
@@ -103,6 +105,7 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
|
||||
token::Lifetime(..) | token::NtLifetime(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
NonterminalKind::Guard => token.is_keyword(kw::If),
|
||||
NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
|
||||
token.kind.close_delim().is_none()
|
||||
}
|
||||
@@ -196,6 +199,9 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseN
|
||||
}))
|
||||
}
|
||||
}
|
||||
NonterminalKind::Guard => {
|
||||
Ok(ParseNtResult::Guard(self.expect_match_arm_guard(ForceCollect::Yes)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
use rustc_ast::util::parser::ExprPrecedence;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::{
|
||||
self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability,
|
||||
Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind,
|
||||
self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, Guard, LocalKind, MacCall,
|
||||
Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
|
||||
StmtKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
|
||||
@@ -110,11 +111,19 @@ pub fn parse_pat_allow_top_guard(
|
||||
let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?;
|
||||
|
||||
if self.eat_keyword(exp!(If)) {
|
||||
let cond = self.parse_expr()?;
|
||||
let guard = if let Some(guard) = self.eat_metavar_guard() {
|
||||
guard
|
||||
} else {
|
||||
let leading_if_span = self.prev_token.span;
|
||||
let cond = self.parse_expr()?;
|
||||
let cond_span = cond.span;
|
||||
Box::new(Guard { cond: *cond, span_with_leading_if: leading_if_span.to(cond_span) })
|
||||
};
|
||||
|
||||
// Feature-gate guard patterns
|
||||
self.psess.gated_spans.gate(sym::guard_patterns, cond.span);
|
||||
let span = pat.span.to(cond.span);
|
||||
Ok(self.mk_pat(span, PatKind::Guard(Box::new(pat), cond)))
|
||||
self.psess.gated_spans.gate(sym::guard_patterns, guard.span());
|
||||
let span = pat.span.to(guard.span());
|
||||
Ok(self.mk_pat(span, PatKind::Guard(Box::new(pat), guard)))
|
||||
} else {
|
||||
Ok(pat)
|
||||
}
|
||||
@@ -601,17 +610,18 @@ fn maybe_add_suggestions_then_emit(
|
||||
}
|
||||
Some(guard) => {
|
||||
// Are parentheses required around the old guard?
|
||||
let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd;
|
||||
let wrap_guard =
|
||||
guard.cond.precedence() <= ExprPrecedence::LAnd;
|
||||
|
||||
err.subdiagnostic(
|
||||
UnexpectedExpressionInPatternSugg::UpdateGuard {
|
||||
ident_span,
|
||||
guard_lo: if wrap_guard {
|
||||
Some(guard.span.shrink_to_lo())
|
||||
Some(guard.span().shrink_to_lo())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
guard_hi: guard.span.shrink_to_hi(),
|
||||
guard_hi: guard.span().shrink_to_hi(),
|
||||
guard_hi_paren: if wrap_guard { ")" } else { "" },
|
||||
ident,
|
||||
expr,
|
||||
|
||||
@@ -4073,7 +4073,7 @@ fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
|
||||
fn resolve_arm(&mut self, arm: &'ast Arm) {
|
||||
self.with_rib(ValueNS, RibKind::Normal, |this| {
|
||||
this.resolve_pattern_top(&arm.pat, PatternSource::Match);
|
||||
visit_opt!(this, visit_expr, &arm.guard);
|
||||
visit_opt!(this, visit_expr, arm.guard.as_ref().map(|g| &g.cond));
|
||||
visit_opt!(this, visit_expr, &arm.body);
|
||||
});
|
||||
}
|
||||
@@ -4215,7 +4215,7 @@ fn resolve_pattern_inner(
|
||||
let subpat_bindings = bindings.pop().unwrap().1;
|
||||
self.with_rib(ValueNS, RibKind::Normal, |this| {
|
||||
*this.innermost_rib_bindings(ValueNS) = subpat_bindings.clone();
|
||||
this.resolve_expr(guard, None);
|
||||
this.resolve_expr(&guard.cond, None);
|
||||
});
|
||||
// Propagate the subpattern's bindings upwards.
|
||||
// FIXME(guard_patterns): For `if let` guards, we'll also need to get the
|
||||
|
||||
@@ -1028,6 +1028,7 @@
|
||||
global_registration,
|
||||
globs,
|
||||
gt,
|
||||
guard,
|
||||
guard_patterns,
|
||||
half_open_range_patterns,
|
||||
half_open_range_patterns_in_slices,
|
||||
@@ -1193,6 +1194,7 @@
|
||||
macro_derive,
|
||||
macro_escape,
|
||||
macro_export,
|
||||
macro_guard_matcher,
|
||||
macro_lifetime_matcher,
|
||||
macro_literal_matcher,
|
||||
macro_metavar_expr,
|
||||
|
||||
@@ -280,7 +280,7 @@ pub fn eq_arm(l: &Arm, r: &Arm) -> bool {
|
||||
l.is_placeholder == r.is_placeholder
|
||||
&& eq_pat(&l.pat, &r.pat)
|
||||
&& eq_expr_opt(l.body.as_deref(), r.body.as_deref())
|
||||
&& eq_expr_opt(l.guard.as_deref(), r.guard.as_deref())
|
||||
&& eq_expr_opt(l.guard.as_deref().map(|g| &g.cond), r.guard.as_deref().map(|g| &g.cond))
|
||||
&& over(&l.attrs, &r.attrs, eq_attr)
|
||||
}
|
||||
|
||||
|
||||
@@ -571,7 +571,7 @@ fn rewrite_match_body(
|
||||
// The `if ...` guard on a match arm.
|
||||
fn rewrite_guard(
|
||||
context: &RewriteContext<'_>,
|
||||
guard: &Option<Box<ast::Expr>>,
|
||||
guard: &Option<Box<ast::Guard>>,
|
||||
shape: Shape,
|
||||
// The amount of space used up on this line for the pattern in
|
||||
// the arm (excludes offset).
|
||||
@@ -586,7 +586,7 @@ fn rewrite_guard(
|
||||
.and_then(|s| s.sub_width_opt(5));
|
||||
if !multiline_pattern {
|
||||
if let Some(cond_shape) = cond_shape {
|
||||
if let Ok(cond_str) = guard.rewrite_result(context, cond_shape) {
|
||||
if let Ok(cond_str) = guard.cond.rewrite_result(context, cond_shape) {
|
||||
if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() {
|
||||
return Ok(format!(" if {cond_str}"));
|
||||
}
|
||||
@@ -597,9 +597,9 @@ fn rewrite_guard(
|
||||
// Not enough space to put the guard after the pattern, try a newline.
|
||||
// 3 = `if `, 5 = ` => {`
|
||||
let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config)
|
||||
.offset_left(3, guard.span)?
|
||||
.sub_width(5, guard.span)?;
|
||||
let cond_str = guard.rewrite_result(context, cond_shape)?;
|
||||
.offset_left(3, guard.span())?
|
||||
.sub_width(5, guard.span())?;
|
||||
let cond_str = guard.cond.rewrite_result(context, cond_shape)?;
|
||||
Ok(format!(
|
||||
"{}if {}",
|
||||
cond_shape.indent.to_string_with_newline(context.config),
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
macro_rules! m {
|
||||
($x:guard) => {}; //~ ERROR `guard` fragments in macro are unstable
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
error[E0658]: `guard` fragments in macro are unstable
|
||||
--> $DIR/feature-gate-macro-guard-matcher.rs:3:10
|
||||
|
|
||||
LL | ($x:guard) => {};
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #153104 <https://github.com/rust-lang/rust/issues/153104> for more information
|
||||
= help: add `#![feature(macro_guard_matcher)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@@ -3,13 +3,14 @@
|
||||
#![allow(unused_macros)]
|
||||
// Check the macro follow sets (see corresponding cfail test).
|
||||
|
||||
// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
|
||||
// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), MetaVarDecl(Guard), Ident(in)}
|
||||
macro_rules! follow_pat {
|
||||
($p:pat =>) => {};
|
||||
($p:pat ,) => {};
|
||||
($p:pat =) => {};
|
||||
($p:pat |) => {};
|
||||
($p:pat if) => {};
|
||||
($p:pat if let) => {};
|
||||
($p:pat in) => {};
|
||||
}
|
||||
// FOLLOW(expr) = {FatArrow, Comma, Semicolon}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
//
|
||||
// Check the macro follow sets (see corresponding rpass test).
|
||||
|
||||
#![feature(macro_guard_matcher)]
|
||||
#![allow(unused_macros)]
|
||||
|
||||
// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
|
||||
// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), MetaVarDecl(Guard), Ident(in)}
|
||||
macro_rules! follow_pat {
|
||||
($p:pat ()) => {}; //~ERROR `$p:pat` is followed by `(`
|
||||
($p:pat []) => {}; //~ERROR `$p:pat` is followed by `[`
|
||||
@@ -47,6 +48,7 @@ macro_rules! follow_expr {
|
||||
($e:expr $t:tt) => {}; //~ERROR `$e:expr` is followed by `$t:tt`
|
||||
($e:expr $i:item) => {}; //~ERROR `$e:expr` is followed by `$i:item`
|
||||
($e:expr $m:meta) => {}; //~ERROR `$e:expr` is followed by `$m:meta`
|
||||
($e:expr $g:guard) => {}; //~ERROR `$e:expr` is followed by `$g:guard`
|
||||
}
|
||||
// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
|
||||
// Ident(as), Ident(where), OpenDelim(Bracket), Nonterminal(Block)}
|
||||
@@ -66,6 +68,7 @@ macro_rules! follow_ty {
|
||||
($t:ty $r:tt) => {}; //~ERROR `$t:ty` is followed by `$r:tt`
|
||||
($t:ty $i:item) => {}; //~ERROR `$t:ty` is followed by `$i:item`
|
||||
($t:ty $m:meta) => {}; //~ERROR `$t:ty` is followed by `$m:meta`
|
||||
($t:ty $g:guard) => {}; //~ERROR `$t:ty` is followed by `$g:guard`
|
||||
}
|
||||
// FOLLOW(stmt) = FOLLOW(expr)
|
||||
macro_rules! follow_stmt {
|
||||
@@ -90,6 +93,7 @@ macro_rules! follow_stmt {
|
||||
($s:stmt $t:tt) => {}; //~ERROR `$s:stmt` is followed by `$t:tt`
|
||||
($s:stmt $i:item) => {}; //~ERROR `$s:stmt` is followed by `$i:item`
|
||||
($s:stmt $m:meta) => {}; //~ERROR `$s:stmt` is followed by `$m:meta`
|
||||
($s:stmt $g:guard) => {}; //~ERROR `$s:stmt` is followed by `$g:guard`
|
||||
}
|
||||
// FOLLOW(path) = FOLLOW(ty)
|
||||
macro_rules! follow_path {
|
||||
@@ -108,6 +112,7 @@ macro_rules! follow_path {
|
||||
($p:path $t:tt) => {}; //~ERROR `$p:path` is followed by `$t:tt`
|
||||
($p:path $i:item) => {}; //~ERROR `$p:path` is followed by `$i:item`
|
||||
($p:path $m:meta) => {}; //~ERROR `$p:path` is followed by `$m:meta`
|
||||
($p:path $g:guard) => {}; //~ERROR `$p:path` is followed by `$g:guard`
|
||||
}
|
||||
// FOLLOW(block) = any token
|
||||
// FOLLOW(ident) = any token
|
||||
|
||||
+135
-103
@@ -1,141 +1,141 @@
|
||||
error: `$p:pat` is followed by `(`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:9:13
|
||||
--> $DIR/macro-follow.rs:10:13
|
||||
|
|
||||
LL | ($p:pat ()) => {};
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `[`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:10:13
|
||||
--> $DIR/macro-follow.rs:11:13
|
||||
|
|
||||
LL | ($p:pat []) => {};
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `{`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:11:13
|
||||
--> $DIR/macro-follow.rs:12:13
|
||||
|
|
||||
LL | ($p:pat {}) => {};
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `:`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:12:13
|
||||
--> $DIR/macro-follow.rs:13:13
|
||||
|
|
||||
LL | ($p:pat :) => {};
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `>`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:13:13
|
||||
--> $DIR/macro-follow.rs:14:13
|
||||
|
|
||||
LL | ($p:pat >) => {};
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `+`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:14:13
|
||||
--> $DIR/macro-follow.rs:15:13
|
||||
|
|
||||
LL | ($p:pat +) => {};
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `ident`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:15:13
|
||||
--> $DIR/macro-follow.rs:16:13
|
||||
|
|
||||
LL | ($p:pat ident) => {};
|
||||
| ^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$q:pat`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:16:13
|
||||
--> $DIR/macro-follow.rs:17:13
|
||||
|
|
||||
LL | ($p:pat $q:pat) => {};
|
||||
| ^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$e:expr`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:17:13
|
||||
--> $DIR/macro-follow.rs:18:13
|
||||
|
|
||||
LL | ($p:pat $e:expr) => {};
|
||||
| ^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$t:ty`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:18:13
|
||||
--> $DIR/macro-follow.rs:19:13
|
||||
|
|
||||
LL | ($p:pat $t:ty) => {};
|
||||
| ^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$s:stmt`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:19:13
|
||||
--> $DIR/macro-follow.rs:20:13
|
||||
|
|
||||
LL | ($p:pat $s:stmt) => {};
|
||||
| ^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$q:path`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:20:13
|
||||
--> $DIR/macro-follow.rs:21:13
|
||||
|
|
||||
LL | ($p:pat $q:path) => {};
|
||||
| ^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$b:block`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:21:13
|
||||
--> $DIR/macro-follow.rs:22:13
|
||||
|
|
||||
LL | ($p:pat $b:block) => {};
|
||||
| ^^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$i:ident`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:22:13
|
||||
--> $DIR/macro-follow.rs:23:13
|
||||
|
|
||||
LL | ($p:pat $i:ident) => {};
|
||||
| ^^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$t:tt`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:23:13
|
||||
--> $DIR/macro-follow.rs:24:13
|
||||
|
|
||||
LL | ($p:pat $t:tt) => {};
|
||||
| ^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$i:item`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:24:13
|
||||
--> $DIR/macro-follow.rs:25:13
|
||||
|
|
||||
LL | ($p:pat $i:item) => {};
|
||||
| ^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$p:pat` is followed by `$m:meta`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-follow.rs:25:13
|
||||
--> $DIR/macro-follow.rs:26:13
|
||||
|
|
||||
LL | ($p:pat $m:meta) => {};
|
||||
| ^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$e:expr` is followed by `(`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:29:14
|
||||
--> $DIR/macro-follow.rs:30:14
|
||||
|
|
||||
LL | ($e:expr ()) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -143,7 +143,7 @@ LL | ($e:expr ()) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `[`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:30:14
|
||||
--> $DIR/macro-follow.rs:31:14
|
||||
|
|
||||
LL | ($e:expr []) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -151,7 +151,7 @@ LL | ($e:expr []) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `{`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:31:14
|
||||
--> $DIR/macro-follow.rs:32:14
|
||||
|
|
||||
LL | ($e:expr {}) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -159,7 +159,7 @@ LL | ($e:expr {}) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `=`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:32:14
|
||||
--> $DIR/macro-follow.rs:33:14
|
||||
|
|
||||
LL | ($e:expr =) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -167,7 +167,7 @@ LL | ($e:expr =) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `|`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:33:14
|
||||
--> $DIR/macro-follow.rs:34:14
|
||||
|
|
||||
LL | ($e:expr |) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -175,7 +175,7 @@ LL | ($e:expr |) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `:`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:34:14
|
||||
--> $DIR/macro-follow.rs:35:14
|
||||
|
|
||||
LL | ($e:expr :) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -183,7 +183,7 @@ LL | ($e:expr :) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `>`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:35:14
|
||||
--> $DIR/macro-follow.rs:36:14
|
||||
|
|
||||
LL | ($e:expr >) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -191,7 +191,7 @@ LL | ($e:expr >) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:36:14
|
||||
--> $DIR/macro-follow.rs:37:14
|
||||
|
|
||||
LL | ($e:expr +) => {};
|
||||
| ^ not allowed after `expr` fragments
|
||||
@@ -199,7 +199,7 @@ LL | ($e:expr +) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `ident`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:37:14
|
||||
--> $DIR/macro-follow.rs:38:14
|
||||
|
|
||||
LL | ($e:expr ident) => {};
|
||||
| ^^^^^ not allowed after `expr` fragments
|
||||
@@ -207,7 +207,7 @@ LL | ($e:expr ident) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `if`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:38:14
|
||||
--> $DIR/macro-follow.rs:39:14
|
||||
|
|
||||
LL | ($e:expr if) => {};
|
||||
| ^^ not allowed after `expr` fragments
|
||||
@@ -215,7 +215,7 @@ LL | ($e:expr if) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `in`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:39:14
|
||||
--> $DIR/macro-follow.rs:40:14
|
||||
|
|
||||
LL | ($e:expr in) => {};
|
||||
| ^^ not allowed after `expr` fragments
|
||||
@@ -223,7 +223,7 @@ LL | ($e:expr in) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$p:pat`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:40:14
|
||||
--> $DIR/macro-follow.rs:41:14
|
||||
|
|
||||
LL | ($e:expr $p:pat) => {};
|
||||
| ^^^^^^ not allowed after `expr` fragments
|
||||
@@ -231,7 +231,7 @@ LL | ($e:expr $p:pat) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$f:expr`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:41:14
|
||||
--> $DIR/macro-follow.rs:42:14
|
||||
|
|
||||
LL | ($e:expr $f:expr) => {};
|
||||
| ^^^^^^^ not allowed after `expr` fragments
|
||||
@@ -239,7 +239,7 @@ LL | ($e:expr $f:expr) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$t:ty`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:42:14
|
||||
--> $DIR/macro-follow.rs:43:14
|
||||
|
|
||||
LL | ($e:expr $t:ty) => {};
|
||||
| ^^^^^ not allowed after `expr` fragments
|
||||
@@ -247,7 +247,7 @@ LL | ($e:expr $t:ty) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$s:stmt`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:43:14
|
||||
--> $DIR/macro-follow.rs:44:14
|
||||
|
|
||||
LL | ($e:expr $s:stmt) => {};
|
||||
| ^^^^^^^ not allowed after `expr` fragments
|
||||
@@ -255,7 +255,7 @@ LL | ($e:expr $s:stmt) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$p:path`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:44:14
|
||||
--> $DIR/macro-follow.rs:45:14
|
||||
|
|
||||
LL | ($e:expr $p:path) => {};
|
||||
| ^^^^^^^ not allowed after `expr` fragments
|
||||
@@ -263,7 +263,7 @@ LL | ($e:expr $p:path) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$b:block`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:45:14
|
||||
--> $DIR/macro-follow.rs:46:14
|
||||
|
|
||||
LL | ($e:expr $b:block) => {};
|
||||
| ^^^^^^^^ not allowed after `expr` fragments
|
||||
@@ -271,7 +271,7 @@ LL | ($e:expr $b:block) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$i:ident`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:46:14
|
||||
--> $DIR/macro-follow.rs:47:14
|
||||
|
|
||||
LL | ($e:expr $i:ident) => {};
|
||||
| ^^^^^^^^ not allowed after `expr` fragments
|
||||
@@ -279,7 +279,7 @@ LL | ($e:expr $i:ident) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$t:tt`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:47:14
|
||||
--> $DIR/macro-follow.rs:48:14
|
||||
|
|
||||
LL | ($e:expr $t:tt) => {};
|
||||
| ^^^^^ not allowed after `expr` fragments
|
||||
@@ -287,7 +287,7 @@ LL | ($e:expr $t:tt) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$i:item`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:48:14
|
||||
--> $DIR/macro-follow.rs:49:14
|
||||
|
|
||||
LL | ($e:expr $i:item) => {};
|
||||
| ^^^^^^^ not allowed after `expr` fragments
|
||||
@@ -295,15 +295,23 @@ LL | ($e:expr $i:item) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$m:meta`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:49:14
|
||||
--> $DIR/macro-follow.rs:50:14
|
||||
|
|
||||
LL | ($e:expr $m:meta) => {};
|
||||
| ^^^^^^^ not allowed after `expr` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$e:expr` is followed by `$g:guard`, which is not allowed for `expr` fragments
|
||||
--> $DIR/macro-follow.rs:51:14
|
||||
|
|
||||
LL | ($e:expr $g:guard) => {};
|
||||
| ^^^^^^^^ not allowed after `expr` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$t:ty` is followed by `(`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:54:12
|
||||
--> $DIR/macro-follow.rs:56:12
|
||||
|
|
||||
LL | ($t:ty ()) => {};
|
||||
| ^ not allowed after `ty` fragments
|
||||
@@ -311,7 +319,7 @@ LL | ($t:ty ()) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `+`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:56:12
|
||||
--> $DIR/macro-follow.rs:58:12
|
||||
|
|
||||
LL | ($t:ty +) => {};
|
||||
| ^ not allowed after `ty` fragments
|
||||
@@ -319,7 +327,7 @@ LL | ($t:ty +) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `ident`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:57:12
|
||||
--> $DIR/macro-follow.rs:59:12
|
||||
|
|
||||
LL | ($t:ty ident) => {};
|
||||
| ^^^^^ not allowed after `ty` fragments
|
||||
@@ -327,7 +335,7 @@ LL | ($t:ty ident) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `if`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:58:12
|
||||
--> $DIR/macro-follow.rs:60:12
|
||||
|
|
||||
LL | ($t:ty if) => {};
|
||||
| ^^ not allowed after `ty` fragments
|
||||
@@ -335,7 +343,7 @@ LL | ($t:ty if) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$p:pat`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:59:12
|
||||
--> $DIR/macro-follow.rs:61:12
|
||||
|
|
||||
LL | ($t:ty $p:pat) => {};
|
||||
| ^^^^^^ not allowed after `ty` fragments
|
||||
@@ -343,7 +351,7 @@ LL | ($t:ty $p:pat) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$e:expr`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:60:12
|
||||
--> $DIR/macro-follow.rs:62:12
|
||||
|
|
||||
LL | ($t:ty $e:expr) => {};
|
||||
| ^^^^^^^ not allowed after `ty` fragments
|
||||
@@ -351,7 +359,7 @@ LL | ($t:ty $e:expr) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$r:ty`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:61:12
|
||||
--> $DIR/macro-follow.rs:63:12
|
||||
|
|
||||
LL | ($t:ty $r:ty) => {};
|
||||
| ^^^^^ not allowed after `ty` fragments
|
||||
@@ -359,7 +367,7 @@ LL | ($t:ty $r:ty) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$s:stmt`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:62:12
|
||||
--> $DIR/macro-follow.rs:64:12
|
||||
|
|
||||
LL | ($t:ty $s:stmt) => {};
|
||||
| ^^^^^^^ not allowed after `ty` fragments
|
||||
@@ -367,7 +375,7 @@ LL | ($t:ty $s:stmt) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$p:path`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:63:12
|
||||
--> $DIR/macro-follow.rs:65:12
|
||||
|
|
||||
LL | ($t:ty $p:path) => {};
|
||||
| ^^^^^^^ not allowed after `ty` fragments
|
||||
@@ -375,7 +383,7 @@ LL | ($t:ty $p:path) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$i:ident`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:65:12
|
||||
--> $DIR/macro-follow.rs:67:12
|
||||
|
|
||||
LL | ($t:ty $i:ident) => {};
|
||||
| ^^^^^^^^ not allowed after `ty` fragments
|
||||
@@ -383,7 +391,7 @@ LL | ($t:ty $i:ident) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$r:tt`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:66:12
|
||||
--> $DIR/macro-follow.rs:68:12
|
||||
|
|
||||
LL | ($t:ty $r:tt) => {};
|
||||
| ^^^^^ not allowed after `ty` fragments
|
||||
@@ -391,7 +399,7 @@ LL | ($t:ty $r:tt) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$i:item`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:67:12
|
||||
--> $DIR/macro-follow.rs:69:12
|
||||
|
|
||||
LL | ($t:ty $i:item) => {};
|
||||
| ^^^^^^^ not allowed after `ty` fragments
|
||||
@@ -399,15 +407,23 @@ LL | ($t:ty $i:item) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$m:meta`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:68:12
|
||||
--> $DIR/macro-follow.rs:70:12
|
||||
|
|
||||
LL | ($t:ty $m:meta) => {};
|
||||
| ^^^^^^^ not allowed after `ty` fragments
|
||||
|
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$t:ty` is followed by `$g:guard`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-follow.rs:71:12
|
||||
|
|
||||
LL | ($t:ty $g:guard) => {};
|
||||
| ^^^^^^^^ not allowed after `ty` fragments
|
||||
|
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$s:stmt` is followed by `(`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:72:14
|
||||
--> $DIR/macro-follow.rs:75:14
|
||||
|
|
||||
LL | ($s:stmt ()) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -415,7 +431,7 @@ LL | ($s:stmt ()) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `[`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:73:14
|
||||
--> $DIR/macro-follow.rs:76:14
|
||||
|
|
||||
LL | ($s:stmt []) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -423,7 +439,7 @@ LL | ($s:stmt []) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `{`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:74:14
|
||||
--> $DIR/macro-follow.rs:77:14
|
||||
|
|
||||
LL | ($s:stmt {}) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -431,7 +447,7 @@ LL | ($s:stmt {}) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `=`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:75:14
|
||||
--> $DIR/macro-follow.rs:78:14
|
||||
|
|
||||
LL | ($s:stmt =) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -439,7 +455,7 @@ LL | ($s:stmt =) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `|`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:76:14
|
||||
--> $DIR/macro-follow.rs:79:14
|
||||
|
|
||||
LL | ($s:stmt |) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -447,7 +463,7 @@ LL | ($s:stmt |) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `:`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:77:14
|
||||
--> $DIR/macro-follow.rs:80:14
|
||||
|
|
||||
LL | ($s:stmt :) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -455,7 +471,7 @@ LL | ($s:stmt :) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `>`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:78:14
|
||||
--> $DIR/macro-follow.rs:81:14
|
||||
|
|
||||
LL | ($s:stmt >) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -463,7 +479,7 @@ LL | ($s:stmt >) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `+`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:79:14
|
||||
--> $DIR/macro-follow.rs:82:14
|
||||
|
|
||||
LL | ($s:stmt +) => {};
|
||||
| ^ not allowed after `stmt` fragments
|
||||
@@ -471,7 +487,7 @@ LL | ($s:stmt +) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `ident`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:80:14
|
||||
--> $DIR/macro-follow.rs:83:14
|
||||
|
|
||||
LL | ($s:stmt ident) => {};
|
||||
| ^^^^^ not allowed after `stmt` fragments
|
||||
@@ -479,7 +495,7 @@ LL | ($s:stmt ident) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `if`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:81:14
|
||||
--> $DIR/macro-follow.rs:84:14
|
||||
|
|
||||
LL | ($s:stmt if) => {};
|
||||
| ^^ not allowed after `stmt` fragments
|
||||
@@ -487,7 +503,7 @@ LL | ($s:stmt if) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `in`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:82:14
|
||||
--> $DIR/macro-follow.rs:85:14
|
||||
|
|
||||
LL | ($s:stmt in) => {};
|
||||
| ^^ not allowed after `stmt` fragments
|
||||
@@ -495,7 +511,7 @@ LL | ($s:stmt in) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$p:pat`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:83:14
|
||||
--> $DIR/macro-follow.rs:86:14
|
||||
|
|
||||
LL | ($s:stmt $p:pat) => {};
|
||||
| ^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -503,7 +519,7 @@ LL | ($s:stmt $p:pat) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$e:expr`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:84:14
|
||||
--> $DIR/macro-follow.rs:87:14
|
||||
|
|
||||
LL | ($s:stmt $e:expr) => {};
|
||||
| ^^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -511,7 +527,7 @@ LL | ($s:stmt $e:expr) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$t:ty`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:85:14
|
||||
--> $DIR/macro-follow.rs:88:14
|
||||
|
|
||||
LL | ($s:stmt $t:ty) => {};
|
||||
| ^^^^^ not allowed after `stmt` fragments
|
||||
@@ -519,7 +535,7 @@ LL | ($s:stmt $t:ty) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$t:stmt`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:86:14
|
||||
--> $DIR/macro-follow.rs:89:14
|
||||
|
|
||||
LL | ($s:stmt $t:stmt) => {};
|
||||
| ^^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -527,7 +543,7 @@ LL | ($s:stmt $t:stmt) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$p:path`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:87:14
|
||||
--> $DIR/macro-follow.rs:90:14
|
||||
|
|
||||
LL | ($s:stmt $p:path) => {};
|
||||
| ^^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -535,7 +551,7 @@ LL | ($s:stmt $p:path) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$b:block`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:88:14
|
||||
--> $DIR/macro-follow.rs:91:14
|
||||
|
|
||||
LL | ($s:stmt $b:block) => {};
|
||||
| ^^^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -543,7 +559,7 @@ LL | ($s:stmt $b:block) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$i:ident`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:89:14
|
||||
--> $DIR/macro-follow.rs:92:14
|
||||
|
|
||||
LL | ($s:stmt $i:ident) => {};
|
||||
| ^^^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -551,7 +567,7 @@ LL | ($s:stmt $i:ident) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$t:tt`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:90:14
|
||||
--> $DIR/macro-follow.rs:93:14
|
||||
|
|
||||
LL | ($s:stmt $t:tt) => {};
|
||||
| ^^^^^ not allowed after `stmt` fragments
|
||||
@@ -559,7 +575,7 @@ LL | ($s:stmt $t:tt) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$i:item`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:91:14
|
||||
--> $DIR/macro-follow.rs:94:14
|
||||
|
|
||||
LL | ($s:stmt $i:item) => {};
|
||||
| ^^^^^^^ not allowed after `stmt` fragments
|
||||
@@ -567,23 +583,31 @@ LL | ($s:stmt $i:item) => {};
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$s:stmt` is followed by `$m:meta`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:92:14
|
||||
--> $DIR/macro-follow.rs:95:14
|
||||
|
|
||||
LL | ($s:stmt $m:meta) => {};
|
||||
| ^^^^^^^ not allowed after `stmt` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$p:path` is followed by `(`, which is not allowed for `path` fragments
|
||||
error: `$s:stmt` is followed by `$g:guard`, which is not allowed for `stmt` fragments
|
||||
--> $DIR/macro-follow.rs:96:14
|
||||
|
|
||||
LL | ($s:stmt $g:guard) => {};
|
||||
| ^^^^^^^^ not allowed after `stmt` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,` or `;`
|
||||
|
||||
error: `$p:path` is followed by `(`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:100:14
|
||||
|
|
||||
LL | ($p:path ()) => {};
|
||||
| ^ not allowed after `path` fragments
|
||||
|
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `+`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:98:14
|
||||
--> $DIR/macro-follow.rs:102:14
|
||||
|
|
||||
LL | ($p:path +) => {};
|
||||
| ^ not allowed after `path` fragments
|
||||
@@ -591,7 +615,7 @@ LL | ($p:path +) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `ident`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:99:14
|
||||
--> $DIR/macro-follow.rs:103:14
|
||||
|
|
||||
LL | ($p:path ident) => {};
|
||||
| ^^^^^ not allowed after `path` fragments
|
||||
@@ -599,7 +623,7 @@ LL | ($p:path ident) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `if`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:100:14
|
||||
--> $DIR/macro-follow.rs:104:14
|
||||
|
|
||||
LL | ($p:path if) => {};
|
||||
| ^^ not allowed after `path` fragments
|
||||
@@ -607,7 +631,7 @@ LL | ($p:path if) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$q:pat`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:101:14
|
||||
--> $DIR/macro-follow.rs:105:14
|
||||
|
|
||||
LL | ($p:path $q:pat) => {};
|
||||
| ^^^^^^ not allowed after `path` fragments
|
||||
@@ -615,7 +639,7 @@ LL | ($p:path $q:pat) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$e:expr`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:102:14
|
||||
--> $DIR/macro-follow.rs:106:14
|
||||
|
|
||||
LL | ($p:path $e:expr) => {};
|
||||
| ^^^^^^^ not allowed after `path` fragments
|
||||
@@ -623,7 +647,7 @@ LL | ($p:path $e:expr) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$t:ty`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:103:14
|
||||
--> $DIR/macro-follow.rs:107:14
|
||||
|
|
||||
LL | ($p:path $t:ty) => {};
|
||||
| ^^^^^ not allowed after `path` fragments
|
||||
@@ -631,7 +655,7 @@ LL | ($p:path $t:ty) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$s:stmt`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:104:14
|
||||
--> $DIR/macro-follow.rs:108:14
|
||||
|
|
||||
LL | ($p:path $s:stmt) => {};
|
||||
| ^^^^^^^ not allowed after `path` fragments
|
||||
@@ -639,7 +663,7 @@ LL | ($p:path $s:stmt) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$q:path`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:105:14
|
||||
--> $DIR/macro-follow.rs:109:14
|
||||
|
|
||||
LL | ($p:path $q:path) => {};
|
||||
| ^^^^^^^ not allowed after `path` fragments
|
||||
@@ -647,7 +671,7 @@ LL | ($p:path $q:path) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$i:ident`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:107:14
|
||||
--> $DIR/macro-follow.rs:111:14
|
||||
|
|
||||
LL | ($p:path $i:ident) => {};
|
||||
| ^^^^^^^^ not allowed after `path` fragments
|
||||
@@ -655,7 +679,7 @@ LL | ($p:path $i:ident) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$t:tt`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:108:14
|
||||
--> $DIR/macro-follow.rs:112:14
|
||||
|
|
||||
LL | ($p:path $t:tt) => {};
|
||||
| ^^^^^ not allowed after `path` fragments
|
||||
@@ -663,7 +687,7 @@ LL | ($p:path $t:tt) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$i:item`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:109:14
|
||||
--> $DIR/macro-follow.rs:113:14
|
||||
|
|
||||
LL | ($p:path $i:item) => {};
|
||||
| ^^^^^^^ not allowed after `path` fragments
|
||||
@@ -671,12 +695,20 @@ LL | ($p:path $i:item) => {};
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: `$p:path` is followed by `$m:meta`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:110:14
|
||||
--> $DIR/macro-follow.rs:114:14
|
||||
|
|
||||
LL | ($p:path $m:meta) => {};
|
||||
| ^^^^^^^ not allowed after `path` fragments
|
||||
|
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: aborting due to 85 previous errors
|
||||
error: `$p:path` is followed by `$g:guard`, which is not allowed for `path` fragments
|
||||
--> $DIR/macro-follow.rs:115:14
|
||||
|
|
||||
LL | ($p:path $g:guard) => {};
|
||||
| ^^^^^^^^ not allowed after `path` fragments
|
||||
|
|
||||
= note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
|
||||
|
||||
error: aborting due to 89 previous errors
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#![feature(macro_guard_matcher)]
|
||||
|
||||
fn main() {
|
||||
macro_rules! m {
|
||||
($x:guard) => {};
|
||||
}
|
||||
|
||||
// Accepts
|
||||
m!(if true);
|
||||
m!(if let Some(x) = Some(1));
|
||||
m!(if let Some(x) = Some(1) && x == 1);
|
||||
m!(if let Some(x) = Some(Some(1)) && let Some(1) = x);
|
||||
m!(if let Some(x) = Some(Some(1)) && let Some(y) = x && y == 1);
|
||||
|
||||
// Rejects
|
||||
m!(let Some(x) = Some(1)); //~ERROR no rules expected keyword `let`
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
error: no rules expected keyword `let`
|
||||
--> $DIR/macro-guard-matcher.rs:16:8
|
||||
|
|
||||
LL | macro_rules! m {
|
||||
| -------------- when calling this macro
|
||||
...
|
||||
LL | m!(let Some(x) = Some(1));
|
||||
| ^^^ no rules expected this token in macro call
|
||||
|
|
||||
note: while trying to match meta-variable `$x:guard`
|
||||
--> $DIR/macro-guard-matcher.rs:5:10
|
||||
|
|
||||
LL | ($x:guard) => {};
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -20,7 +20,7 @@ error: `$pa:pat` is followed by `>`, which is not allowed for `pat` fragments
|
||||
LL | ($pa:pat >) => ();
|
||||
| ^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$pa:pat` is followed by `$pb:pat`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-input-future-proofing.rs:14:14
|
||||
@@ -28,7 +28,7 @@ error: `$pa:pat` is followed by `$pb:pat`, which is not allowed for `pat` fragme
|
||||
LL | ($pa:pat $pb:pat $ty:ty ,) => ();
|
||||
| ^^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$pb:pat` is followed by `$ty:ty`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-input-future-proofing.rs:14:22
|
||||
@@ -36,7 +36,7 @@ error: `$pb:pat` is followed by `$ty:ty`, which is not allowed for `pat` fragmen
|
||||
LL | ($pa:pat $pb:pat $ty:ty ,) => ();
|
||||
| ^^^^^^ not allowed after `pat` fragments
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
|
||||
|
||||
error: `$ty:ty` is followed by `-`, which is not allowed for `ty` fragments
|
||||
--> $DIR/macro-input-future-proofing.rs:17:17
|
||||
|
||||
@@ -6,7 +6,7 @@ LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
|
||||
| |
|
||||
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
|
||||
|
||||
error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32
|
||||
@@ -16,7 +16,7 @@ LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
|
||||
| |
|
||||
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
|
||||
|
||||
error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36
|
||||
@@ -26,7 +26,7 @@ LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
|
||||
| |
|
||||
| help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
|
||||
| |
|
||||
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
|
||||
|
||||
error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-pat2021-pattern-followed-by-or.rs:7:28
|
||||
@@ -16,7 +16,7 @@ LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
|
||||
| |
|
||||
| help: try a `pat_param` fragment specifier instead: `$x:pat_param`
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
|
||||
|
||||
error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
|
||||
--> $DIR/macro-pat2021-pattern-followed-by-or.rs:9:35
|
||||
@@ -26,7 +26,7 @@ LL | ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => {
|
||||
| |
|
||||
| help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
|
||||
|
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if` or `in`
|
||||
= note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(yeet_expr)]
|
||||
#![feature(macro_guard_matcher)]
|
||||
#![deny(unused_macros)]
|
||||
|
||||
// These macros force the use of AST pretty-printing by converting the input to
|
||||
@@ -27,6 +28,7 @@
|
||||
macro_rules! stmt { ($stmt:stmt) => { stringify!($stmt) }; }
|
||||
macro_rules! ty { ($ty:ty) => { stringify!($ty) }; }
|
||||
macro_rules! vis { ($vis:vis) => { stringify!($vis) }; }
|
||||
macro_rules! guard { ($guard:guard) => { stringify!($guard) }; }
|
||||
|
||||
macro_rules! c1 {
|
||||
($frag:ident, [$($tt:tt)*], $s:literal) => {
|
||||
@@ -792,6 +794,21 @@ fn test_vis() {
|
||||
// Attributes are not allowed on visibilities.
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_guard() {
|
||||
c1!(guard, [ if true ], "if true");
|
||||
c1!(guard, [ if let Some(x) = Some(1) ], "if let Some(x) = Some(1)");
|
||||
c1!(guard, [ if let Some(x) = Some(1) && x == 1 ], "if let Some(x) = Some(1) && x == 1");
|
||||
c1!(guard,
|
||||
[ if let Some(x) = Some(Some(1)) && let Some(1) = x ],
|
||||
"if let Some(x) = Some(Some(1)) && let Some(1) = x"
|
||||
);
|
||||
c1!(guard,
|
||||
[ if let Some(x) = Some(Some(1)) && let Some(y) = x && y == 1 ],
|
||||
"if let Some(x) = Some(Some(1)) && let Some(y) = x && y == 1"
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! p {
|
||||
([$($tt:tt)*], $s:literal) => {
|
||||
assert_eq!(stringify!($($tt)*), $s);
|
||||
|
||||
Reference in New Issue
Block a user