Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit a hard error when a panic occurs during const-eval #85704

Merged
merged 1 commit into from
May 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,12 @@ impl<T: Any> AsAny for T {
}

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

impl dyn MachineStopType {
#[inline(always)]
Expand Down
108 changes: 56 additions & 52 deletions compiler/rustc_mir/src/const_eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_span::{Span, Symbol};

use super::InterpCx;
use crate::interpret::{
struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine,
struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine, MachineStopType,
};

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

impl MachineStopType for ConstEvalErrKind {
fn is_hard_err(&self) -> bool {
match self {
Self::Panic { .. } => true,
_ => false,
}
}
}

// The errors become `MachineStop` with plain strings when being raised.
// `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to
// handle these.
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
fn into(self) -> InterpErrorInfo<'tcx> {
err_machine_stop!(self.to_string()).into()
err_machine_stop!(self).into()
}
}

Expand Down Expand Up @@ -148,31 +157,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
tcx: TyCtxtAt<'tcx>,
message: &str,
emit: impl FnOnce(DiagnosticBuilder<'_>),
lint_root: Option<hir::HirId>,
mut lint_root: Option<hir::HirId>,
) -> ErrorHandled {
let must_error = match self.error {
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
return ErrorHandled::TooGeneric;
}
err_inval!(AlreadyReported(error_reported)) => {
return ErrorHandled::Reported(error_reported);
}
// We must *always* hard error on these, even if the caller wants just a lint.
err_inval!(Layout(LayoutError::SizeOverflow(_))) => true,
_ => false,
};
trace!("reporting const eval failure at {:?}", self.span);

let err_msg = match &self.error {
InterpError::MachineStop(msg) => {
// A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`).
// Should be turned into a string by now.
msg.downcast_ref::<String>().expect("invalid MachineStop payload").clone()
}
err => err.to_string(),
};

let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option<String>| {
trace!("reporting const eval failure at {:?}", self.span);
if let Some(span_msg) = span_msg {
err.span_label(self.span, span_msg);
}
Expand All @@ -186,34 +174,50 @@ impl<'tcx> ConstEvalErr<'tcx> {
emit(err)
};

if must_error {
// The `message` makes little sense here, this is a more serious error than the
// caller thinks anyway.
// See <https://github.com/rust-lang/rust/pull/63152>.
finish(struct_error(tcx, &err_msg), None);
ErrorHandled::Reported(ErrorReported)
} else {
// Regular case.
if let Some(lint_root) = lint_root {
// Report as lint.
let hir_id = self
.stacktrace
.iter()
.rev()
.find_map(|frame| frame.lint_root)
.unwrap_or(lint_root);
tcx.struct_span_lint_hir(
rustc_session::lint::builtin::CONST_ERR,
hir_id,
tcx.span,
|lint| finish(lint.build(message), Some(err_msg)),
);
ErrorHandled::Linted
} else {
// Report as hard error.
finish(struct_error(tcx, message), Some(err_msg));
ErrorHandled::Reported(ErrorReported)
// Special handling for certain errors
match &self.error {
// Don't emit a new diagnostic for these errors
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
return ErrorHandled::TooGeneric;
}
err_inval!(AlreadyReported(error_reported)) => {
return ErrorHandled::Reported(*error_reported);
}
err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
// We must *always* hard error on these, even if the caller wants just a lint.
// The `message` makes little sense here, this is a more serious error than the
// caller thinks anyway.
// See <https://github.com/rust-lang/rust/pull/63152>.
finish(struct_error(tcx, &self.error.to_string()), None);
return ErrorHandled::Reported(ErrorReported);
}
_ => {}
};

// If we have a 'hard error', then set `lint_root` to `None` so that we don't
// emit a lint.
if matches!(&self.error, InterpError::MachineStop(err) if err.is_hard_err()) {
lint_root = None;
}

let err_msg = self.error.to_string();

// Regular case - emit a lint.
if let Some(lint_root) = lint_root {
// Report as lint.
let hir_id =
self.stacktrace.iter().rev().find_map(|frame| frame.lint_root).unwrap_or(lint_root);
tcx.struct_span_lint_hir(
rustc_session::lint::builtin::CONST_ERR,
hir_id,
tcx.span,
|lint| finish(lint.build(message), Some(err_msg)),
);
ErrorHandled::Linted
} else {
// Report as hard error.
finish(struct_error(tcx, message), Some(err_msg));
ErrorHandled::Reported(ErrorReported)
}
}
}
10 changes: 0 additions & 10 deletions src/test/ui/consts/const-eval/const_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,30 @@ const MSG: &str = "hello";

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

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

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

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

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

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

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

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

const W_CORE: () = core::panic!(MSG);
//~^ ERROR any use of this value will cause an error
//~| WARN this was previously accepted by the compiler but is being phased out
78 changes: 29 additions & 49 deletions src/test/ui/consts/const-eval/const_panic.stderr
Original file line number Diff line number Diff line change
@@ -1,123 +1,103 @@
error: any use of this value will cause an error
error[E0080]: any use of this value will cause an error
--> $DIR/const_panic.rs:7:15
|
LL | const Z: () = std::panic!("cheese");
| --------------^^^^^^^^^^^^^^^^^^^^^-
| |
| the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

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

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

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

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

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

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

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

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

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

error: aborting due to 10 previous errors

For more information about this error, try `rustc --explain E0080`.
3 changes: 0 additions & 3 deletions src/test/ui/consts/const-eval/const_panic_libcore_bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ use core::panic::PanicInfo;

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

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

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

#[lang = "eh_personality"]
fn eh() {}
Expand Down
Loading