Skip to content

Commit d9feaaa

Browse files
committed
Auto merge of #85704 - Aaron1011:const-panic-hard-err, r=RalfJung
Emit a hard error when a panic occurs during const-eval Previous, a panic during const evaluation would go through the `const_err` lint. This PR ensures that such a panic always causes compilation to fail.
2 parents 91ddf3e + 2779fc1 commit d9feaaa

15 files changed

+118
-182
lines changed

compiler/rustc_middle/src/mir/interpret/error.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,12 @@ impl<T: Any> AsAny for T {
435435
}
436436

437437
/// A trait for machine-specific errors (or other "machine stop" conditions).
438-
pub trait MachineStopType: AsAny + fmt::Display + Send {}
439-
impl MachineStopType for String {}
438+
pub trait MachineStopType: AsAny + fmt::Display + Send {
439+
/// If `true`, emit a hard error instead of going through the `CONST_ERR` lint
440+
fn is_hard_err(&self) -> bool {
441+
false
442+
}
443+
}
440444

441445
impl dyn MachineStopType {
442446
#[inline(always)]

compiler/rustc_mir/src/const_eval/error.rs

+56-52
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_span::{Span, Symbol};
99

1010
use super::InterpCx;
1111
use crate::interpret::{
12-
struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine,
12+
struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine, MachineStopType,
1313
};
1414

1515
/// The CTFE machine has some custom error kinds.
@@ -24,12 +24,21 @@ pub enum ConstEvalErrKind {
2424
Abort(String),
2525
}
2626

27+
impl MachineStopType for ConstEvalErrKind {
28+
fn is_hard_err(&self) -> bool {
29+
match self {
30+
Self::Panic { .. } => true,
31+
_ => false,
32+
}
33+
}
34+
}
35+
2736
// The errors become `MachineStop` with plain strings when being raised.
2837
// `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to
2938
// handle these.
3039
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
3140
fn into(self) -> InterpErrorInfo<'tcx> {
32-
err_machine_stop!(self.to_string()).into()
41+
err_machine_stop!(self).into()
3342
}
3443
}
3544

@@ -148,31 +157,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
148157
tcx: TyCtxtAt<'tcx>,
149158
message: &str,
150159
emit: impl FnOnce(DiagnosticBuilder<'_>),
151-
lint_root: Option<hir::HirId>,
160+
mut lint_root: Option<hir::HirId>,
152161
) -> ErrorHandled {
153-
let must_error = match self.error {
154-
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
155-
return ErrorHandled::TooGeneric;
156-
}
157-
err_inval!(AlreadyReported(error_reported)) => {
158-
return ErrorHandled::Reported(error_reported);
159-
}
160-
// We must *always* hard error on these, even if the caller wants just a lint.
161-
err_inval!(Layout(LayoutError::SizeOverflow(_))) => true,
162-
_ => false,
163-
};
164-
trace!("reporting const eval failure at {:?}", self.span);
165-
166-
let err_msg = match &self.error {
167-
InterpError::MachineStop(msg) => {
168-
// A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`).
169-
// Should be turned into a string by now.
170-
msg.downcast_ref::<String>().expect("invalid MachineStop payload").clone()
171-
}
172-
err => err.to_string(),
173-
};
174-
175162
let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option<String>| {
163+
trace!("reporting const eval failure at {:?}", self.span);
176164
if let Some(span_msg) = span_msg {
177165
err.span_label(self.span, span_msg);
178166
}
@@ -186,34 +174,50 @@ impl<'tcx> ConstEvalErr<'tcx> {
186174
emit(err)
187175
};
188176

189-
if must_error {
190-
// The `message` makes little sense here, this is a more serious error than the
191-
// caller thinks anyway.
192-
// See <https://github.com/rust-lang/rust/pull/63152>.
193-
finish(struct_error(tcx, &err_msg), None);
194-
ErrorHandled::Reported(ErrorReported)
195-
} else {
196-
// Regular case.
197-
if let Some(lint_root) = lint_root {
198-
// Report as lint.
199-
let hir_id = self
200-
.stacktrace
201-
.iter()
202-
.rev()
203-
.find_map(|frame| frame.lint_root)
204-
.unwrap_or(lint_root);
205-
tcx.struct_span_lint_hir(
206-
rustc_session::lint::builtin::CONST_ERR,
207-
hir_id,
208-
tcx.span,
209-
|lint| finish(lint.build(message), Some(err_msg)),
210-
);
211-
ErrorHandled::Linted
212-
} else {
213-
// Report as hard error.
214-
finish(struct_error(tcx, message), Some(err_msg));
215-
ErrorHandled::Reported(ErrorReported)
177+
// Special handling for certain errors
178+
match &self.error {
179+
// Don't emit a new diagnostic for these errors
180+
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
181+
return ErrorHandled::TooGeneric;
182+
}
183+
err_inval!(AlreadyReported(error_reported)) => {
184+
return ErrorHandled::Reported(*error_reported);
185+
}
186+
err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
187+
// We must *always* hard error on these, even if the caller wants just a lint.
188+
// The `message` makes little sense here, this is a more serious error than the
189+
// caller thinks anyway.
190+
// See <https://github.com/rust-lang/rust/pull/63152>.
191+
finish(struct_error(tcx, &self.error.to_string()), None);
192+
return ErrorHandled::Reported(ErrorReported);
216193
}
194+
_ => {}
195+
};
196+
197+
// If we have a 'hard error', then set `lint_root` to `None` so that we don't
198+
// emit a lint.
199+
if matches!(&self.error, InterpError::MachineStop(err) if err.is_hard_err()) {
200+
lint_root = None;
201+
}
202+
203+
let err_msg = self.error.to_string();
204+
205+
// Regular case - emit a lint.
206+
if let Some(lint_root) = lint_root {
207+
// Report as lint.
208+
let hir_id =
209+
self.stacktrace.iter().rev().find_map(|frame| frame.lint_root).unwrap_or(lint_root);
210+
tcx.struct_span_lint_hir(
211+
rustc_session::lint::builtin::CONST_ERR,
212+
hir_id,
213+
tcx.span,
214+
|lint| finish(lint.build(message), Some(err_msg)),
215+
);
216+
ErrorHandled::Linted
217+
} else {
218+
// Report as hard error.
219+
finish(struct_error(tcx, message), Some(err_msg));
220+
ErrorHandled::Reported(ErrorReported)
217221
}
218222
}
219223
}

