Skip to content

Commit 8fa7bdf

Browse files
committed
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 #115562 to exclude changes to rustc.
2 parents 361096f + 6a02baa commit 8fa7bdf

File tree

11 files changed

+117
-30
lines changed

11 files changed

+117
-30
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
207207
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
208208
let def_id = instance.def_id();
209209

210-
if Some(def_id) == self.tcx.lang_items().panic_display()
210+
if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
211211
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
212212
{
213213
let args = self.copy_fn_args(args)?;

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
886886

887887
// At this point, we are calling a function, `callee`, whose `DefId` is known...
888888

889-
// `begin_panic` and `panic_display` are generic functions that accept
889+
// `begin_panic` and `#[rustc_const_panic_str]` functions accept generic
890890
// types other than str. Check to enforce that only str can be used in
891891
// const-eval.
892892

@@ -898,8 +898,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
898898
}
899899
}
900900

901-
// const-eval of the `panic_display` fn assumes the argument is `&&str`
902-
if Some(callee) == tcx.lang_items().panic_display() {
901+
// const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
902+
if tcx.has_attr(callee, sym::rustc_const_panic_str) {
903903
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
904904
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
905905
{

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
666666
rustc_attr!(
667667
rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
668668
),
669+
// Ensure the argument to this function is &&str during const-check.
670+
rustc_attr!(
671+
rustc_const_panic_str, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
672+
),
669673

670674
// ==========================================================================
671675
// Internal attributes, Layout related:

compiler/rustc_hir/src/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ language_item_table! {
230230
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
231231
PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
232232
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
233-
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
234233
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
235234
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
236235
PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0);

compiler/rustc_span/src/symbol.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,6 @@ symbols! {
11041104
panic_abort,
11051105
panic_bounds_check,
11061106
panic_cannot_unwind,
1107-
panic_display,
11081107
panic_fmt,
11091108
panic_handler,
11101109
panic_impl,
@@ -1299,6 +1298,7 @@ symbols! {
12991298
rustc_coherence_is_core,
13001299
rustc_coinductive,
13011300
rustc_confusables,
1301+
rustc_const_panic_str,
13021302
rustc_const_stable,
13031303
rustc_const_unstable,
13041304
rustc_conversion_suggestion,

library/core/src/panic.rs

+45
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub macro panic_2015 {
4747
#[allow_internal_unstable(core_panic, const_format_args)]
4848
#[rustc_diagnostic_item = "core_panic_2021_macro"]
4949
#[rustc_macro_transparency = "semitransparent"]
50+
#[cfg(any(bootstrap, feature = "panic_immediate_abort"))]
5051
pub macro panic_2021 {
5152
() => (
5253
$crate::panicking::panic("explicit panic")
@@ -62,6 +63,50 @@ pub macro panic_2021 {
6263
}),
6364
}
6465

66+
#[doc(hidden)]
67+
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
68+
#[allow_internal_unstable(
69+
core_panic,
70+
core_intrinsics,
71+
const_dispatch,
72+
const_eval_select,
73+
const_format_args,
74+
rustc_attrs
75+
)]
76+
#[rustc_diagnostic_item = "core_panic_2021_macro"]
77+
#[rustc_macro_transparency = "semitransparent"]
78+
#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))]
79+
pub macro panic_2021 {
80+
() => ({
81+
// Create a function so that the argument for `track_caller`
82+
// can be moved inside if possible.
83+
#[cold]
84+
#[track_caller]
85+
#[inline(never)]
86+
const fn panic_cold_explicit() -> ! {
87+
$crate::panicking::panic_explicit()
88+
}
89+
panic_cold_explicit();
90+
}),
91+
// Special-case the single-argument case for const_panic.
92+
("{}", $arg:expr $(,)?) => ({
93+
#[cold]
94+
#[track_caller]
95+
#[inline(never)]
96+
#[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval
97+
#[rustc_do_not_const_check] // hooked by const-eval
98+
const fn panic_cold_display<T: $crate::fmt::Display>(arg: &T) -> ! {
99+
$crate::panicking::panic_display(arg)
100+
}
101+
panic_cold_display(&$arg);
102+
}),
103+
($($t:tt)+) => ({
104+
// Semicolon to prevent temporaries inside the formatting machinery from
105+
// being considered alive in the caller after the panic_fmt call.
106+
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
107+
}),
108+
}
109+
65110
#[doc(hidden)]
66111
#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
67112
#[allow_internal_unstable(core_panic)]

library/core/src/panicking.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! {
152152
panic_display(&expr);
153153
}
154154

155+
#[track_caller]
156+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
157+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
158+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
159+
pub const fn panic_explicit() -> ! {
160+
panic_display(&"explicit panic");
161+
}
162+
155163
#[inline]
156164
#[track_caller]
157165
#[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint
@@ -161,8 +169,10 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
161169

162170
#[inline]
163171
#[track_caller]
164-
#[lang = "panic_display"] // needed for const-evaluated panics
165172
#[rustc_do_not_const_check] // hooked by const-eval
173+
#[cfg_attr(bootstrap, lang = "panic_display")]
174+
// enforce a &&str argument in const-check and hook this by const-eval
175+
#[cfg_attr(not(bootstrap), rustc_const_panic_str)]
166176
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
167177
pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
168178
panic_fmt(format_args!("{}", *x));

src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,30 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
134134
}
135135
}
136136

137+
fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool {
138+
match stmt.kind {
139+
StmtKind::Item(..) => false,
140+
_ => true,
141+
}
142+
}
143+
137144
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
138145
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
139146
match e.kind {
140147
// fix #10776
141148
ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
142-
([], Some(e)) => self.visit_expr(e),
143-
([stmt], None) => match stmt.kind {
144-
StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
145-
_ => {},
149+
(stmts, Some(e)) => {
150+
if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) {
151+
self.visit_expr(e)
152+
}
153+
},
154+
([first @ .., stmt], None) => {
155+
if first.iter().all(|stmt| !stmt_might_diverge(stmt)) {
156+
match stmt.kind {
157+
StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
158+
_ => {},
159+
}
160+
}
146161
},
147162
_ => {},
148163
},

src/tools/clippy/clippy_utils/src/macros.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,26 @@ pub enum PanicExpn<'a> {
228228

229229
impl<'a> PanicExpn<'a> {
230230
pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
231-
let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else {
231+
let ExprKind::Call(callee, args) = &expr.kind else {
232232
return None;
233233
};
234234
let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else {
235235
return None;
236236
};
237-
let result = match path.segments.last().unwrap().ident.as_str() {
237+
let name = path.segments.last().unwrap().ident.as_str();
238+
239+
// This has no argument
240+
if name == "panic_cold_explicit" {
241+
return Some(Self::Empty);
242+
};
243+
244+
let [arg, rest @ ..] = args else {
245+
return None;
246+
};
247+
let result = match name {
238248
"panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
239249
"panic" | "panic_str" => Self::Str(arg),
240-
"panic_display" => {
250+
"panic_display" | "panic_cold_display" => {
241251
let ExprKind::AddrOf(_, _, e) = &arg.kind else {
242252
return None;
243253
};

src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
//@no-rustfix
55
use std::sync::atomic::Ordering; // #[non_exhaustive] enum
66

7+
fn repeat() -> ! {
8+
panic!()
9+
}
10+
711
pub fn f(x: Ordering) {
812
match x {
913
Ordering::Relaxed => println!("relaxed"),
1014
Ordering::Release => println!("release"),
1115
Ordering::Acquire => println!("acquire"),
12-
Ordering::AcqRel | Ordering::SeqCst => panic!(),
16+
Ordering::AcqRel | Ordering::SeqCst => repeat(),
1317
#[deny(non_exhaustive_omitted_patterns)]
14-
_ => panic!(),
18+
_ => repeat(),
1519
}
1620
}
1721

@@ -25,8 +29,8 @@ mod f {
2529
Ordering::Relaxed => println!("relaxed"),
2630
Ordering::Release => println!("release"),
2731
Ordering::Acquire => println!("acquire"),
28-
Ordering::AcqRel | Ordering::SeqCst => panic!(),
29-
_ => panic!(),
32+
Ordering::AcqRel | Ordering::SeqCst => repeat(),
33+
_ => repeat(),
3034
}
3135
}
3236
}
@@ -38,9 +42,9 @@ pub fn g(x: Ordering) {
3842
Ordering::Relaxed => println!("relaxed"),
3943
Ordering::Release => println!("release"),
4044
Ordering::Acquire => println!("acquire"),
41-
Ordering::AcqRel | Ordering::SeqCst => panic!(),
45+
Ordering::AcqRel | Ordering::SeqCst => repeat(),
4246
//~^ ERROR: this match arm has an identical body to the `_` wildcard arm
43-
_ => panic!(),
47+
_ => repeat(),
4448
}
4549
}
4650

@@ -52,9 +56,9 @@ mod g {
5256
Ordering::Relaxed => println!("relaxed"),
5357
Ordering::Release => println!("release"),
5458
Ordering::Acquire => println!("acquire"),
55-
Ordering::AcqRel | Ordering::SeqCst => panic!(),
59+
Ordering::AcqRel | Ordering::SeqCst => repeat(),
5660
//~^ ERROR: this match arm has an identical body to the `_` wildcard arm
57-
_ => panic!(),
61+
_ => repeat(),
5862
}
5963
}
6064
}

src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
error: this match arm has an identical body to the `_` wildcard arm
2-
--> $DIR/match_same_arms_non_exhaustive.rs:41:9
2+
--> $DIR/match_same_arms_non_exhaustive.rs:45:9
33
|
4-
LL | Ordering::AcqRel | Ordering::SeqCst => panic!(),
4+
LL | Ordering::AcqRel | Ordering::SeqCst => repeat(),
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
66
|
77
= help: or try changing either arm body
88
note: `_` wildcard arm here
9-
--> $DIR/match_same_arms_non_exhaustive.rs:43:9
9+
--> $DIR/match_same_arms_non_exhaustive.rs:47:9
1010
|
11-
LL | _ => panic!(),
11+
LL | _ => repeat(),
1212
| ^^^^^^^^^^^^^
1313
= note: `-D clippy::match-same-arms` implied by `-D warnings`
1414
= help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
1515

1616
error: this match arm has an identical body to the `_` wildcard arm
17-
--> $DIR/match_same_arms_non_exhaustive.rs:55:13
17+
--> $DIR/match_same_arms_non_exhaustive.rs:59:13
1818
|
19-
LL | Ordering::AcqRel | Ordering::SeqCst => panic!(),
19+
LL | Ordering::AcqRel | Ordering::SeqCst => repeat(),
2020
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
2121
|
2222
= help: or try changing either arm body
2323
note: `_` wildcard arm here
24-
--> $DIR/match_same_arms_non_exhaustive.rs:57:13
24+
--> $DIR/match_same_arms_non_exhaustive.rs:61:13
2525
|
26-
LL | _ => panic!(),
26+
LL | _ => repeat(),
2727
| ^^^^^^^^^^^^^
2828

2929
error: aborting due to 2 previous errors

0 commit comments

Comments
 (0)