about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2023-09-03 06:31:56 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2023-09-08 14:05:57 +0200
commit6a02baaa3d9c471577037a053ee8ed50a9327f7d (patch)
treef628291159e775e24fe9d181d34f1faaa1dc0b7f
parent15e52b05ca8f63e0da27c808680388717e5b997e (diff)
downloadrust-6a02baaa3d9c471577037a053ee8ed50a9327f7d.tar.gz
rust-6a02baaa3d9c471577037a053ee8ed50a9327f7d.zip
Partially outline code inside the panic! macro
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs6
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--library/core/src/panic.rs45
-rw-r--r--library/core/src/panicking.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs16
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs20
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr16
11 files changed, 117 insertions, 30 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index f16aea6f34b..6c92ad45f47 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -207,7 +207,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         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()
         {
             let args = self.copy_fn_args(args)?;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index f288ddc25d3..97c3a7d5b8d 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -886,7 +886,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // 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
                 // 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`
-                if Some(callee) == tcx.lang_items().panic_display() {
+                // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
+                if tcx.has_attr(callee, sym::rustc_const_panic_str) {
                     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()) =>
                         {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e745ef1ec07..95f4e829b10 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -667,6 +667,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         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:
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 23b20543d53..4a89a6f7e39 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -230,7 +230,6 @@ language_item_table! {
     Panic,                   sym::panic,               panic_fn,                   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;
-    PanicDisplay,            sym::panic_display,       panic_display,              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);
     PanicMisalignedPointerDereference,        sym::panic_misaligned_pointer_dereference,  panic_misaligned_pointer_dereference_fn,      Target::Fn,             GenericRequirement::Exact(0);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 656deebb5d0..f07326ac86a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1099,7 +1099,6 @@ symbols! {
         panic_abort,
         panic_bounds_check,
         panic_cannot_unwind,
-        panic_display,
         panic_fmt,
         panic_handler,
         panic_impl,
@@ -1295,6 +1294,7 @@ symbols! {
         rustc_coherence_is_core,
         rustc_coinductive,
         rustc_confusables,
+        rustc_const_panic_str,
         rustc_const_stable,
         rustc_const_unstable,
         rustc_conversion_suggestion,
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 20be60d3535..02974b0ec14 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -47,6 +47,7 @@ pub macro panic_2015 {
 #[allow_internal_unstable(core_panic, const_format_args)]
 #[rustc_diagnostic_item = "core_panic_2021_macro"]
 #[rustc_macro_transparency = "semitransparent"]
+#[cfg(any(bootstrap, feature = "panic_immediate_abort"))]
 pub macro panic_2021 {
     () => (
         $crate::panicking::panic("explicit panic")
@@ -63,6 +64,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)]
 #[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
 #[allow_internal_unstable(core_panic)]
 #[rustc_diagnostic_item = "unreachable_2015_macro"]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 281f8c1e166..46f1c275b6e 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! {
     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]
 #[track_caller]
 #[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]
 #[track_caller]
-#[lang = "panic_display"] // needed for const-evaluated panics
 #[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")]
 pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
     panic_fmt(format_args!("{}", *x));
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 367cd6bd413..ea6a9bc5657 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -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> {
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
             // fix #10776
             ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
-                ([], Some(e)) => self.visit_expr(e),
-                ([stmt], None) => match stmt.kind {
-                    StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
-                    _ => {},
+                (stmts, Some(e)) => {
+                    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),
+                            _ => {},
+                        }
+                    }
                 },
                 _ => {},
             },
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 173f9841d44..94334f55109 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -227,16 +227,26 @@ pub enum PanicExpn<'a> {
 
 impl<'a> PanicExpn<'a> {
     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;
         };
         let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else {
             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" | "panic_str" => Self::Str(arg),
-            "panic_display" => {
+            "panic_display" | "panic_cold_display" => {
                 let ExprKind::AddrOf(_, _, e) = &arg.kind else {
                     return None;
                 };
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
index 1ee048bf7f6..e1b95aa5776 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
@@ -4,14 +4,18 @@
 //@no-rustfix
 use std::sync::atomic::Ordering; // #[non_exhaustive] enum
 
+fn repeat() -> ! {
+    panic!()
+}
+
 pub fn f(x: Ordering) {
     match x {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         Ordering::Acquire => println!("acquire"),
-        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        Ordering::AcqRel | Ordering::SeqCst => repeat(),
         #[deny(non_exhaustive_omitted_patterns)]
-        _ => panic!(),
+        _ => repeat(),
     }
 }
 
@@ -25,8 +29,8 @@ mod f {
             Ordering::Relaxed => println!("relaxed"),
             Ordering::Release => println!("release"),
             Ordering::Acquire => println!("acquire"),
-            Ordering::AcqRel | Ordering::SeqCst => panic!(),
-            _ => panic!(),
+            Ordering::AcqRel | Ordering::SeqCst => repeat(),
+            _ => repeat(),
         }
     }
 }
@@ -38,9 +42,9 @@ pub fn g(x: Ordering) {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         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
-        _ => panic!(),
+        _ => repeat(),
     }
 }
 
@@ -52,9 +56,9 @@ mod g {
             Ordering::Relaxed => println!("relaxed"),
             Ordering::Release => println!("release"),
             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
-            _ => panic!(),
+            _ => repeat(),
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
index a039536338b..ae6b02ab1b5 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
@@ -1,29 +1,29 @@
 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: or try changing either arm body
 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`
    = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
 
 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: or try changing either arm body
 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