Auto merge of #121655 - matthiaskrgr:rollup-qpx3kks, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #121598 (rename 'try' intrinsic to 'catch_unwind') - #121639 (Update books) - #121648 (Update Vec and String `{from,into}_raw_parts`-family docs) - #121651 (Properly emit `expected ;` on `#[attr] expr`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
71ffdf7ff7
36 changed files with 123 additions and 72 deletions
|
@ -23,7 +23,7 @@ use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
|
||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::GenericArgsRef;
|
use rustc_middle::ty::GenericArgsRef;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
|
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -1132,7 +1132,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||||
ret.write_cvalue(fx, val);
|
ret.write_cvalue(fx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
kw::Try => {
|
sym::catch_unwind => {
|
||||||
intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic);
|
intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic);
|
||||||
let f = f.load_scalar(fx);
|
let f = f.load_scalar(fx);
|
||||||
let data = data.load_scalar(fx);
|
let data = data.load_scalar(fx);
|
||||||
|
|
|
@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Instance, Ty};
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
#[cfg(feature="master")]
|
#[cfg(feature="master")]
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||||
use rustc_span::{Span, Symbol, symbol::kw, sym};
|
use rustc_span::{Span, Symbol, sym};
|
||||||
use rustc_target::abi::HasDataLayout;
|
use rustc_target::abi::HasDataLayout;
|
||||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
|
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
|
||||||
use rustc_target::spec::PanicStrategy;
|
use rustc_target::spec::PanicStrategy;
|
||||||
|
@ -129,7 +129,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||||
let res = self.context.new_call(None, builtin, &[a]);
|
let res = self.context.new_call(None, builtin, &[a]);
|
||||||
self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
|
self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
|
||||||
}
|
}
|
||||||
kw::Try => {
|
sym::catch_unwind => {
|
||||||
try_intrinsic(
|
try_intrinsic(
|
||||||
self,
|
self,
|
||||||
args[0].immediate(),
|
args[0].immediate(),
|
||||||
|
|
|
@ -17,7 +17,7 @@ use rustc_hir as hir;
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
|
||||||
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
use rustc_middle::ty::{self, GenericArgsRef, Ty};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::{sym, symbol::kw, Span, Symbol};
|
use rustc_span::{sym, Span, Symbol};
|
||||||
use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
|
use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
|
||||||
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
||||||
|
|
||||||
|
@ -133,8 +133,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
sym::unlikely => self
|
sym::unlikely => self
|
||||||
.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
|
.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
|
||||||
kw::Try => {
|
sym::catch_unwind => {
|
||||||
try_intrinsic(
|
catch_unwind_intrinsic(
|
||||||
self,
|
self,
|
||||||
args[0].immediate(),
|
args[0].immediate(),
|
||||||
args[1].immediate(),
|
args[1].immediate(),
|
||||||
|
@ -457,7 +457,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_intrinsic<'ll>(
|
fn catch_unwind_intrinsic<'ll>(
|
||||||
bx: &mut Builder<'_, 'll, '_>,
|
bx: &mut Builder<'_, 'll, '_>,
|
||||||
try_func: &'ll Value,
|
try_func: &'ll Value,
|
||||||
data: &'ll Value,
|
data: &'ll Value,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rustc_hir as hir;
|
||||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ pub fn check_intrinsic_type(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
kw::Try => {
|
sym::catch_unwind => {
|
||||||
let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8);
|
let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8);
|
||||||
let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
|
let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
|
||||||
[mut_u8],
|
[mut_u8],
|
||||||
|
|
|
@ -800,9 +800,8 @@ impl<'a> Parser<'a> {
|
||||||
{
|
{
|
||||||
Ok(next_attr) => next_attr,
|
Ok(next_attr) => next_attr,
|
||||||
Err(inner_err) => {
|
Err(inner_err) => {
|
||||||
err.cancel();
|
|
||||||
inner_err.cancel();
|
inner_err.cancel();
|
||||||
return self.dcx().span_delayed_bug(expr.span, "not a tail expression");
|
return err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&& let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
|
&& let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
|
||||||
|
@ -813,9 +812,8 @@ impl<'a> Parser<'a> {
|
||||||
let next_expr = match snapshot.parse_expr() {
|
let next_expr = match snapshot.parse_expr() {
|
||||||
Ok(next_expr) => next_expr,
|
Ok(next_expr) => next_expr,
|
||||||
Err(inner_err) => {
|
Err(inner_err) => {
|
||||||
err.cancel();
|
|
||||||
inner_err.cancel();
|
inner_err.cancel();
|
||||||
return self.dcx().span_delayed_bug(expr.span, "not a tail expression");
|
return err.emit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// We have for sure
|
// We have for sure
|
||||||
|
|
|
@ -487,6 +487,7 @@ symbols! {
|
||||||
call_once,
|
call_once,
|
||||||
caller_location,
|
caller_location,
|
||||||
capture_disjoint_fields,
|
capture_disjoint_fields,
|
||||||
|
catch_unwind,
|
||||||
cause,
|
cause,
|
||||||
cdylib,
|
cdylib,
|
||||||
ceilf32,
|
ceilf32,
|
||||||
|
|
|
@ -864,7 +864,7 @@ impl String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decomposes a `String` into its raw components.
|
/// Decomposes a `String` into its raw components: `(pointer, length, capacity)`.
|
||||||
///
|
///
|
||||||
/// Returns the raw pointer to the underlying data, the length of
|
/// Returns the raw pointer to the underlying data, the length of
|
||||||
/// the string (in bytes), and the allocated capacity of the data
|
/// the string (in bytes), and the allocated capacity of the data
|
||||||
|
@ -896,7 +896,7 @@ impl String {
|
||||||
self.vec.into_raw_parts()
|
self.vec.into_raw_parts()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `String` from a length, capacity, and pointer.
|
/// Creates a new `String` from a pointer, a length and a capacity.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
|
|
|
@ -481,7 +481,7 @@ impl<T> Vec<T> {
|
||||||
Self::with_capacity_in(capacity, Global)
|
Self::with_capacity_in(capacity, Global)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `Vec<T>` directly from a pointer, a capacity, and a length.
|
/// Creates a `Vec<T>` directly from a pointer, a length, and a capacity.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
|
@ -672,7 +672,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
|
Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `Vec<T, A>` directly from a pointer, a capacity, a length,
|
/// Creates a `Vec<T, A>` directly from a pointer, a length, a capacity,
|
||||||
/// and an allocator.
|
/// and an allocator.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
@ -786,7 +786,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } }
|
unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decomposes a `Vec<T>` into its raw components.
|
/// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity)`.
|
||||||
///
|
///
|
||||||
/// Returns the raw pointer to the underlying data, the length of
|
/// Returns the raw pointer to the underlying data, the length of
|
||||||
/// the vector (in elements), and the allocated capacity of the
|
/// the vector (in elements), and the allocated capacity of the
|
||||||
|
@ -824,7 +824,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
(me.as_mut_ptr(), me.len(), me.capacity())
|
(me.as_mut_ptr(), me.len(), me.capacity())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decomposes a `Vec<T>` into its raw components.
|
/// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity, allocator)`.
|
||||||
///
|
///
|
||||||
/// Returns the raw pointer to the underlying data, the length of the vector (in elements),
|
/// Returns the raw pointer to the underlying data, the length of the vector (in elements),
|
||||||
/// the allocated capacity of the data (in elements), and the allocator. These are the same
|
/// the allocated capacity of the data (in elements), and the allocator. These are the same
|
||||||
|
|
|
@ -75,6 +75,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||||
unsafe { crate::ptr::drop_in_place(to_drop) }
|
unsafe { crate::ptr::drop_in_place(to_drop) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
|
pub use self::r#try as catch_unwind;
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
// N.B., these intrinsics take raw pointers because they mutate aliased
|
// N.B., these intrinsics take raw pointers because they mutate aliased
|
||||||
// memory, which is not valid for either `&` or `&mut`.
|
// memory, which is not valid for either `&` or `&mut`.
|
||||||
|
@ -2382,16 +2385,24 @@ extern "rust-intrinsic" {
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn variant_count<T>() -> usize;
|
pub fn variant_count<T>() -> usize;
|
||||||
|
|
||||||
/// Rust's "try catch" construct which invokes the function pointer `try_fn`
|
/// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
|
||||||
/// with the data pointer `data`.
|
/// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
|
||||||
///
|
|
||||||
/// The third argument is a function called if a panic occurs. This function
|
|
||||||
/// takes the data pointer and a pointer to the target-specific exception
|
|
||||||
/// object that was caught. For more information see the compiler's
|
|
||||||
/// source as well as std's catch implementation.
|
|
||||||
///
|
///
|
||||||
/// `catch_fn` must not unwind.
|
/// `catch_fn` must not unwind.
|
||||||
|
///
|
||||||
|
/// The third argument is a function called if an unwind occurs (both Rust unwinds and foreign
|
||||||
|
/// unwinds). This function takes the data pointer and a pointer to the target-specific
|
||||||
|
/// exception object that was caught. For more information, see the compiler's source as well as
|
||||||
|
/// std's `catch_unwind` implementation.
|
||||||
|
///
|
||||||
|
/// The stable version of this intrinsic is `std::panic::catch_unwind`.
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
|
||||||
|
|
||||||
|
/// For bootstrap only, see `catch_unwind`.
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[cfg(bootstrap)]
|
||||||
pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
|
pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
|
||||||
|
|
||||||
/// Emits a `!nontemporal` store according to LLVM (see their docs).
|
/// Emits a `!nontemporal` store according to LLVM (see their docs).
|
||||||
|
|
|
@ -8,14 +8,14 @@ type Payload = Box<Box<dyn Any + Send>>;
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
/// Miri-provided extern function to begin unwinding.
|
/// Miri-provided extern function to begin unwinding.
|
||||||
fn miri_start_panic(payload: *mut u8) -> !;
|
fn miri_start_unwind(payload: *mut u8) -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
|
pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
|
||||||
// The payload we pass to `miri_start_panic` will be exactly the argument we get
|
// The payload we pass to `miri_start_unwind` will be exactly the argument we get
|
||||||
// in `cleanup` below. So we just box it up once, to get something pointer-sized.
|
// in `cleanup` below. So we just box it up once, to get something pointer-sized.
|
||||||
let payload_box: Payload = Box::new(payload);
|
let payload_box: Payload = Box::new(payload);
|
||||||
miri_start_panic(Box::into_raw(payload_box) as *mut u8)
|
miri_start_unwind(Box::into_raw(payload_box) as *mut u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {
|
pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {
|
||||||
|
|
|
@ -508,12 +508,12 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
|
||||||
// Access to the union's fields: this is `std` and we know that the `r#try`
|
// Access to the union's fields: this is `std` and we know that the `r#try`
|
||||||
// intrinsic fills in the `r` or `p` union field based on its return value.
|
// intrinsic fills in the `r` or `p` union field based on its return value.
|
||||||
//
|
//
|
||||||
// The call to `intrinsics::r#try` is made safe by:
|
// The call to `intrinsics::catch_unwind` is made safe by:
|
||||||
// - `do_call`, the first argument, can be called with the initial `data_ptr`.
|
// - `do_call`, the first argument, can be called with the initial `data_ptr`.
|
||||||
// - `do_catch`, the second argument, can be called with the `data_ptr` as well.
|
// - `do_catch`, the second argument, can be called with the `data_ptr` as well.
|
||||||
// See their safety preconditions for more information
|
// See their safety preconditions for more information
|
||||||
unsafe {
|
unsafe {
|
||||||
return if intrinsics::r#try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
|
return if intrinsics::catch_unwind(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
|
||||||
Ok(ManuallyDrop::into_inner(data.r))
|
Ok(ManuallyDrop::into_inner(data.r))
|
||||||
} else {
|
} else {
|
||||||
Err(ManuallyDrop::into_inner(data.p))
|
Err(ManuallyDrop::into_inner(data.p))
|
||||||
|
@ -540,7 +540,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
|
||||||
// Its must contains a valid `f` (type: F) value that can be use to fill
|
// Its must contains a valid `f` (type: F) value that can be use to fill
|
||||||
// `data.r`.
|
// `data.r`.
|
||||||
//
|
//
|
||||||
// This function cannot be marked as `unsafe` because `intrinsics::r#try`
|
// This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
|
||||||
// expects normal function pointers.
|
// expects normal function pointers.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
|
fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
|
||||||
|
@ -562,7 +562,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
|
||||||
// Since this uses `cleanup` it also hinges on a correct implementation of
|
// Since this uses `cleanup` it also hinges on a correct implementation of
|
||||||
// `__rustc_panic_cleanup`.
|
// `__rustc_panic_cleanup`.
|
||||||
//
|
//
|
||||||
// This function cannot be marked as `unsafe` because `intrinsics::r#try`
|
// This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
|
||||||
// expects normal function pointers.
|
// expects normal function pointers.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind
|
#[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 71352deb20727b4dda9ebfe8182709d5bf17dfea
|
Subproject commit 19c40bfd2d57641d962f3119a1c343355f1b3c5e
|
|
@ -1 +1 @@
|
||||||
Subproject commit 76bd48a273a0e0413a3bf22c699112d41497b99e
|
Subproject commit e1eead1181a691e56299294d5f1d62fe7a26d317
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8227666de13f6e7bb32dea9dc42e841adb5ce4b7
|
Subproject commit 3417f866932cb1c09c6be0f31d2a02ee01b4b95d
|
|
@ -1 +1 @@
|
||||||
Subproject commit e188d5d466f7f3ff9f1d518393235f4fe951be46
|
Subproject commit 57f1e708f5d5850562bc385aaf610e6af14d6ec8
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1f30cc7cca9a3433bc1872abdc98960b36c21ca0
|
Subproject commit 7b0ef5b0bea5e3ce3b9764aa5754a60e2cc05c52
|
|
@ -143,7 +143,7 @@ pub struct Thread<'mir, 'tcx> {
|
||||||
join_status: ThreadJoinStatus,
|
join_status: ThreadJoinStatus,
|
||||||
|
|
||||||
/// Stack of active panic payloads for the current thread. Used for storing
|
/// Stack of active panic payloads for the current thread. Used for storing
|
||||||
/// the argument of the call to `miri_start_panic` (the panic payload) when unwinding.
|
/// the argument of the call to `miri_start_unwind` (the panic payload) when unwinding.
|
||||||
/// This is pointer-sized, and matches the `Payload` type in `src/libpanic_unwind/miri.rs`.
|
/// This is pointer-sized, and matches the `Payload` type in `src/libpanic_unwind/miri.rs`.
|
||||||
///
|
///
|
||||||
/// In real unwinding, the payload gets passed as an argument to the landing pad,
|
/// In real unwinding, the payload gets passed as an argument to the landing pad,
|
||||||
|
|
|
@ -68,9 +68,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
let ret = match ret {
|
let ret = match ret {
|
||||||
None =>
|
None =>
|
||||||
match link_name.as_str() {
|
match link_name.as_str() {
|
||||||
"miri_start_panic" => {
|
"miri_start_unwind" => {
|
||||||
// `check_shim` happens inside `handle_miri_start_panic`.
|
// `check_shim` happens inside `handle_miri_start_unwind`.
|
||||||
this.handle_miri_start_panic(abi, link_name, args, unwind)?;
|
this.handle_miri_start_unwind(abi, link_name, args, unwind)?;
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
// This matches calls to the foreign item `panic_impl`.
|
// This matches calls to the foreign item `panic_impl`.
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
|
|
||||||
// Some intrinsics are special and need the "ret".
|
// Some intrinsics are special and need the "ret".
|
||||||
match intrinsic_name {
|
match intrinsic_name {
|
||||||
"try" => return this.handle_try(args, dest, ret),
|
"catch_unwind" => return this.handle_catch_unwind(args, dest, ret),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
//! The core pieces of the runtime are:
|
//! The core pieces of the runtime are:
|
||||||
//! - An implementation of `__rust_maybe_catch_panic` that pushes the invoked stack frame with
|
//! - An implementation of `__rust_maybe_catch_panic` that pushes the invoked stack frame with
|
||||||
//! some extra metadata derived from the panic-catching arguments of `__rust_maybe_catch_panic`.
|
//! some extra metadata derived from the panic-catching arguments of `__rust_maybe_catch_panic`.
|
||||||
//! - A hack in `libpanic_unwind` that calls the `miri_start_panic` intrinsic instead of the
|
//! - A hack in `libpanic_unwind` that calls the `miri_start_unwind` intrinsic instead of the
|
||||||
//! target-native panic runtime. (This lives in the rustc repo.)
|
//! target-native panic runtime. (This lives in the rustc repo.)
|
||||||
//! - An implementation of `miri_start_panic` that stores its argument (the panic payload), and then
|
//! - An implementation of `miri_start_unwind` that stores its argument (the panic payload), and then
|
||||||
//! immediately returns, but on the *unwind* edge (not the normal return edge), thus initiating unwinding.
|
//! immediately returns, but on the *unwind* edge (not the normal return edge), thus initiating unwinding.
|
||||||
//! - A hook executed each time a frame is popped, such that if the frame pushed by `__rust_maybe_catch_panic`
|
//! - A hook executed each time a frame is popped, such that if the frame pushed by `__rust_maybe_catch_panic`
|
||||||
//! gets popped *during unwinding*, we take the panic payload and store it according to the extra
|
//! gets popped *during unwinding*, we take the panic payload and store it according to the extra
|
||||||
|
@ -44,9 +44,9 @@ impl VisitProvenance for CatchUnwindData<'_> {
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
|
||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
/// Handles the special `miri_start_panic` intrinsic, which is called
|
/// Handles the special `miri_start_unwind` intrinsic, which is called
|
||||||
/// by libpanic_unwind to delegate the actual unwinding process to Miri.
|
/// by libpanic_unwind to delegate the actual unwinding process to Miri.
|
||||||
fn handle_miri_start_panic(
|
fn handle_miri_start_unwind(
|
||||||
&mut self,
|
&mut self,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
link_name: Symbol,
|
link_name: Symbol,
|
||||||
|
@ -55,7 +55,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
trace!("miri_start_panic: {:?}", this.frame().instance);
|
trace!("miri_start_unwind: {:?}", this.frame().instance);
|
||||||
|
|
||||||
// Get the raw pointer stored in arg[0] (the panic payload).
|
// Get the raw pointer stored in arg[0] (the panic payload).
|
||||||
let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
||||||
|
@ -69,7 +69,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
|
/// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
|
||||||
fn handle_try(
|
fn handle_catch_unwind(
|
||||||
&mut self,
|
&mut self,
|
||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
|
@ -85,7 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
// what that is), and returns 1.
|
// what that is), and returns 1.
|
||||||
// The `payload` is passed (by libstd) to `__rust_panic_cleanup`, which is then expected to
|
// The `payload` is passed (by libstd) to `__rust_panic_cleanup`, which is then expected to
|
||||||
// return a `Box<dyn Any + Send + 'static>`.
|
// return a `Box<dyn Any + Send + 'static>`.
|
||||||
// In Miri, `miri_start_panic` is passed exactly that type, so we make the `payload` simply
|
// In Miri, `miri_start_unwind` is passed exactly that type, so we make the `payload` simply
|
||||||
// a pointer to `Box<dyn Any + Send + 'static>`.
|
// a pointer to `Box<dyn Any + Send + 'static>`.
|
||||||
|
|
||||||
// Get all the arguments.
|
// Get all the arguments.
|
||||||
|
@ -141,7 +141,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
// We set the return value of `try` to 1, since there was a panic.
|
// We set the return value of `try` to 1, since there was a panic.
|
||||||
this.write_scalar(Scalar::from_i32(1), &catch_unwind.dest)?;
|
this.write_scalar(Scalar::from_i32(1), &catch_unwind.dest)?;
|
||||||
|
|
||||||
// The Thread's `panic_payload` holds what was passed to `miri_start_panic`.
|
// The Thread's `panic_payload` holds what was passed to `miri_start_unwind`.
|
||||||
// This is exactly the second argument we need to pass to `catch_fn`.
|
// This is exactly the second argument we need to pass to `catch_fn`.
|
||||||
let payload = this.active_thread_mut().panic_payloads.pop().unwrap();
|
let payload = this.active_thread_mut().panic_payloads.pop().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Make sure we check the ABI when Miri itself invokes a function
|
// Make sure we check the ABI when Miri itself invokes a function
|
||||||
// as part of a shim implementation.
|
// as part of a shim implementation.
|
||||||
std::intrinsics::r#try(
|
std::intrinsics::catch_unwind(
|
||||||
//~^ ERROR: calling a function with ABI C using caller ABI Rust
|
//~^ ERROR: calling a function with ABI C using caller ABI Rust
|
||||||
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
||||||
std::ptr::null_mut(),
|
std::ptr::null_mut(),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
error: Undefined Behavior: calling a function with ABI C using caller ABI Rust
|
error: Undefined Behavior: calling a function with ABI C using caller ABI Rust
|
||||||
--> $DIR/check_callback_abi.rs:LL:CC
|
--> $DIR/check_callback_abi.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | / std::intrinsics::r#try(
|
LL | / std::intrinsics::catch_unwind(
|
||||||
LL | |
|
LL | |
|
||||||
LL | | std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
LL | | std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
||||||
LL | | std::ptr::null_mut(),
|
LL | | std::ptr::null_mut(),
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
#![feature(c_unwind)]
|
#![feature(c_unwind)]
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn miri_start_panic(payload: *mut u8) -> !;
|
fn miri_start_unwind(payload: *mut u8) -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe { miri_start_panic(&mut 0) }
|
unsafe { miri_start_unwind(&mut 0) }
|
||||||
//~^ ERROR: unwinding past a stack frame that does not allow unwinding
|
//~^ ERROR: unwinding past a stack frame that does not allow unwinding
|
||||||
}
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
|
WARNING: the flag `-Zmiri-disable-abi-check` is deprecated and planned to be removed.
|
||||||
If you have a use-case for it, please file an issue.
|
If you have a use-case for it, please file an issue.
|
||||||
error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding
|
error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding
|
||||||
--> $DIR/bad_miri_start_panic.rs:LL:CC
|
--> $DIR/bad_miri_start_unwind.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { miri_start_panic(&mut 0) }
|
LL | unsafe { miri_start_unwind(&mut 0) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/bad_miri_start_panic.rs:LL:CC
|
= note: inside `main` at $DIR/bad_miri_start_unwind.rs:LL:CC
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
//! Unwinding despite `-C panic=abort` is an error.
|
//! Unwinding despite `-C panic=abort` is an error.
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn miri_start_panic(payload: *mut u8) -> !;
|
fn miri_start_unwind(payload: *mut u8) -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
miri_start_panic(&mut 0); //~ ERROR: unwinding past a stack frame that does not allow unwinding
|
miri_start_unwind(&mut 0); //~ ERROR: unwinding past a stack frame that does not allow unwinding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding
|
error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding
|
||||||
--> $DIR/unwind_panic_abort.rs:LL:CC
|
--> $DIR/unwind_panic_abort.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | miri_start_panic(&mut 0);
|
LL | miri_start_unwind(&mut 0);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
|
|
@ -15,7 +15,7 @@ fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = malloc(0);
|
let _ = malloc(0);
|
||||||
std::mem::transmute::<fn(), extern "C" fn()>(foo)();
|
std::mem::transmute::<fn(), extern "C" fn()>(foo)();
|
||||||
std::intrinsics::r#try(
|
std::intrinsics::catch_unwind(
|
||||||
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
|
||||||
std::ptr::null_mut(),
|
std::ptr::null_mut(),
|
||||||
|_, _| unreachable!(),
|
|_, _| unreachable!(),
|
||||||
|
|
|
@ -56,7 +56,7 @@ extern "Rust" {
|
||||||
///
|
///
|
||||||
/// This is internal and unstable and should not be used; we give it here
|
/// This is internal and unstable and should not be used; we give it here
|
||||||
/// just to be complete.
|
/// just to be complete.
|
||||||
pub fn miri_start_panic(payload: *mut u8) -> !;
|
pub fn miri_start_unwind(payload: *mut u8) -> !;
|
||||||
|
|
||||||
/// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer
|
/// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer
|
||||||
/// points to. If this pointer is invalid (not pointing to an allocation), interpretation will abort.
|
/// points to. If this pointer is invalid (not pointing to an allocation), interpretation will abort.
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub fn test_cleanup() {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn test_rtry() {
|
pub fn test_rtry() {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::intrinsics::r#try(|_| {
|
core::intrinsics::catch_unwind(|_| {
|
||||||
may_panic();
|
may_panic();
|
||||||
}, core::ptr::null_mut(), |data, exception| {
|
}, core::ptr::null_mut(), |data, exception| {
|
||||||
log_number(data as usize);
|
log_number(data as usize);
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub fn test_cleanup() {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn test_rtry() {
|
pub fn test_rtry() {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::intrinsics::r#try(|_| {
|
core::intrinsics::catch_unwind(|_| {
|
||||||
may_panic();
|
may_panic();
|
||||||
}, core::ptr::null_mut(), |data, exception| {
|
}, core::ptr::null_mut(), |data, exception| {
|
||||||
log_number(data as usize);
|
log_number(data as usize);
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub extern "C" fn start() -> usize {
|
||||||
let data = 0x1234usize as *mut u8; // Something to recognize
|
let data = 0x1234usize as *mut u8; // Something to recognize
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::intrinsics::r#try(|data: *mut u8| {
|
core::intrinsics::catch_unwind(|data: *mut u8| {
|
||||||
let _log_on_drop = LogOnDrop;
|
let _log_on_drop = LogOnDrop;
|
||||||
|
|
||||||
logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data));
|
logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data));
|
||||||
|
|
|
@ -15,7 +15,7 @@ note: required because it's used within this closure
|
||||||
|
|
|
|
||||||
LL | catch_unwind(|| { x.set(23); });
|
LL | catch_unwind(|| { x.set(23); });
|
||||||
| ^^
|
| ^^
|
||||||
note: required by a bound in `catch_unwind`
|
note: required by a bound in `std::panic::catch_unwind`
|
||||||
--> $SRC_DIR/std/src/panic.rs:LL:COL
|
--> $SRC_DIR/std/src/panic.rs:LL:COL
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: expected `;`, found `#`
|
error: expected `;`, found `#`
|
||||||
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:4:47
|
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body-1.rs:4:47
|
||||||
|
|
|
|
||||||
LL | #[cfg(feature = )]
|
LL | #[cfg(feature = )]
|
||||||
| ------------------ only `;` terminated statements or tail expressions are allowed after this attribute
|
| ------------------ only `;` terminated statements or tail expressions are allowed after this attribute
|
||||||
|
@ -18,7 +18,7 @@ LL | { [1, 2, 3].iter().map().collect::<String>() }
|
||||||
| + +
|
| + +
|
||||||
|
|
||||||
error: expected statement after outer attribute
|
error: expected statement after outer attribute
|
||||||
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:5:5
|
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body-1.rs:5:5
|
||||||
|
|
|
|
||||||
LL | #[attr]
|
LL | #[attr]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Issue #121647: recovery path leaving unemitted error behind
|
||||||
|
|
||||||
|
macro_rules! the_macro {
|
||||||
|
( $foo:stmt ; $bar:stmt ; ) => {
|
||||||
|
#[cfg()]
|
||||||
|
$foo //~ ERROR expected `;`, found `#`
|
||||||
|
|
||||||
|
#[cfg(bar)]
|
||||||
|
$bar
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
the_macro!( (); (); );
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
error: expected `;`, found `#`
|
||||||
|
--> $DIR/properly-recover-from-trailing-outer-attribute-in-body-2.rs:6:13
|
||||||
|
|
|
||||||
|
LL | #[cfg()]
|
||||||
|
| -------- only `;` terminated statements or tail expressions are allowed after this attribute
|
||||||
|
LL | $foo
|
||||||
|
| ^ expected `;` here
|
||||||
|
LL |
|
||||||
|
LL | #[cfg(bar)]
|
||||||
|
| - unexpected token
|
||||||
|
...
|
||||||
|
LL | the_macro!( (); (); );
|
||||||
|
| --------------------- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `the_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: add `;` here
|
||||||
|
|
|
||||||
|
LL | $foo;
|
||||||
|
| +
|
||||||
|
help: alternatively, consider surrounding the expression with a block
|
||||||
|
|
|
||||||
|
LL | the_macro!( { () }; (); );
|
||||||
|
| + +
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue