Skip to content

Commit c4766cf

Browse files
committed
[RFC-2011] Expand matches!
1 parent fdd0301 commit c4766cf

File tree

21 files changed

+251
-88
lines changed

21 files changed

+251
-88
lines changed

compiler/rustc_ast/src/ast.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,7 @@ impl Expr {
12911291
ExprKind::Struct(..) => ExprPrecedence::Struct,
12921292
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
12931293
ExprKind::Paren(..) => ExprPrecedence::Paren,
1294+
ExprKind::Matches(..) => ExprPrecedence::Matches,
12941295
ExprKind::Try(..) => ExprPrecedence::Try,
12951296
ExprKind::Yield(..) => ExprPrecedence::Yield,
12961297
ExprKind::Yeet(..) => ExprPrecedence::Yeet,
@@ -1488,6 +1489,9 @@ pub enum ExprKind {
14881489
/// Output of the `offset_of!()` macro.
14891490
OffsetOf(P<Ty>, P<[Ident]>),
14901491

1492+
/// Output of the `matches!()` macro.
1493+
Matches(P<Expr>, P<Arm>, P<Arm>),
1494+
14911495
/// A macro invocation; pre-expansion.
14921496
MacCall(P<MacCall>),
14931497

compiler/rustc_ast/src/mut_visit.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ pub trait MutVisitor: Sized {
148148
noop_visit_anon_const(c, self);
149149
}
150150

151+
fn visit_arm(&mut self, arm: &mut P<Arm>) {
152+
noop_visit_arm(arm, self)
153+
}
154+
151155
fn visit_expr(&mut self, e: &mut P<Expr>) {
152156
noop_visit_expr(e, self);
153157
}
@@ -443,13 +447,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
443447
}
444448

445449
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
446-
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
447-
visit_attrs(attrs, vis);
448-
vis.visit_id(id);
449-
vis.visit_pat(pat);
450-
visit_opt(guard, |guard| vis.visit_expr(guard));
451-
vis.visit_expr(body);
452-
vis.visit_span(span);
450+
noop_visit_arm(&mut arm, vis);
453451
smallvec![arm]
454452
}
455453

@@ -695,6 +693,16 @@ pub fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
695693
}
696694
}
697695