src/test/ui/consts/const-eval/const_panic.rs

-10
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,30 @@ const MSG: &str = "hello";
66

77
const Z: () = std::panic!("cheese");
88
//~^ ERROR any use of this value will cause an error
9-
//~| WARN this was previously accepted by the compiler but is being phased out
109

1110
const Z2: () = std::panic!();
1211
//~^ ERROR any use of this value will cause an error
13-
//~| WARN this was previously accepted by the compiler but is being phased out
1412

1513
const Y: () = std::unreachable!();
1614
//~^ ERROR any use of this value will cause an error
17-
//~| WARN this was previously accepted by the compiler but is being phased out
1815

1916
const X: () = std::unimplemented!();
2017
//~^ ERROR any use of this value will cause an error
21-
//~| WARN this was previously accepted by the compiler but is being phased out
2218
//
2319
const W: () = std::panic!(MSG);
2420
//~^ ERROR any use of this value will cause an error
25-
//~| WARN this was previously accepted by the compiler but is being phased out
2621

2722
const Z_CORE: () = core::panic!("cheese");
2823
//~^ ERROR any use of this value will cause an error
29-
//~| WARN this was previously accepted by the compiler but is being phased out
3024

3125
const Z2_CORE: () = core::panic!();
3226
//~^ ERROR any use of this value will cause an error
33-
//~| WARN this was previously accepted by the compiler but is being phased out
3427

3528
const Y_CORE: () = core::unreachable!();
3629
//~^ ERROR any use of this value will cause an error
37-
//~| WARN this was previously accepted by the compiler but is being phased out
3830

3931
const X_CORE: () = core::unimplemented!();
4032
//~^ ERROR any use of this value will cause an error
41-
//~| WARN this was previously accepted by the compiler but is being phased out
4233

4334
const W_CORE: () = core::panic!(MSG);
4435
//~^ ERROR any use of this value will cause an error
45-
//~| WARN this was previously accepted by the compiler but is being phased out
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,103 @@
1-
error: any use of this value will cause an error
1+
error[E0080]: any use of this value will cause an error
22
--> $DIR/const_panic.rs:7:15
33
|
44
LL | const Z: () = std::panic!("cheese");
55
| --------------^^^^^^^^^^^^^^^^^^^^^-
66
| |
77
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15
88
|
9-
= note: `#[deny(const_err)]` on by default
10-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
11-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
129
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
1310

14-
error: any use of this value will cause an error
15-
--> $DIR/const_panic.rs:11:16
11+
error[E0080]: any use of this value will cause an error
12+
--> $DIR/const_panic.rs:10:16
1613
|
1714
LL | const Z2: () = std::panic!();
1815
| ---------------^^^^^^^^^^^^^-
1916
| |
20-
| the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:11:16
17+
| the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16
2118
|
22-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
23-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
2419
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
2520

