mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
Auto merge of #115670 - Zoxc:outline-panic-macro-1, r=Mark-Simulacrum
Partially outline code inside the panic! macro This outlines code inside the panic! macro in some cases. This is split out from https://github.com/rust-lang/rust/pull/115562 to exclude changes to rustc.
This commit is contained in:
commit
8fa7bdf191
@ -207,7 +207,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
|||||||
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
|
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
|
||||||
let def_id = instance.def_id();
|
let def_id = instance.def_id();
|
||||||
|
|
||||||
if Some(def_id) == self.tcx.lang_items().panic_display()
|
if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
|
||||||
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
|
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
|
||||||
{
|
{
|
||||||
let args = self.copy_fn_args(args)?;
|
let args = self.copy_fn_args(args)?;
|
||||||
|
@ -886,7 +886,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
|
|
||||||
// At this point, we are calling a function, `callee`, whose `DefId` is known...
|
// At this point, we are calling a function, `callee`, whose `DefId` is known...
|
||||||
|
|
||||||
// `begin_panic` and `panic_display` are generic functions that accept
|
// `begin_panic` and `#[rustc_const_panic_str]` functions accept generic
|
||||||
// types other than str. Check to enforce that only str can be used in
|
// types other than str. Check to enforce that only str can be used in
|
||||||
// const-eval.
|
// const-eval.
|
||||||
|
|
||||||
@ -898,8 +898,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// const-eval of the `panic_display` fn assumes the argument is `&&str`
|
// const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
|
||||||
if Some(callee) == tcx.lang_items().panic_display() {
|
if tcx.has_attr(callee, sym::rustc_const_panic_str) {
|
||||||
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
|
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
|
||||||
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
|
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
|
||||||
{
|
{
|
||||||
|
@ -666,6 +666,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||||||
rustc_attr!(
|
rustc_attr!(
|
||||||
rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
|
rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
|
||||||
),
|
),
|
||||||
|
// Ensure the argument to this function is &&str during const-check.
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_const_panic_str, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
|
||||||
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Internal attributes, Layout related:
|
// Internal attributes, Layout related:
|
||||||
|
@ -230,7 +230,6 @@ language_item_table! {
|
|||||||
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
|
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
|
||||||
PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
|
PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
|
||||||
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
|
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
|
||||||
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
|
|
||||||
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
|
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
|
||||||
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
|
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
|
||||||
PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0);
|
PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0);
|
||||||
|
@ -1104,7 +1104,6 @@ symbols! {
|
|||||||
panic_abort,
|
panic_abort,
|
||||||
panic_bounds_check,
|
panic_bounds_check,
|
||||||
panic_cannot_unwind,
|
panic_cannot_unwind,
|
||||||
panic_display,
|
|
||||||
panic_fmt,
|
panic_fmt,
|
||||||
panic_handler,
|
panic_handler,
|
||||||
panic_impl,
|
panic_impl,
|
||||||
@ -1299,6 +1298,7 @@ symbols! {
|
|||||||
rustc_coherence_is_core,
|
rustc_coherence_is_core,
|
||||||
rustc_coinductive,
|
rustc_coinductive,
|
||||||
rustc_confusables,
|
rustc_confusables,
|
||||||
|
rustc_const_panic_str,
|
||||||
rustc_const_stable,
|
rustc_const_stable,
|
||||||
rustc_const_unstable,
|
rustc_const_unstable,
|
||||||
rustc_conversion_suggestion,
|
rustc_conversion_suggestion,
|
||||||
|
@ -47,6 +47,7 @@ pub macro panic_2015 {
|
|||||||
#[allow_internal_unstable(core_panic, const_format_args)]
|
#[allow_internal_unstable(core_panic, const_format_args)]
|
||||||
#[rustc_diagnostic_item = "core_panic_2021_macro"]
|
#[rustc_diagnostic_item = "core_panic_2021_macro"]
|
||||||
#[rustc_macro_transparency = "semitransparent"]
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
|
#[cfg(any(bootstrap, feature = "panic_immediate_abort"))]
|
||||||
pub macro panic_2021 {
|
pub macro panic_2021 {
|
||||||
() => (
|
() => (
|
||||||
$crate::panicking::panic("explicit panic")
|
$crate::panicking::panic("explicit panic")
|
||||||
@ -62,6 +63,50 @@ pub macro panic_2021 {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
|
||||||
|
#[allow_internal_unstable(
|
||||||
|
core_panic,
|
||||||
|
core_intrinsics,
|
||||||
|
const_dispatch,
|
||||||
|
const_eval_select,
|
||||||
|
const_format_args,
|
||||||
|
rustc_attrs
|
||||||
|
)]
|
||||||
|
#[rustc_diagnostic_item = "core_panic_2021_macro"]
|
||||||
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
|
#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))]
|
||||||
|
pub macro panic_2021 {
|
||||||
|
() => ({
|
||||||
|
// Create a function so that the argument for `track_caller`
|
||||||
|
// can be moved inside if possible.
|
||||||
|
#[cold]
|
||||||
|
#[track_caller]
|
||||||
|
#[inline(never)]
|
||||||
|
const fn panic_cold_explicit() -> ! {
|
||||||
|
$crate::panicking::panic_explicit()
|
||||||
|
}
|
||||||
|
panic_cold_explicit();
|
||||||
|
}),
|
||||||
|
// Special-case the single-argument case for const_panic.
|
||||||
|
("{}", $arg:expr $(,)?) => ({
|
||||||
|
#[cold]
|
||||||
|
#[track_caller]
|
||||||
|
#[inline(never)]
|
||||||
|
#[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval
|
||||||
|
#[rustc_do_not_const_check] // hooked by const-eval
|
||||||
|
const fn panic_cold_display<T: $crate::fmt::Display>(arg: &T) -> ! {
|
||||||
|
$crate::panicking::panic_display(arg)
|
||||||
|
}
|
||||||
|
panic_cold_display(&$arg);
|
||||||
|
}),
|
||||||
|
($($t:tt)+) => ({
|
||||||
|
// Semicolon to prevent temporaries inside the formatting machinery from
|
||||||
|
// being considered alive in the caller after the panic_fmt call.
|
||||||
|
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
|
#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
|
||||||
#[allow_internal_unstable(core_panic)]
|
#[allow_internal_unstable(core_panic)]
|
||||||
|
@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! {
|
|||||||
panic_display(&expr);
|
panic_display(&expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
|
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
|
||||||
|
pub const fn panic_explicit() -> ! {
|
||||||
|
panic_display(&"explicit panic");
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint
|
#[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint
|
||||||
@ -161,8 +169,10 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[lang = "panic_display"] // needed for const-evaluated panics
|
|
||||||
#[rustc_do_not_const_check] // hooked by const-eval
|
#[rustc_do_not_const_check] // hooked by const-eval
|
||||||
|
#[cfg_attr(bootstrap, lang = "panic_display")]
|
||||||
|
// enforce a &&str argument in const-check and hook this by const-eval
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_panic_str)]
|
||||||
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
|
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
|
||||||
pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
|
pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
|
||||||
panic_fmt(format_args!("{}", *x));
|
panic_fmt(format_args!("{}", *x));
|
||||||
|
@ -134,15 +134,30 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool {
|
||||||
|
match stmt.kind {
|
||||||
|
StmtKind::Item(..) => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
// fix #10776
|
// fix #10776
|
||||||
ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
|
ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
|
||||||
([], Some(e)) => self.visit_expr(e),
|
(stmts, Some(e)) => {
|
||||||
([stmt], None) => match stmt.kind {
|
if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) {
|
||||||
|
self.visit_expr(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
([first @ .., stmt], None) => {
|
||||||
|
if first.iter().all(|stmt| !stmt_might_diverge(stmt)) {
|
||||||
|
match stmt.kind {
|
||||||
StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
|
StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
|
||||||
_ => {},
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
|
@ -228,16 +228,26 @@ pub enum PanicExpn<'a> {
|
|||||||
|
|
||||||
impl<'a> PanicExpn<'a> {
|
impl<'a> PanicExpn<'a> {
|
||||||
pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
|
pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
|
||||||
let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else {
|
let ExprKind::Call(callee, args) = &expr.kind else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else {
|
let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let result = match path.segments.last().unwrap().ident.as_str() {
|
let name = path.segments.last().unwrap().ident.as_str();
|
||||||
|
|
||||||
|
// This has no argument
|
||||||
|
if name == "panic_cold_explicit" {
|
||||||
|
return Some(Self::Empty);
|
||||||
|
};
|
||||||
|
|
||||||
|
let [arg, rest @ ..] = args else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
let result = match name {
|
||||||
"panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
|
"panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
|
||||||
"panic" | "panic_str" => Self::Str(arg),
|
"panic" | "panic_str" => Self::Str(arg),
|
||||||
"panic_display" => {
|
"panic_display" | "panic_cold_display" => {
|
||||||
let ExprKind::AddrOf(_, _, e) = &arg.kind else {
|
let ExprKind::AddrOf(_, _, e) = &arg.kind else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
@ -4,14 +4,18 @@
|
|||||||
//@no-rustfix
|
//@no-rustfix
|
||||||
use std::sync::atomic::Ordering; // #[non_exhaustive] enum
|
use std::sync::atomic::Ordering; // #[non_exhaustive] enum
|
||||||
|
|
||||||
|
fn repeat() -> ! {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn f(x: Ordering) {
|
pub fn f(x: Ordering) {
|
||||||
match x {
|
match x {
|
||||||
Ordering::Relaxed => println!("relaxed"),
|
Ordering::Relaxed => println!("relaxed"),
|
||||||
Ordering::Release => println!("release"),
|
Ordering::Release => println!("release"),
|
||||||
Ordering::Acquire => println!("acquire"),
|
Ordering::Acquire => println!("acquire"),
|
||||||
Ordering::AcqRel | Ordering::SeqCst => panic!(),
|
Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
#[deny(non_exhaustive_omitted_patterns)]
|
||||||
_ => panic!(),
|
_ => repeat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,8 +29,8 @@ mod f {
|
|||||||
Ordering::Relaxed => println!("relaxed"),
|
Ordering::Relaxed => println!("relaxed"),
|
||||||
Ordering::Release => println!("release"),
|
Ordering::Release => println!("release"),
|
||||||
Ordering::Acquire => println!("acquire"),
|
Ordering::Acquire => println!("acquire"),
|
||||||
Ordering::AcqRel | Ordering::SeqCst => panic!(),
|
Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
_ => panic!(),
|
_ => repeat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,9 +42,9 @@ pub fn g(x: Ordering) {
|
|||||||
Ordering::Relaxed => println!("relaxed"),
|
Ordering::Relaxed => println!("relaxed"),
|
||||||
Ordering::Release => println!("release"),
|
Ordering::Release => println!("release"),
|
||||||
Ordering::Acquire => println!("acquire"),
|
Ordering::Acquire => println!("acquire"),
|
||||||
Ordering::AcqRel | Ordering::SeqCst => panic!(),
|
Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
//~^ ERROR: this match arm has an identical body to the `_` wildcard arm
|
//~^ ERROR: this match arm has an identical body to the `_` wildcard arm
|
||||||
_ => panic!(),
|
_ => repeat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,9 +56,9 @@ mod g {
|
|||||||
Ordering::Relaxed => println!("relaxed"),
|
Ordering::Relaxed => println!("relaxed"),
|
||||||
Ordering::Release => println!("release"),
|
Ordering::Release => println!("release"),
|
||||||
Ordering::Acquire => println!("acquire"),
|
Ordering::Acquire => println!("acquire"),
|
||||||
Ordering::AcqRel | Ordering::SeqCst => panic!(),
|
Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
//~^ ERROR: this match arm has an identical body to the `_` wildcard arm
|
//~^ ERROR: this match arm has an identical body to the `_` wildcard arm
|
||||||
_ => panic!(),
|
_ => repeat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
error: this match arm has an identical body to the `_` wildcard arm
|
error: this match arm has an identical body to the `_` wildcard arm
|
||||||
--> $DIR/match_same_arms_non_exhaustive.rs:41:9
|
--> $DIR/match_same_arms_non_exhaustive.rs:45:9
|
||||||
|
|
|
|
||||||
LL | Ordering::AcqRel | Ordering::SeqCst => panic!(),
|
LL | Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
|
||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: `_` wildcard arm here
|
note: `_` wildcard arm here
|
||||||
--> $DIR/match_same_arms_non_exhaustive.rs:43:9
|
--> $DIR/match_same_arms_non_exhaustive.rs:47:9
|
||||||
|
|
|
|
||||||
LL | _ => panic!(),
|
LL | _ => repeat(),
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: `-D clippy::match-same-arms` implied by `-D warnings`
|
= note: `-D clippy::match-same-arms` implied by `-D warnings`
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
|
= help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
|
||||||
|
|
||||||
error: this match arm has an identical body to the `_` wildcard arm
|
error: this match arm has an identical body to the `_` wildcard arm
|
||||||
--> $DIR/match_same_arms_non_exhaustive.rs:55:13
|
--> $DIR/match_same_arms_non_exhaustive.rs:59:13
|
||||||
|
|
|
|
||||||
LL | Ordering::AcqRel | Ordering::SeqCst => panic!(),
|
LL | Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
|
||||||
|
|
|
|
||||||
= help: or try changing either arm body
|
= help: or try changing either arm body
|
||||||
note: `_` wildcard arm here
|
note: `_` wildcard arm here
|
||||||
--> $DIR/match_same_arms_non_exhaustive.rs:57:13
|
--> $DIR/match_same_arms_non_exhaustive.rs:61:13
|
||||||
|
|
|
|
||||||
LL | _ => panic!(),
|
LL | _ => repeat(),
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
Loading…
Reference in New Issue
Block a user