diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 0be71b52d9edd..05a31358443aa 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -278,36 +278,36 @@ pub unsafe fn r#try R>(f: F) -> Result> Err(ManuallyDrop::into_inner(data.p)) }; - // Compatibility wrapper around the try intrinsic for bootstrap - #[inline] + // Compatibility wrapper around the try intrinsic for bootstrap. + // + // We also need to mark it #[inline(never)] to work around a bug on MinGW + // targets: the unwinding implementation was relying on UB, but this only + // becomes a problem in practice if inlining is involved. + #[cfg(not(bootstrap))] + use intrinsics::r#try as do_try; + #[cfg(bootstrap)] + #[inline(never)] unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 { - #[cfg(not(bootstrap))] - { - intrinsics::r#try(try_fn, data, catch_fn) - } - #[cfg(bootstrap)] - { - use crate::mem::MaybeUninit; + use crate::mem::MaybeUninit; + #[cfg(target_env = "msvc")] + type TryPayload = [u64; 2]; + #[cfg(not(target_env = "msvc"))] + type TryPayload = *mut u8; + + let mut payload: MaybeUninit = MaybeUninit::uninit(); + let payload_ptr = payload.as_mut_ptr() as *mut u8; + let r = intrinsics::r#try(try_fn, data, payload_ptr); + if r != 0 { #[cfg(target_env = "msvc")] - type TryPayload = [u64; 2]; + { + catch_fn(data, payload_ptr) + } #[cfg(not(target_env = "msvc"))] - type TryPayload = *mut u8; - - let mut payload: MaybeUninit = MaybeUninit::uninit(); - let payload_ptr = payload.as_mut_ptr() as *mut u8; - let r = intrinsics::r#try(try_fn, data, payload_ptr); - if r != 0 { - #[cfg(target_env = "msvc")] - { - catch_fn(data, payload_ptr) - } - #[cfg(not(target_env = "msvc"))] - { - catch_fn(data, payload.assume_init()) - } + { + catch_fn(data, payload.assume_init()) } - r } + r } // We consider unwinding to be rare, so mark this function as cold. However, @@ -321,7 +321,9 @@ pub unsafe fn r#try R>(f: F) -> Result> obj } - #[inline] + // See comment on do_try above for why #[inline(never)] is needed on bootstrap. + #[cfg_attr(bootstrap, inline(never))] + #[cfg_attr(not(bootstrap), inline)] fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data;