696+
fn noop_visit_arm<T: MutVisitor>(arm: &mut Arm, vis: &mut T) {
697+
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm;
698+
visit_attrs(attrs, vis);
699+
vis.visit_id(id);
700+
vis.visit_pat(pat);
701+
visit_opt(guard, |guard| vis.visit_expr(guard));
702+
vis.visit_expr(body);
703+
vis.visit_span(span);
704+
}
705+
698706
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
699707
pub fn visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
700708
match tt {
@@ -1334,6 +1342,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
13341342
vis.visit_expr(f);
13351343
visit_thin_exprs(args, vis);
13361344
}
1345+
ExprKind::Matches(expr, true_arm, false_arm) => {
1346+
vis.visit_expr(expr);
1347+
vis.visit_arm(true_arm);
1348+
vis.visit_arm(false_arm);
1349+
}
13371350
ExprKind::MethodCall(box MethodCall {
13381351
seg: PathSegment { ident, id, args: seg_args },
13391352
receiver,

compiler/rustc_ast/src/util/parser.rs

+2
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ pub enum ExprPrecedence {
267267
InlineAsm,
268268
OffsetOf,
269269
Mac,
270+
Matches,
270271
FormatArgs,
271272

272273
Array,
@@ -329,6 +330,7 @@ impl ExprPrecedence {
329330
| ExprPrecedence::Field
330331
| ExprPrecedence::Index
331332
| ExprPrecedence::Try
333+
| ExprPrecedence::Matches
332334
| ExprPrecedence::InlineAsm
333335
| ExprPrecedence::Mac
334336
| ExprPrecedence::FormatArgs

compiler/rustc_ast/src/visit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
803803
visitor.visit_expr(callee_expression);
804804
walk_list!(visitor, visit_expr, arguments);
805805
}
806+
ExprKind::Matches(expr, true_arm, false_arm) => {
807+
visitor.visit_expr(expr);
808+
visitor.visit_arm(true_arm);
809+
visitor.visit_arm(false_arm);
810+
}
806811
ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => {
807812
visitor.visit_path_segment(seg);
808813
visitor.visit_expr(receiver);

compiler/rustc_ast_lowering/src/expr.rs

+7
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
274274
ExprKind::InlineAsm(asm) => {
275275
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
276276
}
277+
ExprKind::Matches(expr, true_arm, false_arm) => hir::ExprKind::Match(
278+
self.lower_expr(expr),
279+
self.arena.alloc_from_iter(
280+
[true_arm, false_arm].iter().map(|elem| self.lower_arm(elem)),
281+
),
282+
hir::MatchSource::Normal,
283+
),
277284
ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
278285
ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(
279286
self.lower_ty(

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+14
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,20 @@ impl<'a> State<'a> {
555555
self.end();
556556
self.pclose();
557557
}
558+
ast::ExprKind::Matches(expr, true_arm, _) => {
559+
self.word("builtin # matches");
560+
self.popen();
561+
self.rbox(0, Inconsistent);
562+
self.print_expr(expr);
563+
self.word(", ");
564+
self.print_pat(&true_arm.pat);
565+
if let Some(elem) = &true_arm.guard {
566+
self.word("if");
567+
self.print_expr(elem);
568+
}
569+
self.pclose();
570+
self.end();
571+
}
558572
ast::ExprKind::OffsetOf(container, fields) => {
559573
self.word("builtin # offset_of");
560574
self.popen();

compiler/rustc_builtin_macros/src/assert.rs

+23-21
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,13 @@ pub fn expand_assert<'cx>(
3131
// context to pick up whichever is currently in scope.
3232
let call_site_span = cx.with_call_site_ctxt(span);
3333

34-
let panic_path = || {
35-
if use_panic_2021(span) {
36-
// On edition 2021, we always call `$crate::panic::panic_2021!()`.
37-
Path {
38-
span: call_site_span,
39-
segments: cx
40-
.std_path(&[sym::panic, sym::panic_2021])
41-
.into_iter()
42-
.map(|ident| PathSegment::from_ident(ident))
43-
.collect(),
44-
tokens: None,
45-
}
46-
} else {
47-
// Before edition 2021, we call `panic!()` unqualified,
48-
// such that it calls either `std::panic!()` or `core::panic!()`.
49-
Path::from_ident(Ident::new(sym::panic, call_site_span))
50-
}
51-
};
52-
5334
// Simply uses the user provided message instead of generating custom outputs
5435
let expr = if let Some(tokens) = custom_message {
36+
let panic_path = panic_path(call_site_span, cx, span);
5537
let then = cx.expr(
5638
call_site_span,
5739
ExprKind::MacCall(P(MacCall {
58-
path: panic_path(),
40+
path: panic_path,
5941
args: P(DelimArgs {
6042
dspan: DelimSpan::from_single(call_site_span),
6143
delim: MacDelimiter::Parenthesis,
@@ -69,7 +51,8 @@ pub fn expand_assert<'cx>(
6951
//
7052
// FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
7153
else if let Some(features) = cx.ecfg.features && features.generic_assert {
72-
context::Context::new(cx, call_site_span).build(cond_expr, panic_path())
54+
let panic_path = panic_path(call_site_span, cx, span);
55+
context::Context::new(cx, call_site_span).build(cond_expr, panic_path)
7356
}
7457
// If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
7558
// string
@@ -110,6 +93,25 @@ fn expr_if_not(
11093
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
11194
}
11295

96+
fn panic_path(call_site_span: Span, cx: &mut ExtCtxt<'_>, span: Span) -> Path {
97+
if use_panic_2021(span) {
98+
// On edition 2021, we always call `$crate::panic::panic_2021!()`.
99+
Path {
100+
span: call_site_span,
101+
segments: cx
102+
.std_path(&[sym::panic, sym::panic_2021])
103+
.into_iter()
104+
.map(|ident| PathSegment::from_ident(ident))
105+
.collect(),
106+
tokens: None,
107+
}
108+
} else {
109+
// Before edition 2021, we call `panic!()` unqualified,
110+
// such that it calls either `std::panic!()` or `core::panic!()`.
111+
Path::from_ident(Ident::new(sym::panic, call_site_span))
112+
}
113+
}
114+
113115
fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
114116
let mut parser = cx.new_parser_from_tts(stream);
115117

compiler/rustc_builtin_macros/src/assert/context.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub(super) struct Context<'cx, 'a> {
2222
best_case_captures: Vec<Stmt>,
2323
// Top-level `let captureN = Capture::new()` statements
2424
capture_decls: Vec<Capture>,
25-
cx: &'cx ExtCtxt<'a>,
25+
cx: &'cx mut ExtCtxt<'a>,
2626
// Formatting string used for debugging
2727
fmt_string: String,
2828
// If the current expression being visited consumes itself. Used to construct
@@ -41,7 +41,7 @@ pub(super) struct Context<'cx, 'a> {
4141
}
4242

4343
impl<'cx, 'a> Context<'cx, 'a> {
44-
pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self {
44+
pub(super) fn new(cx: &'cx mut ExtCtxt<'a>, span: Span) -> Self {
4545
Self {
4646
best_case_captures: <_>::default(),
4747
capture_decls: <_>::default(),
@@ -85,8 +85,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
8585

8686
let mut assert_then_stmts = ThinVec::with_capacity(2);
8787
assert_then_stmts.extend(best_case_captures);
88-
assert_then_stmts.push(self.cx.stmt_expr(panic));
89-
let assert_then = self.cx.block(span, assert_then_stmts);
88+
assert_then_stmts.push(cx.stmt_expr(panic));
89+
let assert_then = cx.block(span, assert_then_stmts);
9090

9191
let mut stmts = ThinVec::with_capacity(4);
9292
stmts.push(initial_imports);
@@ -237,6 +237,9 @@ impl<'cx, 'a> Context<'cx, 'a> {
237237
self.manage_cond_expr(prefix);
238238
self.manage_cond_expr(suffix);
239239
}
240+
ExprKind::Matches(expr, _, _) => {
241+
self.manage_cond_expr(expr);
242+
}
240243
ExprKind::MethodCall(call) => {
241244
for arg in &mut call.args {
242245
self.manage_cond_expr(arg);
@@ -295,17 +298,17 @@ impl<'cx, 'a> Context<'cx, 'a> {
295298
| ExprKind::Continue(_)
296299
| ExprKind::Err
297300
| ExprKind::Field(_, _)
298-
| ExprKind::FormatArgs(_)
299301
| ExprKind::ForLoop(_, _, _, _)
302+
| ExprKind::FormatArgs(_)
300303
| ExprKind::If(_, _, _)
301304
| ExprKind::IncludedBytes(..)
302305
| ExprKind::InlineAsm(_)
303-
| ExprKind::OffsetOf(_, _)
304306
| ExprKind::Let(_, _, _)
305307
| ExprKind::Lit(_)
306308
| ExprKind::Loop(_, _, _)
307309
| ExprKind::MacCall(_)
308310
| ExprKind::Match(_, _)
311+
| ExprKind::OffsetOf(_, _)
309312
| ExprKind::Path(_, _)
310313
| ExprKind::Ret(_)
311314
| ExprKind::Try(_)

0 commit comments

Comments
 (0)