diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index fab90e3cc5..60da1f1e6c 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -132,6 +132,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // This matches calls to the foreign item `panic_impl`. // The implementation is provided by the function with the `#[panic_handler]` attribute. "panic_impl" => { + this.check_panic_supported()?; let panic_impl_id = this.tcx.lang_items().panic_impl().unwrap(); let panic_impl_instance = ty::Instance::mono(*this.tcx, panic_impl_id); return Ok(Some(&*this.load_mir(panic_impl_instance.def, None)?)); diff --git a/src/shims/mod.rs b/src/shims/mod.rs index d9e4d226ec..5b5a11b86b 100644 --- a/src/shims/mod.rs +++ b/src/shims/mod.rs @@ -42,6 +42,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx return this.emulate_foreign_item(instance.def_id(), args, ret, unwind); } + // Better error message for panics on Windows. + let def_id = instance.def_id(); + if Some(def_id) == this.tcx.lang_items().begin_panic_fn() || + Some(def_id) == this.tcx.lang_items().panic_impl() + { + this.check_panic_supported()?; + } + // Otherwise, load the MIR. Ok(Some(&*this.load_mir(instance.def, None)?)) } diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 2f61ab6c39..8dded8bf40 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -32,6 +32,14 @@ pub struct CatchUnwindData<'tcx> { impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { + /// Check if panicking is supported on this platform, and give a good error otherwise. + fn check_panic_supported(&self) -> InterpResult<'tcx> { + match self.eval_context_ref().tcx.sess.target.target.target_os.as_str() { + "linux" | "macos" => Ok(()), + _ => throw_unsup_format!("panicking is not supported on this platform"), + } + } + /// Handles the special `miri_start_panic` intrinsic, which is called /// by libpanic_unwind to delegate the actual unwinding process to Miri. fn handle_miri_start_panic( diff --git a/tests/compile-fail/panic/windows1.rs b/tests/compile-fail/panic/windows1.rs new file mode 100644 index 0000000000..1d6faf1e75 --- /dev/null +++ b/tests/compile-fail/panic/windows1.rs @@ -0,0 +1,9 @@ +// ignore-linux +// ignore-macos + +// Test that panics on Windows give a reasonable error message. + +// error-pattern: panicking is not supported on this platform +fn main() { + core::panic!("this is {}", "Windows"); +} diff --git a/tests/compile-fail/panic/windows2.rs b/tests/compile-fail/panic/windows2.rs new file mode 100644 index 0000000000..023088a692 --- /dev/null +++ b/tests/compile-fail/panic/windows2.rs @@ -0,0 +1,9 @@ +// ignore-linux +// ignore-macos + +// Test that panics on Windows give a reasonable error message. + +// error-pattern: panicking is not supported on this platform +fn main() { + std::panic!("this is Windows"); +} diff --git a/tests/compile-fail/panic/windows3.rs b/tests/compile-fail/panic/windows3.rs new file mode 100644 index 0000000000..b96022fc4e --- /dev/null +++ b/tests/compile-fail/panic/windows3.rs @@ -0,0 +1,10 @@ +// ignore-linux +// ignore-macos + +// Test that panics on Windows give a reasonable error message. + +// error-pattern: panicking is not supported on this platform +#[allow(unconditional_panic)] +fn main() { + let _val = 1/0; +}