From 3beb2e95a98e90f43809a9ab1fb7175d4fa7aa8d Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 18 Oct 2020 22:30:16 +0200 Subject: [PATCH] Expand assert!(expr) to panic() function instead of panic!() macro. The panic message might contain braces which should never be interpreted as format placeholders, which panic!() will do in a future edition. --- compiler/rustc_builtin_macros/src/assert.rs | 62 ++++++++++++--------- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/macros/mod.rs | 1 + 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 5bfd8a2bf56..bc3276538da 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -1,8 +1,8 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, TokenKind}; -use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; +use rustc_ast::token; +use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_expand::base::*; @@ -26,31 +26,41 @@ pub fn expand_assert<'cx>( // `core::panic` and `std::panic` are different macros, so we use call-site // context to pick up whichever is currently in scope. let sp = cx.with_call_site_ctxt(sp); - let tokens = custom_message.unwrap_or_else(|| { - TokenStream::from(TokenTree::token( - TokenKind::lit( - token::Str, - Symbol::intern(&format!( - "assertion failed: {}", - pprust::expr_to_string(&cond_expr).escape_debug() - )), - None, - ), - DUMMY_SP, - )) - }); - let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens)); - let panic_call = MacCall { - path: Path::from_ident(Ident::new(sym::panic, sp)), - args, - prior_type_ascription: None, + + let panic_call = { + if let Some(tokens) = custom_message { + // Pass the custom message to panic!(). + cx.expr( + sp, + ExprKind::MacCall(MacCall { + path: Path::from_ident(Ident::new(sym::panic, sp)), + args: P(MacArgs::Delimited( + DelimSpan::from_single(sp), + MacDelimiter::Parenthesis, + tokens, + )), + prior_type_ascription: None, + }), + ) + } else { + // Pass our own message directly to $crate::panicking::panic(), + // because it might contain `{` and `}` that should always be + // passed literally. + cx.expr_call_global( + sp, + cx.std_path(&[sym::panicking, sym::panic]), + vec![cx.expr_str( + DUMMY_SP, + Symbol::intern(&format!( + "assertion failed: {}", + pprust::expr_to_string(&cond_expr).escape_debug() + )), + )], + ) + } }; - let if_expr = cx.expr_if( - sp, - cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), - cx.expr(sp, ExprKind::MacCall(panic_call)), - None, - ); + let if_expr = + cx.expr_if(sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), panic_call, None); MacEager::expr(if_expr) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c6949d9387c..733d2b1ef9a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -791,6 +791,7 @@ panic_runtime, panic_str, panic_unwind, + panicking, param_attrs, parent_trait, partial_cmp, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 9f28186a33c..53e6b459839 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1217,6 +1217,7 @@ macro_rules! include { #[rustc_builtin_macro] #[macro_export] #[rustc_diagnostic_item = "assert_macro"] + #[allow_internal_unstable(core_panic)] macro_rules! assert { ($cond:expr $(,)?) => {{ /* compiler built-in */ }}; ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};