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.
This commit is contained in:
Mara Bos 2020-10-18 22:30:16 +02:00
parent f228efc3f5
commit 3beb2e95a9
3 changed files with 38 additions and 26 deletions

View File

@ -1,8 +1,8 @@
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, TokenKind}; use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{self as ast, *}; use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_expand::base::*; 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 // `core::panic` and `std::panic` are different macros, so we use call-site
// context to pick up whichever is currently in scope. // context to pick up whichever is currently in scope.
let sp = cx.with_call_site_ctxt(sp); let sp = cx.with_call_site_ctxt(sp);
let tokens = custom_message.unwrap_or_else(|| {
TokenStream::from(TokenTree::token( let panic_call = {
TokenKind::lit( if let Some(tokens) = custom_message {
token::Str, // Pass the custom message to panic!().
Symbol::intern(&format!( cx.expr(
"assertion failed: {}", sp,
pprust::expr_to_string(&cond_expr).escape_debug() ExprKind::MacCall(MacCall {
)), path: Path::from_ident(Ident::new(sym::panic, sp)),
None, args: P(MacArgs::Delimited(
), DelimSpan::from_single(sp),
DUMMY_SP, MacDelimiter::Parenthesis,
)) tokens,
}); )),
let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens)); prior_type_ascription: None,
let panic_call = MacCall { }),
path: Path::from_ident(Ident::new(sym::panic, sp)), )
args, } else {
prior_type_ascription: None, // 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( let if_expr =
sp, cx.expr_if(sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), panic_call, None);
cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
cx.expr(sp, ExprKind::MacCall(panic_call)),
None,
);
MacEager::expr(if_expr) MacEager::expr(if_expr)
} }

View File

@ -791,6 +791,7 @@ symbols! {
panic_runtime, panic_runtime,
panic_str, panic_str,
panic_unwind, panic_unwind,
panicking,
param_attrs, param_attrs,
parent_trait, parent_trait,
partial_cmp, partial_cmp,

View File

@ -1217,6 +1217,7 @@ pub(crate) mod builtin {
#[rustc_builtin_macro] #[rustc_builtin_macro]
#[macro_export] #[macro_export]
#[rustc_diagnostic_item = "assert_macro"] #[rustc_diagnostic_item = "assert_macro"]
#[allow_internal_unstable(core_panic)]
macro_rules! assert { macro_rules! assert {
($cond:expr $(,)?) => {{ /* compiler built-in */ }}; ($cond:expr $(,)?) => {{ /* compiler built-in */ }};
($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};