26-
error: any use of this value will cause an error
27-
--> $DIR/const_panic.rs:15:15
21+
error[E0080]: any use of this value will cause an error
22+
--> $DIR/const_panic.rs:13:15
2823
|
2924
LL | const Y: () = std::unreachable!();
3025
| --------------^^^^^^^^^^^^^^^^^^^-
3126
| |
32-
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:15:15
27+
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:13:15
3328
|
34-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
35-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
3629
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
3730

38-
error: any use of this value will cause an error
39-
--> $DIR/const_panic.rs:19:15
31+
error[E0080]: any use of this value will cause an error
32+
--> $DIR/const_panic.rs:16:15
4033
|
4134
LL | const X: () = std::unimplemented!();
4235
| --------------^^^^^^^^^^^^^^^^^^^^^-
4336
| |
44-
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:19:15
37+
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:16:15
4538
|
46-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
47-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
4839
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
4940

50-
error: any use of this value will cause an error
51-
--> $DIR/const_panic.rs:23:15
41+
error[E0080]: any use of this value will cause an error
42+
--> $DIR/const_panic.rs:19:15
5243
|
5344
LL | const W: () = std::panic!(MSG);
5445
| --------------^^^^^^^^^^^^^^^^-
5546
| |
56-
| the evaluated program panicked at 'hello', $DIR/const_panic.rs:23:15
47+
| the evaluated program panicked at 'hello', $DIR/const_panic.rs:19:15
5748
|
58-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
59-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
6049
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
6150

62-
error: any use of this value will cause an error
63-
--> $DIR/const_panic.rs:27:20
51+
error[E0080]: any use of this value will cause an error
52+
--> $DIR/const_panic.rs:22:20
6453
|
6554
LL | const Z_CORE: () = core::panic!("cheese");
6655
| -------------------^^^^^^^^^^^^^^^^^^^^^^-
6756
| |
68-
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:27:20
57+
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
6958
|
70-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
71-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
7259
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
7360

74-
error: any use of this value will cause an error
75-
--> $DIR/const_panic.rs:31:21
61+
error[E0080]: any use of this value will cause an error
62+
--> $DIR/const_panic.rs:25:21
7663
|
7764
LL | const Z2_CORE: () = core::panic!();
7865
| --------------------^^^^^^^^^^^^^^-
7966
| |
80-
| the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:31:21
67+
| the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
8168
|
82-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
83-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
8469
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
8570

86-
error: any use of this value will cause an error
87-
--> $DIR/const_panic.rs:35:20
71+
error[E0080]: any use of this value will cause an error
72+
--> $DIR/const_panic.rs:28:20
8873
|
8974
LL | const Y_CORE: () = core::unreachable!();
9075
| -------------------^^^^^^^^^^^^^^^^^^^^-
9176
| |
92-
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:35:20
77+
| the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
9378
|
94-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
95-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
9679
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
9780

98-
error: any use of this value will cause an error
99-
--> $DIR/const_panic.rs:39:20
81+
error[E0080]: any use of this value will cause an error
82+
--> $DIR/const_panic.rs:31:20
10083
|
10184
LL | const X_CORE: () = core::unimplemented!();
10285
| -------------------^^^^^^^^^^^^^^^^^^^^^^-
10386
| |
104-
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:39:20
87+
| the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
10588
|
106-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
107-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
10889
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
10990

110-
error: any use of this value will cause an error
111-
--> $DIR/const_panic.rs:43:20
91+
error[E0080]: any use of this value will cause an error
92+
--> $DIR/const_panic.rs:34:20
11293
|
11394
LL | const W_CORE: () = core::panic!(MSG);
11495
| -------------------^^^^^^^^^^^^^^^^^-
11596
| |
116-
| the evaluated program panicked at 'hello', $DIR/const_panic.rs:43:20
97+
| the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
11798
|
118-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
119-
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
12099
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
121100

122101
error: aborting due to 10 previous errors
123102

103+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/const-eval/const_panic_libcore_bin.rs

-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ use core::panic::PanicInfo;
88

99
const Z: () = panic!("cheese");
1010
//~^ ERROR any use of this value will cause an error
11-
//~| WARN this was previously accepted by the compiler but is being phased out
1211

1312
const Y: () = unreachable!();
1413
//~^ ERROR any use of this value will cause an error
15-
//~| WARN this was previously accepted by the compiler but is being phased out
1614

1715
const X: () = unimplemented!();
1816
//~^ ERROR any use of this value will cause an error
19-
//~| WARN this was previously accepted by the compiler but is being phased out
2017

2118
#[lang = "eh_personality"]
2219
fn eh() {}

0 commit comments

Comments
 (0)