diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 43b429f6947ec..9562dc7695227 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1291,6 +1291,7 @@ impl Expr { ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Paren(..) => ExprPrecedence::Paren, + ExprKind::Matches(..) => ExprPrecedence::Matches, ExprKind::Try(..) => ExprPrecedence::Try, ExprKind::Yield(..) => ExprPrecedence::Yield, ExprKind::Yeet(..) => ExprPrecedence::Yeet, @@ -1488,6 +1489,9 @@ pub enum ExprKind { /// Output of the `offset_of!()` macro. OffsetOf(P, P<[Ident]>), + /// Output of the `matches!()` macro. + Matches(P, P, P), + /// A macro invocation; pre-expansion. MacCall(P), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 66b94d12a32c6..fa5d8d61cc29d 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -148,6 +148,10 @@ pub trait MutVisitor: Sized { noop_visit_anon_const(c, self); } + fn visit_arm(&mut self, arm: &mut P) { + noop_visit_arm(arm, self) + } + fn visit_expr(&mut self, e: &mut P) { noop_visit_expr(e, self); } @@ -443,13 +447,7 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { } pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> { - let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm; - visit_attrs(attrs, vis); - vis.visit_id(id); - vis.visit_pat(pat); - visit_opt(guard, |guard| vis.visit_expr(guard)); - vis.visit_expr(body); - vis.visit_span(span); + noop_visit_arm(&mut arm, vis); smallvec![arm] } @@ -695,6 +693,16 @@ pub fn visit_attr_tt(tt: &mut AttrTokenTree, vis: &mut T) { } } +fn noop_visit_arm(arm: &mut Arm, vis: &mut T) { + let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm; + visit_attrs(attrs, vis); + vis.visit_id(id); + vis.visit_pat(pat); + visit_opt(guard, |guard| vis.visit_expr(guard)); + vis.visit_expr(body); + vis.visit_span(span); +} + // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. pub fn visit_tt(tt: &mut TokenTree, vis: &mut T) { match tt { @@ -1334,6 +1342,11 @@ pub fn noop_visit_expr( vis.visit_expr(f); visit_thin_exprs(args, vis); } + ExprKind::Matches(expr, true_arm, false_arm) => { + vis.visit_expr(expr); + vis.visit_arm(true_arm); + vis.visit_arm(false_arm); + } ExprKind::MethodCall(box MethodCall { seg: PathSegment { ident, id, args: seg_args }, receiver, diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 35afd5423721d..dbdb97c3c2019 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -267,6 +267,7 @@ pub enum ExprPrecedence { InlineAsm, OffsetOf, Mac, + Matches, FormatArgs, Array, @@ -329,6 +330,7 @@ impl ExprPrecedence { | ExprPrecedence::Field | ExprPrecedence::Index | ExprPrecedence::Try + | ExprPrecedence::Matches | ExprPrecedence::InlineAsm | ExprPrecedence::Mac | ExprPrecedence::FormatArgs diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 275692ad5dda7..346c75a2d53ee 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -803,6 +803,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); } + ExprKind::Matches(expr, true_arm, false_arm) => { + visitor.visit_expr(expr); + visitor.visit_arm(true_arm); + visitor.visit_arm(false_arm); + } ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => { visitor.visit_path_segment(seg); visitor.visit_expr(receiver); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5e0ab80c6ac9f..240d58296a02a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -274,6 +274,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::InlineAsm(asm) => { hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm)) } + ExprKind::Matches(expr, true_arm, false_arm) => hir::ExprKind::Match( + self.lower_expr(expr), + self.arena.alloc_from_iter( + [true_arm, false_arm].iter().map(|elem| self.lower_arm(elem)), + ), + hir::MatchSource::Normal, + ), ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt), ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( self.lower_ty( diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 87c32ffce1214..8baf4b064dd07 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -555,6 +555,20 @@ impl<'a> State<'a> { self.end(); self.pclose(); } + ast::ExprKind::Matches(expr, true_arm, _) => { + self.word("builtin # matches"); + self.popen(); + self.rbox(0, Inconsistent); + self.print_expr(expr); + self.word(", "); + self.print_pat(&true_arm.pat); + if let Some(elem) = &true_arm.guard { + self.word("if"); + self.print_expr(elem); + } + self.pclose(); + self.end(); + } ast::ExprKind::OffsetOf(container, fields) => { self.word("builtin # offset_of"); self.popen(); diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index ab4ea9c8c2052..69fde4f320048 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -31,31 +31,13 @@ pub fn expand_assert<'cx>( // context to pick up whichever is currently in scope. let call_site_span = cx.with_call_site_ctxt(span); - let panic_path = || { - if use_panic_2021(span) { - // On edition 2021, we always call `$crate::panic::panic_2021!()`. - Path { - span: call_site_span, - segments: cx - .std_path(&[sym::panic, sym::panic_2021]) - .into_iter() - .map(|ident| PathSegment::from_ident(ident)) - .collect(), - tokens: None, - } - } else { - // Before edition 2021, we call `panic!()` unqualified, - // such that it calls either `std::panic!()` or `core::panic!()`. - Path::from_ident(Ident::new(sym::panic, call_site_span)) - } - }; - // Simply uses the user provided message instead of generating custom outputs let expr = if let Some(tokens) = custom_message { + let panic_path = panic_path(call_site_span, cx, span); let then = cx.expr( call_site_span, ExprKind::MacCall(P(MacCall { - path: panic_path(), + path: panic_path, args: P(DelimArgs { dspan: DelimSpan::from_single(call_site_span), delim: MacDelimiter::Parenthesis, @@ -69,7 +51,8 @@ pub fn expand_assert<'cx>( // // FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949 else if let Some(features) = cx.ecfg.features && features.generic_assert { - context::Context::new(cx, call_site_span).build(cond_expr, panic_path()) + let panic_path = panic_path(call_site_span, cx, span); + context::Context::new(cx, call_site_span).build(cond_expr, panic_path) } // If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..." // string @@ -110,6 +93,25 @@ fn expr_if_not( cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els) } +fn panic_path(call_site_span: Span, cx: &mut ExtCtxt<'_>, span: Span) -> Path { + if use_panic_2021(span) { + // On edition 2021, we always call `$crate::panic::panic_2021!()`. + Path { + span: call_site_span, + segments: cx + .std_path(&[sym::panic, sym::panic_2021]) + .into_iter() + .map(|ident| PathSegment::from_ident(ident)) + .collect(), + tokens: None, + } + } else { + // Before edition 2021, we call `panic!()` unqualified, + // such that it calls either `std::panic!()` or `core::panic!()`. + Path::from_ident(Ident::new(sym::panic, call_site_span)) + } +} + fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> { let mut parser = cx.new_parser_from_tts(stream); diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index ea830a0ce60df..39679e9a881c3 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -22,7 +22,7 @@ pub(super) struct Context<'cx, 'a> { best_case_captures: Vec, // Top-level `let captureN = Capture::new()` statements capture_decls: Vec, - cx: &'cx ExtCtxt<'a>, + cx: &'cx mut ExtCtxt<'a>, // Formatting string used for debugging fmt_string: String, // If the current expression being visited consumes itself. Used to construct @@ -41,7 +41,7 @@ pub(super) struct Context<'cx, 'a> { } impl<'cx, 'a> Context<'cx, 'a> { - pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self { + pub(super) fn new(cx: &'cx mut ExtCtxt<'a>, span: Span) -> Self { Self { best_case_captures: <_>::default(), capture_decls: <_>::default(), @@ -85,8 +85,8 @@ impl<'cx, 'a> Context<'cx, 'a> { let mut assert_then_stmts = ThinVec::with_capacity(2); assert_then_stmts.extend(best_case_captures); - assert_then_stmts.push(self.cx.stmt_expr(panic)); - let assert_then = self.cx.block(span, assert_then_stmts); + assert_then_stmts.push(cx.stmt_expr(panic)); + let assert_then = cx.block(span, assert_then_stmts); let mut stmts = ThinVec::with_capacity(4); stmts.push(initial_imports); @@ -237,6 +237,9 @@ impl<'cx, 'a> Context<'cx, 'a> { self.manage_cond_expr(prefix); self.manage_cond_expr(suffix); } + ExprKind::Matches(expr, _, _) => { + self.manage_cond_expr(expr); + } ExprKind::MethodCall(call) => { for arg in &mut call.args { self.manage_cond_expr(arg); @@ -295,17 +298,17 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::Continue(_) | ExprKind::Err | ExprKind::Field(_, _) - | ExprKind::FormatArgs(_) | ExprKind::ForLoop(_, _, _, _) + | ExprKind::FormatArgs(_) | ExprKind::If(_, _, _) | ExprKind::IncludedBytes(..) | ExprKind::InlineAsm(_) - | ExprKind::OffsetOf(_, _) | ExprKind::Let(_, _, _) | ExprKind::Lit(_) | ExprKind::Loop(_, _, _) | ExprKind::MacCall(_) | ExprKind::Match(_, _) + | ExprKind::OffsetOf(_, _) | ExprKind::Path(_, _) | ExprKind::Ret(_) | ExprKind::Try(_) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ee712a8e1b5db..b0eaf0898cb1f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -9,6 +9,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::{Path, PathSegment}; +use core::borrow::BorrowMut; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -1473,17 +1474,34 @@ impl<'a> Parser<'a> { }; // `!`, as an operator, is prefix, so we know this isn't that. - let (span, kind) = if self.eat(&token::Not) { + let expr = if self.eat(&token::Not) { + fn mac_call_expr(args: P, lo: Span, path: Path, this: &mut Parser<'_>) -> P { + this.mk_expr( + lo.to(this.prev_token.span), + ExprKind::MacCall(P(MacCall { path, args })) + ) + } // MACRO INVOCATION expression if qself.is_some() { self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span)); } + let args = self.parse_delim_args()?; let lo = path.span; - let mac = P(MacCall { - path, - args: self.parse_delim_args()?, - }); - (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) + if let Some(first_segment) = path.segments.first() { + match parse_builtin_mac(&first_segment.ident, lo, || { + Parser::new(&self.sess, args.tokens.clone(), false, None) + }) { + Err(err) => { + err.cancel(); + mac_call_expr(args, lo, path, self) + }, + Ok(None) => mac_call_expr(args, lo, path, self), + Ok(Some(builtin_expr)) => builtin_expr, + } + } + else { + mac_call_expr(args, lo, path, self) + } } else if self.check(&token::OpenDelim(Delimiter::Brace)) && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) { @@ -1492,10 +1510,9 @@ impl<'a> Parser<'a> { } return expr; } else { - (path.span, ExprKind::Path(qself, path)) + self.mk_expr(path.span, ExprKind::Path(qself, path)) }; - let expr = self.mk_expr(span, kind); self.maybe_recover_from_bad_qpath(expr) } @@ -1774,13 +1791,7 @@ impl<'a> Parser<'a> { /// Parse `builtin # ident(args,*)`. fn parse_expr_builtin(&mut self) -> PResult<'a, P> { - self.parse_builtin(|this, lo, ident| { - if ident.name == sym::offset_of { - return Ok(Some(this.parse_expr_offset_of(lo)?)); - } - - Ok(None) - }) + self.parse_builtin(|this, lo, ident| parse_builtin_mac(&ident, lo, || this)) } pub(crate) fn parse_builtin( @@ -1827,6 +1838,55 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.to_vec().into()))) } + pub(crate) fn parse_expr_matches(&mut self, lo: Span) -> PResult<'a, P> { + let expr = self.parse_expr()?; + self.expect(&TokenKind::Comma)?; + let pat = self.parse_pat_allow_top_alt( + None, + RecoverComma::No, + RecoverColon::Yes, + CommaRecoveryMode::LikelyTuple, + )?; + let guard = if self.eat_keyword(kw::If) { + let guard = self.parse_expr()?; + Some(guard) + } else { + None + }; + let _ = self.eat(&token::Comma); + let span = lo.to(self.token.span); + let true_arm = Arm { + attrs: <_>::default(), + pat, + guard, + body: self.mk_expr( + span, + ExprKind::Lit(token::Lit::new(token::LitKind::Bool, kw::True, None)), + ), + span, + id: DUMMY_NODE_ID, + is_placeholder: false, + }; + let false_arm = Arm { + attrs: <_>::default(), + pat: P(ast::Pat { + id: DUMMY_NODE_ID, + kind: ast::PatKind::Wild, + span, + tokens: <_>::default(), + }), + guard: None, + body: self.mk_expr( + span, + ExprKind::Lit(token::Lit::new(token::LitKind::Bool, kw::False, None)), + ), + span, + id: DUMMY_NODE_ID, + is_placeholder: false, + }; + Ok(self.mk_expr(lo.to(self.token.span), ExprKind::Matches(expr, P(true_arm), P(false_arm)))) + } + /// Returns a string literal if the next token is a string literal. /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind, /// and returns `None` if the next token is not literal at all. @@ -3317,7 +3377,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let res = f(this, attrs)?; - let trailing = if this.restrictions.contains(Restrictions::STMT_EXPR) + let trailing = if this.restrictions.contains(Restrictions::STMT_EXPRPAr) && this.token.kind == token::Semi { TrailingToken::Semi @@ -3333,3 +3393,21 @@ impl<'a> Parser<'a> { }) } } + +/// `parser` is a callback to avoid unecessary clones of `Parser`. +pub(crate) fn parse_builtin_mac<'any, B>( + ident: &Ident, + lo: Span, + parser: impl FnOnce() -> B, +) -> PResult<'any, Option>> +where + B: BorrowMut>, +{ + if ident.name == sym::matches { + return Ok(Some(parser().borrow_mut().parse_expr_matches(lo)?)); + } + if ident.name == sym::offset_of { + return Ok(Some(parser().borrow_mut().parse_expr_offset_of(lo)?)); + } + Ok(None) +} diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index dc5e454074ded..72d2a7ebc3f75 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -569,7 +569,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let, If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign, AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, - InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err + InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err, + Matches ] ); ast_visit::walk_expr(self, e) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 874d578fe1db3..c2a697fe6053b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -923,6 +923,7 @@ symbols! { masked, match_beginning_vert, match_default_bindings, + matches, matches_macro, maxnumf32, maxnumf64, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index b24882ddb179f..abc5e71a7926c 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -336,9 +336,10 @@ pub macro debug_assert_matches($($arg:tt)*) { /// let bar = Some(4); /// assert!(matches!(bar, Some(x) if x > 2)); /// ``` +#[cfg(bootstrap)] +#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] #[macro_export] #[stable(feature = "matches_macro", since = "1.42.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] macro_rules! matches { ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { match $expression { @@ -348,6 +349,31 @@ macro_rules! matches { }; } +/// Returns whether the given expression matches any of the given patterns. +/// +/// Like in a `match` expression, the pattern can be optionally followed by `if` +/// and a guard expression that has access to names bound by the pattern. +/// +/// # Examples +/// +/// ``` +/// let foo = 'f'; +/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z')); +/// +/// let bar = Some(4); +/// assert!(matches!(bar, Some(x) if x > 2)); +/// ``` +#[allow_internal_unstable(builtin_syntax)] +#[cfg(not(bootstrap))] +#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] +#[macro_export] +#[stable(feature = "matches_macro", since = "1.42.0")] +macro_rules! matches { + ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { + builtin # matches($expression, $pattern $(if $guard)?) + }; +} + /// Unwraps a result or propagates its error. /// /// The [`?` operator][propagating-errors] was added to replace `try!` @@ -782,7 +808,6 @@ macro_rules! todo { /// with exception of expansion functions transforming macro inputs into outputs, /// those functions are provided by the compiler. pub(crate) mod builtin { - /// Causes compilation to fail with the given error message when encountered. /// /// This macro should be used when a crate uses a conditional compilation strategy to provide diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 14f7f03016fbe..8b939442461e9 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -217,6 +217,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Try(..) | ast::ExprKind::TryBlock(..) | ast::ExprKind::Tup(..) + | ast::ExprKind::Matches(..) | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::Await(..) diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 5dc628adb0c6f..a4a1685180102 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -401,6 +401,7 @@ pub(crate) fn format_expr( ast::ExprKind::Underscore => Some("_".to_owned()), ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) + | ast::ExprKind::Matches(..) | ast::ExprKind::OffsetOf(..) => { // These do not occur in the AST because macros aren't expanded. unreachable!() diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index ca1716574071b..677433f6040b1 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -500,6 +500,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::InlineAsm(..) | ast::ExprKind::OffsetOf(..) + | ast::ExprKind::Matches(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) | ast::ExprKind::Range(..) diff --git a/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff b/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff index a717d1bbd12f2..d5627a9b4f4e5 100644 --- a/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff +++ b/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff @@ -4,32 +4,32 @@ fn issue_77355_opt(_1: Foo) -> u64 { debug num => _1; // in scope 0 at $DIR/const_goto.rs:+0:20: +0:23 let mut _0: u64; // return place in scope 0 at $DIR/const_goto.rs:+0:33: +0:36 -- let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- let mut _2: bool; // in scope 0 at $DIR/const_goto.rs:+1:8: +1:37 - let mut _3: isize; // in scope 0 at $DIR/const_goto.rs:+1:22: +1:28 + let mut _2: isize; // in scope 0 at $DIR/const_goto.rs:+1:22: +1:28 bb0: { -- StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- StorageLive(_2); // scope 0 at $DIR/const_goto.rs:+1:8: +1:37 - _3 = discriminant(_1); // scope 0 at $DIR/const_goto.rs:+1:17: +1:20 -- switchInt(move _3) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _3) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto.rs:+1:8: +1:20 + _2 = discriminant(_1); // scope 0 at $DIR/const_goto.rs:+1:17: +1:20 -+ switchInt(move _2) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ switchInt(move _2) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto.rs:+1:8: +1:20 } bb1: { -- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _2 = const false; // scope 0 at $DIR/const_goto.rs:+1:8: +1:37 +- goto -> bb3; // scope 0 at $DIR/const_goto.rs:+1:8: +1:37 + _0 = const 42_u64; // scope 0 at $DIR/const_goto.rs:+1:53: +1:55 + goto -> bb3; // scope 0 at $DIR/const_goto.rs:+1:5: +1:57 } bb2: { -- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _2 = const true; // scope 0 at $DIR/const_goto.rs:+1:8: +1:37 +- goto -> bb3; // scope 0 at $DIR/const_goto.rs:+1:8: +1:37 - } - - bb3: { -- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto.rs:+1:8: +1:37 - } - - bb4: { diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff index e3757941c8cd1..0d174e4b69985 100644 --- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff +++ b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff @@ -22,17 +22,17 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/offset_of.rs:+1:9: +1:10 -- _1 = OffsetOf(Alpha, [0]); // scope 0 at $SRC_DIR/core/src/mem/mod.rs:LL:COL -+ _1 = const 4_usize; // scope 0 at $SRC_DIR/core/src/mem/mod.rs:LL:COL +- _1 = OffsetOf(Alpha, [0]); // scope 0 at $DIR/offset_of.rs:+1:13: +1:32 ++ _1 = const 4_usize; // scope 0 at $DIR/offset_of.rs:+1:13: +1:32 StorageLive(_2); // scope 1 at $DIR/offset_of.rs:+2:9: +2:10 -- _2 = OffsetOf(Alpha, [1]); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL -+ _2 = const 0_usize; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL +- _2 = OffsetOf(Alpha, [1]); // scope 1 at $DIR/offset_of.rs:+2:13: +2:32 ++ _2 = const 0_usize; // scope 1 at $DIR/offset_of.rs:+2:13: +2:32 StorageLive(_3); // scope 2 at $DIR/offset_of.rs:+3:9: +3:11 -- _3 = OffsetOf(Alpha, [2, 0]); // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL -+ _3 = const 2_usize; // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL +- _3 = OffsetOf(Alpha, [2, 0]); // scope 2 at $DIR/offset_of.rs:+3:14: +3:35 ++ _3 = const 2_usize; // scope 2 at $DIR/offset_of.rs:+3:14: +3:35 StorageLive(_4); // scope 3 at $DIR/offset_of.rs:+4:9: +4:11 -- _4 = OffsetOf(Alpha, [2, 1]); // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL -+ _4 = const 3_usize; // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL +- _4 = OffsetOf(Alpha, [2, 1]); // scope 3 at $DIR/offset_of.rs:+4:14: +4:35 ++ _4 = const 3_usize; // scope 3 at $DIR/offset_of.rs:+4:14: +4:35 _0 = const (); // scope 0 at $DIR/offset_of.rs:+0:15: +5:2 StorageDead(_4); // scope 3 at $DIR/offset_of.rs:+5:1: +5:2 StorageDead(_3); // scope 2 at $DIR/offset_of.rs:+5:1: +5:2 diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff index 4a655604cd183..28cc86e68fd2a 100644 --- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff +++ b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff @@ -22,13 +22,13 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/offset_of.rs:+1:9: +1:11 - _1 = OffsetOf(Gamma, [0]); // scope 0 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + _1 = OffsetOf(Gamma, [0]); // scope 0 at $DIR/offset_of.rs:+1:14: +1:36 StorageLive(_2); // scope 1 at $DIR/offset_of.rs:+2:9: +2:11 - _2 = OffsetOf(Gamma, [1]); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + _2 = OffsetOf(Gamma, [1]); // scope 1 at $DIR/offset_of.rs:+2:14: +2:36 StorageLive(_3); // scope 2 at $DIR/offset_of.rs:+3:9: +3:11 - _3 = OffsetOf(Delta, [1]); // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + _3 = OffsetOf(Delta, [1]); // scope 2 at $DIR/offset_of.rs:+3:14: +3:36 StorageLive(_4); // scope 3 at $DIR/offset_of.rs:+4:9: +4:11 - _4 = OffsetOf(Delta, [2]); // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL + _4 = OffsetOf(Delta, [2]); // scope 3 at $DIR/offset_of.rs:+4:14: +4:36 _0 = const (); // scope 0 at $DIR/offset_of.rs:+0:17: +5:2 StorageDead(_4); // scope 3 at $DIR/offset_of.rs:+5:1: +5:2 StorageDead(_3); // scope 2 at $DIR/offset_of.rs:+5:1: +5:2 diff --git a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff index 0580f73341d21..e351b62591dba 100644 --- a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff @@ -4,33 +4,33 @@ fn foo(_1: Option<()>) -> () { debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11 let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25 - let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26 -+ let mut _4: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL ++ let mut _4: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:20 bb0: { - StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20 -- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:20 ++ StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:20 ++ _4 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:20 ++ _2 = Eq(_4, const 0_isize); // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 ++ StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:20 ++ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 } bb1: { -- _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 - } - - bb2: { -- _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL -- goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 - } - - bb3: { -- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL +- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+1:8: +1:26 - } - - bb4: { diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs index e88e24482ccc8..52a5ad6a28f1b 100644 --- a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs @@ -86,6 +86,9 @@ fn main() { // index [ [1i32, 1][elem as usize] == 3 ] => "Assertion failed: [1i32, 1][elem as usize] == 3\nWith captures:\n elem = 1\n" + // matches + [ matches!(Some(elem == 1i32), None) ] => "Assertion failed: builtin # matches(Some(elem == 1i32), None)\nWith captures:\n elem = 1\n" + // method call [ FOO.add(elem, elem) == 3 ] => "Assertion failed: FOO.add(elem, elem) == 3\nWith captures:\n elem = 1\n" diff --git a/tests/ui/stdlib-unit-tests/matches2021.rs b/tests/ui/stdlib-unit-tests/matches2021.rs index 9143a8cdd59bc..1b64bfba2bf85 100644 --- a/tests/ui/stdlib-unit-tests/matches2021.rs +++ b/tests/ui/stdlib-unit-tests/matches2021.rs @@ -1,3 +1,5 @@ +#![allow(unreachable_patterns)] + // run-pass // edition:2021