Auto merge of #93179 - Urgau:unreachable-2021, r=m-ou-se,oli-obk
Fix invalid special casing of the unreachable! macro This pull-request fix an invalid special casing of the `unreachable!` macro in the same way the `panic!` macro was solved, by adding two new internal only macros `unreachable_2015` and `unreachable_2021` edition dependent and turn `unreachable!` into a built-in macro that do dispatching. This logic is stolen from the `panic!` macro. ~~This pull-request also adds an internal feature `format_args_capture_non_literal` that allows capturing arguments from formatted string that expanded from macros. The original RFC #2795 mentioned this as a future possibility. This feature is [required](https://github.com/rust-lang/rust/issues/92137#issuecomment-1018630522) because of concatenation that needs to be done inside the macro:~~ ```rust $crate::concat!("internal error: entered unreachable code: ", $fmt) ``` **In summary** the new behavior for the `unreachable!` macro with this pr is: Edition 2021: ```rust let x = 5; unreachable!("x is {x}"); ``` ``` internal error: entered unreachable code: x is 5 ``` Edition <= 2018: ```rust let x = 5; unreachable!("x is {x}"); ``` ``` internal error: entered unreachable code: x is {x} ``` Also note that the change in this PR are **insta-stable** and **breaking changes** but this a considered as being a [bug](https://github.com/rust-lang/rust/issues/92137#issuecomment-998441613). If someone could start a perf run and then a crater run this would be appreciated. Fixes https://github.com/rust-lang/rust/issues/92137
This commit is contained in:
commit
25b21a1d16
22 changed files with 326 additions and 80 deletions
|
@ -49,9 +49,11 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
|
|||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
|
||||
if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
|
||||
let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id);
|
||||
|
||||
if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
|
||||
|| Some(def_id) == cx.tcx.lang_items().panic_fn()
|
||||
|| Some(def_id) == cx.tcx.lang_items().panic_str()
|
||||
|| f_diagnostic_name == Some(sym::panic_str)
|
||||
{
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
|
||||
if matches!(
|
||||
|
@ -61,6 +63,22 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
|
|||
check_panic(cx, f, arg);
|
||||
}
|
||||
}
|
||||
} else if f_diagnostic_name == Some(sym::unreachable_display) {
|
||||
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
|
||||
if cx.tcx.is_diagnostic_item(sym::unreachable_2015_macro, id) {
|
||||
check_panic(
|
||||
cx,
|
||||
f,
|
||||
// This is safe because we checked above that the callee is indeed
|
||||
// unreachable_display
|
||||
match &arg.kind {
|
||||
// Get the borrowed arg not the borrow
|
||||
hir::ExprKind::AddrOf(ast::BorrowKind::Ref, _, arg) => arg,
|
||||
_ => bug!("call to unreachable_display without borrow"),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +103,8 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||
return;
|
||||
}
|
||||
|
||||
// Find the span of the argument to `panic!()`, before expansion in the
|
||||
// case of `panic!(some_macro!())`.
|
||||
// Find the span of the argument to `panic!()` or `unreachable!`, before expansion in the
|
||||
// case of `panic!(some_macro!())` or `unreachable!(some_macro!())`.
|
||||
// We don't use source_callsite(), because this `panic!(..)` might itself
|
||||
// be expanded from another macro, in which case we want to stop at that
|
||||
// expansion.
|
||||
|
@ -319,6 +337,7 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span,
|
|||
| sym::std_panic_macro
|
||||
| sym::assert_macro
|
||||
| sym::debug_assert_macro
|
||||
| sym::unreachable_macro
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue