Auto merge of #72204 - RalfJung:abort, r=Mark-Simulacrum
make abort intrinsic safe, and correct its documentation Turns out `std::process::abort` is not the same as the intrinsic, the comment was just wrong. Quoting from the unix implementation: ``` // On Unix-like platforms, libc::abort will unregister signal handlers // including the SIGABRT handler, preventing the abort from being blocked, and // fclose streams, with the side effect of flushing them so libc buffered // output will be printed. Additionally the shell will generally print a more // understandable error message like "Abort trap" rather than "Illegal // instruction" that intrinsics::abort would cause, as intrinsics::abort is // implemented as an illegal instruction. ```
This commit is contained in:
commit
34cce58d81
|
@ -2027,6 +2027,8 @@ trait RcBoxPtr<T: ?Sized> {
|
||||||
// nevertheless, we insert an abort here to hint LLVM at
|
// nevertheless, we insert an abort here to hint LLVM at
|
||||||
// an otherwise missed optimization.
|
// an otherwise missed optimization.
|
||||||
if strong == 0 || strong == usize::max_value() {
|
if strong == 0 || strong == usize::max_value() {
|
||||||
|
// remove `unsafe` on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -2053,6 +2055,8 @@ trait RcBoxPtr<T: ?Sized> {
|
||||||
// nevertheless, we insert an abort here to hint LLVM at
|
// nevertheless, we insert an abort here to hint LLVM at
|
||||||
// an otherwise missed optimization.
|
// an otherwise missed optimization.
|
||||||
if weak == 0 || weak == usize::max_value() {
|
if weak == 0 || weak == usize::max_value() {
|
||||||
|
// remove `unsafe` on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1096,6 +1096,8 @@ impl<T: ?Sized> Clone for Arc<T> {
|
||||||
// We abort because such a program is incredibly degenerate, and we
|
// We abort because such a program is incredibly degenerate, and we
|
||||||
// don't care to support it.
|
// don't care to support it.
|
||||||
if old_size > MAX_REFCOUNT {
|
if old_size > MAX_REFCOUNT {
|
||||||
|
// remove `unsafe` on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -1614,6 +1616,8 @@ impl<T: ?Sized> Weak<T> {
|
||||||
|
|
||||||
// See comments in `Arc::clone` for why we do this (for `mem::forget`).
|
// See comments in `Arc::clone` for why we do this (for `mem::forget`).
|
||||||
if n > MAX_REFCOUNT {
|
if n > MAX_REFCOUNT {
|
||||||
|
// remove `unsafe` on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -1753,6 +1757,7 @@ impl<T: ?Sized> Clone for Weak<T> {
|
||||||
|
|
||||||
// See comments in Arc::clone() for why we do this (for mem::forget).
|
// See comments in Arc::clone() for why we do this (for mem::forget).
|
||||||
if old_size > MAX_REFCOUNT {
|
if old_size > MAX_REFCOUNT {
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,10 +133,9 @@
|
||||||
//! `Cell<T>`.
|
//! `Cell<T>`.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! #![feature(core_intrinsics)]
|
|
||||||
//! use std::cell::Cell;
|
//! use std::cell::Cell;
|
||||||
//! use std::ptr::NonNull;
|
//! use std::ptr::NonNull;
|
||||||
//! use std::intrinsics::abort;
|
//! use std::process::abort;
|
||||||
//! use std::marker::PhantomData;
|
//! use std::marker::PhantomData;
|
||||||
//!
|
//!
|
||||||
//! struct Rc<T: ?Sized> {
|
//! struct Rc<T: ?Sized> {
|
||||||
|
@ -173,7 +172,7 @@
|
||||||
//! .strong
|
//! .strong
|
||||||
//! .set(self.strong()
|
//! .set(self.strong()
|
||||||
//! .checked_add(1)
|
//! .checked_add(1)
|
||||||
//! .unwrap_or_else(|| unsafe { abort() }));
|
//! .unwrap_or_else(|| abort() ));
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -918,7 +918,7 @@ extern "rust-intrinsic" {
|
||||||
|
|
||||||
/// Aborts the execution of the process.
|
/// Aborts the execution of the process.
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is
|
/// A more user-friendly and stable version of this operation is
|
||||||
/// [`std::process::abort`](../../std/process/fn.abort.html).
|
/// [`std::process::abort`](../../std/process/fn.abort.html).
|
||||||
pub fn abort() -> !;
|
pub fn abort() -> !;
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,12 @@ use crate::panic::{Location, PanicInfo};
|
||||||
#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
|
#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
|
||||||
pub fn panic(expr: &str) -> ! {
|
pub fn panic(expr: &str) -> ! {
|
||||||
if cfg!(feature = "panic_immediate_abort") {
|
if cfg!(feature = "panic_immediate_abort") {
|
||||||
|
// remove `unsafe` (and safety comment) on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
// SAFETY: the `abort` intrinsic has no requirements to be called.
|
// SAFETY: the `abort` intrinsic has no requirements to be called.
|
||||||
unsafe { super::intrinsics::abort() }
|
unsafe {
|
||||||
|
super::intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
|
// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
|
||||||
|
@ -58,8 +62,12 @@ pub fn panic(expr: &str) -> ! {
|
||||||
#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
|
#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
|
||||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||||
if cfg!(feature = "panic_immediate_abort") {
|
if cfg!(feature = "panic_immediate_abort") {
|
||||||
|
// remove `unsafe` (and safety comment) on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
// SAFETY: the `abort` intrinsic has no requirements to be called.
|
// SAFETY: the `abort` intrinsic has no requirements to be called.
|
||||||
unsafe { super::intrinsics::abort() }
|
unsafe {
|
||||||
|
super::intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("index out of bounds: the len is {} but the index is {}", len, index)
|
panic!("index out of bounds: the len is {} but the index is {}", len, index)
|
||||||
|
@ -72,8 +80,12 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||||
if cfg!(feature = "panic_immediate_abort") {
|
if cfg!(feature = "panic_immediate_abort") {
|
||||||
|
// remove `unsafe` (and safety comment) on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
// SAFETY: the `abort` intrinsic has no requirements to be called.
|
// SAFETY: the `abort` intrinsic has no requirements to be called.
|
||||||
unsafe { super::intrinsics::abort() }
|
unsafe {
|
||||||
|
super::intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
|
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
|
||||||
|
|
|
@ -327,5 +327,8 @@ pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
|
||||||
#[lang = "eh_personality"]
|
#[lang = "eh_personality"]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
fn rust_eh_personality() {
|
fn rust_eh_personality() {
|
||||||
unsafe { core::intrinsics::abort() }
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
|
||||||
|
unsafe {
|
||||||
|
core::intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ fn equate_intrinsic_type<'tcx>(
|
||||||
/// Returns `true` if the given intrinsic is unsafe to call or not.
|
/// Returns `true` if the given intrinsic is unsafe to call or not.
|
||||||
pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
|
pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
|
||||||
match intrinsic {
|
match intrinsic {
|
||||||
"size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val"
|
"abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val"
|
||||||
| "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow"
|
| "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow"
|
||||||
| "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
|
| "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
|
||||||
| "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
|
| "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
|
||||||
|
@ -130,7 +130,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(n_tps, inputs, output, hir::Unsafety::Unsafe)
|
(n_tps, inputs, output, hir::Unsafety::Unsafe)
|
||||||
} else if &name[..] == "abort" || &name[..] == "unreachable" {
|
} else if &name[..] == "abort" {
|
||||||
|
(0, Vec::new(), tcx.types.never, hir::Unsafety::Normal)
|
||||||
|
} else if &name[..] == "unreachable" {
|
||||||
(0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
|
(0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
|
||||||
} else {
|
} else {
|
||||||
let unsafety = intrinsic_operation_unsafety(&name[..]);
|
let unsafety = intrinsic_operation_unsafety(&name[..]);
|
||||||
|
|
|
@ -332,7 +332,10 @@ pub fn panicking() -> bool {
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! {
|
pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! {
|
||||||
if cfg!(feature = "panic_immediate_abort") {
|
if cfg!(feature = "panic_immediate_abort") {
|
||||||
unsafe { intrinsics::abort() }
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
|
||||||
|
unsafe {
|
||||||
|
intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let info = PanicInfo::internal_constructor(Some(msg), Location::caller());
|
let info = PanicInfo::internal_constructor(Some(msg), Location::caller());
|
||||||
|
@ -398,7 +401,10 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
pub fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
||||||
if cfg!(feature = "panic_immediate_abort") {
|
if cfg!(feature = "panic_immediate_abort") {
|
||||||
unsafe { intrinsics::abort() }
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
|
||||||
|
unsafe {
|
||||||
|
intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_panic_with_hook(&mut PanicPayload::new(msg), None, Location::caller());
|
rust_panic_with_hook(&mut PanicPayload::new(msg), None, Location::caller());
|
||||||
|
@ -458,7 +464,10 @@ fn rust_panic_with_hook(
|
||||||
"thread panicked while processing \
|
"thread panicked while processing \
|
||||||
panic. aborting.\n"
|
panic. aborting.\n"
|
||||||
));
|
));
|
||||||
unsafe { intrinsics::abort() }
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
|
||||||
|
unsafe {
|
||||||
|
intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -493,7 +502,10 @@ fn rust_panic_with_hook(
|
||||||
"thread panicked while panicking. \
|
"thread panicked while panicking. \
|
||||||
aborting.\n"
|
aborting.\n"
|
||||||
));
|
));
|
||||||
unsafe { intrinsics::abort() }
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump
|
||||||
|
unsafe {
|
||||||
|
intrinsics::abort()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_panic(payload)
|
rust_panic(payload)
|
||||||
|
|
|
@ -354,6 +354,8 @@ impl<T> Packet<T> {
|
||||||
|
|
||||||
// See comments on Arc::clone() on why we do this (for `mem::forget`).
|
// See comments on Arc::clone() on why we do this (for `mem::forget`).
|
||||||
if old_count > MAX_REFCOUNT {
|
if old_count > MAX_REFCOUNT {
|
||||||
|
// remove `unsafe` on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,6 +358,8 @@ impl<T> Packet<T> {
|
||||||
|
|
||||||
// See comments on Arc::clone() on why we do this (for `mem::forget`).
|
// See comments on Arc::clone() on why we do this (for `mem::forget`).
|
||||||
if old_count > MAX_REFCOUNT {
|
if old_count > MAX_REFCOUNT {
|
||||||
|
// remove `unsafe` on bootstrap bump
|
||||||
|
#[cfg_attr(not(bootstrap), allow(unused_unsafe))]
|
||||||
unsafe {
|
unsafe {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue