From f15715f3e48835c681e6958134c9b3dc0c8ae12a Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 14 Jul 2024 22:17:28 +0300 Subject: [PATCH] lib: replace some `mem::forget`'s with `ManuallyDrop` --- alloc/src/rc.rs | 47 ++++++++++------------ alloc/src/sync.rs | 36 ++++++++--------- core/src/task/wake.rs | 15 +++---- proc_macro/src/bridge/buffer.rs | 11 +++-- proc_macro/src/bridge/client.rs | 4 +- std/src/os/fd/owned.rs | 6 +-- std/src/os/solid/io.rs | 6 +-- std/src/os/windows/io/handle.rs | 6 +-- std/src/os/windows/io/socket.rs | 7 +--- std/src/sys/pal/hermit/thread.rs | 6 +-- std/src/sys/pal/sgx/abi/tls/mod.rs | 4 +- std/src/sys/pal/sgx/abi/usercalls/alloc.rs | 7 ++-- std/src/sys/pal/sgx/fd.rs | 10 ++--- std/src/sys/pal/teeos/thread.rs | 16 +++----- std/src/sys/pal/unix/thread.rs | 14 +++---- std/src/sys/pal/wasi/thread.rs | 10 ++--- std/src/thread/mod.rs | 9 ++--- 17 files changed, 85 insertions(+), 129 deletions(-) diff --git a/alloc/src/rc.rs b/alloc/src/rc.rs index 9982c8ea6dcbe..bfe3ea2080017 100644 --- a/alloc/src/rc.rs +++ b/alloc/src/rc.rs @@ -259,7 +259,7 @@ use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unsize}; -use core::mem::{self, align_of_val_raw, forget, ManuallyDrop}; +use core::mem::{self, align_of_val_raw, ManuallyDrop}; use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] @@ -908,19 +908,18 @@ impl Rc { #[stable(feature = "rc_unique", since = "1.4.0")] pub fn try_unwrap(this: Self) -> Result { if Rc::strong_count(&this) == 1 { - unsafe { - let val = ptr::read(&*this); // copy the contained object - let alloc = ptr::read(&this.alloc); // copy the allocator - - // Indicate to Weaks that they can't be promoted by decrementing - // the strong count, and then remove the implicit "strong weak" - // pointer while also handling drop logic by just crafting a - // fake Weak. - this.inner().dec_strong(); - let _weak = Weak { ptr: this.ptr, alloc }; - forget(this); - Ok(val) - } + let this = ManuallyDrop::new(this); + + let val: T = unsafe { ptr::read(&**this) }; // copy the contained object + let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator + + // Indicate to Weaks that they can't be promoted by decrementing + // the strong count, and then remove the implicit "strong weak" + // pointer while also handling drop logic by just crafting a + // fake Weak. + this.inner().dec_strong(); + let _weak = Weak { ptr: this.ptr, alloc }; + Ok(val) } else { Err(this) } @@ -1354,9 +1353,8 @@ impl Rc { #[stable(feature = "rc_raw", since = "1.17.0")] #[rustc_never_returns_null_ptr] pub fn into_raw(this: Self) -> *const T { - let ptr = Self::as_ptr(&this); - mem::forget(this); - ptr + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) } /// Consumes the `Rc`, returning the wrapped pointer and allocator. @@ -2127,7 +2125,7 @@ impl Rc<[T]> { } // All clear. Forget the guard so it doesn't free the new RcBox. - forget(guard); + mem::forget(guard); Self::from_ptr(ptr) } @@ -3080,9 +3078,7 @@ impl Weak { #[must_use = "losing the pointer will leak memory"] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { - let result = self.as_ptr(); - mem::forget(self); - result + mem::ManuallyDrop::new(self).as_ptr() } /// Consumes the `Weak`, returning the wrapped pointer and allocator. @@ -3762,10 +3758,11 @@ impl UniqueRcUninit { /// # Safety /// /// The data must have been initialized (by writing to [`Self::data_ptr()`]). - unsafe fn into_rc(mut self) -> Rc { - let ptr = self.ptr; - let alloc = self.alloc.take().unwrap(); - mem::forget(self); + unsafe fn into_rc(self) -> Rc { + let mut this = ManuallyDrop::new(self); + let ptr = this.ptr; + let alloc = this.alloc.take().unwrap(); + // SAFETY: The pointer is valid as per `UniqueRcUninit::new`, and the caller is responsible // for having initialized the data. unsafe { Rc::from_ptr_in(ptr.as_ptr(), alloc) } diff --git a/alloc/src/sync.rs b/alloc/src/sync.rs index a905a1e6b7e62..c36b8f6a1ac8a 100644 --- a/alloc/src/sync.rs +++ b/alloc/src/sync.rs @@ -20,7 +20,7 @@ use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unsize}; -use core::mem::{self, align_of_val_raw}; +use core::mem::{self, align_of_val_raw, ManuallyDrop}; use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::Pin; @@ -960,16 +960,14 @@ impl Arc { acquire!(this.inner().strong); - unsafe { - let elem = ptr::read(&this.ptr.as_ref().data); - let alloc = ptr::read(&this.alloc); // copy the allocator + let this = ManuallyDrop::new(this); + let elem: T = unsafe { ptr::read(&this.ptr.as_ref().data) }; + let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator - // Make a weak pointer to clean up the implicit strong-weak reference - let _weak = Weak { ptr: this.ptr, alloc }; - mem::forget(this); + // Make a weak pointer to clean up the implicit strong-weak reference + let _weak = Weak { ptr: this.ptr, alloc }; - Ok(elem) - } + Ok(elem) } /// Returns the inner value, if the `Arc` has exactly one strong reference. @@ -1493,9 +1491,8 @@ impl Arc { #[stable(feature = "rc_raw", since = "1.17.0")] #[rustc_never_returns_null_ptr] pub fn into_raw(this: Self) -> *const T { - let ptr = Self::as_ptr(&this); - mem::forget(this); - ptr + let this = ManuallyDrop::new(this); + Self::as_ptr(&*this) } /// Consumes the `Arc`, returning the wrapped pointer and allocator. @@ -2801,9 +2798,7 @@ impl Weak { #[must_use = "losing the pointer will leak memory"] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { - let result = self.as_ptr(); - mem::forget(self); - result + ManuallyDrop::new(self).as_ptr() } /// Consumes the `Weak`, returning the wrapped pointer and allocator. @@ -3875,13 +3870,14 @@ impl UniqueArcUninit { /// # Safety /// /// The data must have been initialized (by writing to [`Self::data_ptr()`]). - unsafe fn into_arc(mut self) -> Arc { - let ptr = self.ptr; - let alloc = self.alloc.take().unwrap(); - mem::forget(self); + unsafe fn into_arc(self) -> Arc { + let mut this = ManuallyDrop::new(self); + let ptr = this.ptr.as_ptr(); + let alloc = this.alloc.take().unwrap(); + // SAFETY: The pointer is valid as per `UniqueArcUninit::new`, and the caller is responsible // for having initialized the data. - unsafe { Arc::from_ptr_in(ptr.as_ptr(), alloc) } + unsafe { Arc::from_ptr_in(ptr, alloc) } } } diff --git a/core/src/task/wake.rs b/core/src/task/wake.rs index 86a965f68e085..e785d75a63d7a 100644 --- a/core/src/task/wake.rs +++ b/core/src/task/wake.rs @@ -1,10 +1,9 @@ #![stable(feature = "futures_api", since = "1.36.0")] -use crate::mem::transmute; - use crate::any::Any; use crate::fmt; use crate::marker::PhantomData; +use crate::mem::{transmute, ManuallyDrop}; use crate::panic::AssertUnwindSafe; use crate::ptr; @@ -465,16 +464,14 @@ impl Waker { pub fn wake(self) { // The actual wakeup call is delegated through a virtual function call // to the implementation which is defined by the executor. - let wake = self.waker.vtable.wake; - let data = self.waker.data; // Don't call `drop` -- the waker will be consumed by `wake`. - crate::mem::forget(self); + let this = ManuallyDrop::new(self); // SAFETY: This is safe because `Waker::from_raw` is the only way // to initialize `wake` and `data` requiring the user to acknowledge // that the contract of `RawWaker` is upheld. - unsafe { (wake)(data) }; + unsafe { (this.waker.vtable.wake)(this.waker.data) }; } /// Wake up the task associated with this `Waker` without consuming the `Waker`. @@ -726,16 +723,14 @@ impl LocalWaker { pub fn wake(self) { // The actual wakeup call is delegated through a virtual function call // to the implementation which is defined by the executor. - let wake = self.waker.vtable.wake; - let data = self.waker.data; // Don't call `drop` -- the waker will be consumed by `wake`. - crate::mem::forget(self); + let this = ManuallyDrop::new(self); // SAFETY: This is safe because `Waker::from_raw` is the only way // to initialize `wake` and `data` requiring the user to acknowledge // that the contract of `RawWaker` is upheld. - unsafe { (wake)(data) }; + unsafe { (this.waker.vtable.wake)(this.waker.data) }; } /// Wake up the task associated with this `LocalWaker` without consuming the `LocalWaker`. diff --git a/proc_macro/src/bridge/buffer.rs b/proc_macro/src/bridge/buffer.rs index 149767bf70521..78fcd1999b2f3 100644 --- a/proc_macro/src/bridge/buffer.rs +++ b/proc_macro/src/bridge/buffer.rs @@ -1,7 +1,7 @@ //! Buffer management for same-process client<->server communication. use std::io::{self, Write}; -use std::mem; +use std::mem::{self, ManuallyDrop}; use std::ops::{Deref, DerefMut}; use std::slice; @@ -129,17 +129,16 @@ impl Drop for Buffer { } impl From> for Buffer { - fn from(mut v: Vec) -> Self { + fn from(v: Vec) -> Self { + let mut v = ManuallyDrop::new(v); let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity()); - mem::forget(v); // This utility function is nested in here because it can *only* // be safely called on `Buffer`s created by *this* `proc_macro`. fn to_vec(b: Buffer) -> Vec { unsafe { - let Buffer { data, len, capacity, .. } = b; - mem::forget(b); - Vec::from_raw_parts(data, len, capacity) + let b = ManuallyDrop::new(b); + Vec::from_raw_parts(b.data, b.len, b.capacity) } } diff --git a/proc_macro/src/bridge/client.rs b/proc_macro/src/bridge/client.rs index faca745e56f74..9658fc4840f67 100644 --- a/proc_macro/src/bridge/client.rs +++ b/proc_macro/src/bridge/client.rs @@ -51,9 +51,7 @@ macro_rules! define_client_handles { impl Encode for $oty { fn encode(self, w: &mut Writer, s: &mut S) { - let handle = self.handle; - mem::forget(self); - handle.encode(w, s); + mem::ManuallyDrop::new(self).handle.encode(w, s); } } diff --git a/std/src/os/fd/owned.rs b/std/src/os/fd/owned.rs index a1f83029d2727..800f3b0274faf 100644 --- a/std/src/os/fd/owned.rs +++ b/std/src/os/fd/owned.rs @@ -8,7 +8,7 @@ use crate::fmt; use crate::fs; use crate::io; use crate::marker::PhantomData; -use crate::mem::forget; +use crate::mem::ManuallyDrop; #[cfg(not(any(target_arch = "wasm32", target_env = "sgx", target_os = "hermit")))] use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -141,9 +141,7 @@ impl AsRawFd for OwnedFd { impl IntoRawFd for OwnedFd { #[inline] fn into_raw_fd(self) -> RawFd { - let fd = self.fd; - forget(self); - fd + ManuallyDrop::new(self).fd } } diff --git a/std/src/os/solid/io.rs b/std/src/os/solid/io.rs index 19b4fe22093c3..34fd745d4f9b4 100644 --- a/std/src/os/solid/io.rs +++ b/std/src/os/solid/io.rs @@ -49,7 +49,7 @@ use crate::fmt; use crate::marker::PhantomData; -use crate::mem::forget; +use crate::mem::ManuallyDrop; use crate::net; use crate::sys; use crate::sys_common::{self, AsInner, FromInner, IntoInner}; @@ -149,9 +149,7 @@ impl AsRawFd for OwnedFd { impl IntoRawFd for OwnedFd { #[inline] fn into_raw_fd(self) -> RawFd { - let fd = self.fd; - forget(self); - fd + ManuallyDrop::new(self).fd } } diff --git a/std/src/os/windows/io/handle.rs b/std/src/os/windows/io/handle.rs index a9d1983dce610..9865386e753df 100644 --- a/std/src/os/windows/io/handle.rs +++ b/std/src/os/windows/io/handle.rs @@ -7,7 +7,7 @@ use crate::fmt; use crate::fs; use crate::io; use crate::marker::PhantomData; -use crate::mem::{forget, ManuallyDrop}; +use crate::mem::ManuallyDrop; use crate::ptr; use crate::sys; use crate::sys::cvt; @@ -319,9 +319,7 @@ impl AsRawHandle for OwnedHandle { impl IntoRawHandle for OwnedHandle { #[inline] fn into_raw_handle(self) -> RawHandle { - let handle = self.handle; - forget(self); - handle + ManuallyDrop::new(self).handle } } diff --git a/std/src/os/windows/io/socket.rs b/std/src/os/windows/io/socket.rs index 6ffdf907c8ed3..a0a0cd2d2a3f2 100644 --- a/std/src/os/windows/io/socket.rs +++ b/std/src/os/windows/io/socket.rs @@ -6,8 +6,7 @@ use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; use crate::fmt; use crate::io; use crate::marker::PhantomData; -use crate::mem; -use crate::mem::forget; +use crate::mem::{self, ManuallyDrop}; use crate::sys; #[cfg(not(target_vendor = "uwp"))] use crate::sys::cvt; @@ -191,9 +190,7 @@ impl AsRawSocket for OwnedSocket { impl IntoRawSocket for OwnedSocket { #[inline] fn into_raw_socket(self) -> RawSocket { - let socket = self.socket; - forget(self); - socket + ManuallyDrop::new(self).socket } } diff --git a/std/src/sys/pal/hermit/thread.rs b/std/src/sys/pal/hermit/thread.rs index a244b953d2a49..3723f03081c17 100644 --- a/std/src/sys/pal/hermit/thread.rs +++ b/std/src/sys/pal/hermit/thread.rs @@ -3,7 +3,7 @@ use super::hermit_abi; use crate::ffi::CStr; use crate::io; -use crate::mem; +use crate::mem::ManuallyDrop; use crate::num::NonZero; use crate::ptr; use crate::time::Duration; @@ -90,9 +90,7 @@ impl Thread { #[inline] pub fn into_id(self) -> Tid { - let id = self.tid; - mem::forget(self); - id + ManuallyDrop::new(self).tid } } diff --git a/std/src/sys/pal/sgx/abi/tls/mod.rs b/std/src/sys/pal/sgx/abi/tls/mod.rs index 8a9ea4ac00df0..bab59a3422d15 100644 --- a/std/src/sys/pal/sgx/abi/tls/mod.rs +++ b/std/src/sys/pal/sgx/abi/tls/mod.rs @@ -95,8 +95,8 @@ impl Tls { #[allow(unused)] pub unsafe fn activate_persistent(self: Box) { // FIXME: Needs safety information. See entry.S for `set_tls_ptr` definition. - unsafe { set_tls_ptr(core::ptr::addr_of!(*self) as _) }; - mem::forget(self); + let ptr = Box::into_raw(self).cast_const().cast::(); + unsafe { set_tls_ptr(ptr) }; } unsafe fn current<'a>() -> &'a Tls { diff --git a/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/std/src/sys/pal/sgx/abi/usercalls/alloc.rs index f99cea360f1f4..b625636752cc1 100644 --- a/std/src/sys/pal/sgx/abi/usercalls/alloc.rs +++ b/std/src/sys/pal/sgx/abi/usercalls/alloc.rs @@ -5,7 +5,7 @@ use crate::cell::UnsafeCell; use crate::cmp; use crate::convert::TryInto; use crate::intrinsics; -use crate::mem; +use crate::mem::{self, ManuallyDrop}; use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; use crate::ptr::{self, NonNull}; use crate::slice; @@ -176,6 +176,7 @@ unsafe impl UserSafe for [T] { /// are used solely to indicate intent: a mutable reference is for writing to /// user memory, an immutable reference for reading from user memory. #[unstable(feature = "sgx_platform", issue = "56975")] +#[repr(transparent)] pub struct UserRef(UnsafeCell); /// An owned type in userspace memory. `User` is equivalent to `Box` in /// enclave memory. Access to the memory is only allowed by copying to avoid @@ -266,9 +267,7 @@ where /// Converts this value into a raw pointer. The value will no longer be /// automatically freed. pub fn into_raw(self) -> *mut T { - let ret = self.0; - mem::forget(self); - ret.as_ptr() as _ + ManuallyDrop::new(self).0.as_ptr() as _ } } diff --git a/std/src/sys/pal/sgx/fd.rs b/std/src/sys/pal/sgx/fd.rs index b3686d0e28328..c41b527cff798 100644 --- a/std/src/sys/pal/sgx/fd.rs +++ b/std/src/sys/pal/sgx/fd.rs @@ -2,7 +2,7 @@ use fortanix_sgx_abi::Fd; use super::abi::usercalls; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::mem; +use crate::mem::ManuallyDrop; use crate::sys::{AsInner, FromInner, IntoInner}; #[derive(Debug)] @@ -21,9 +21,7 @@ impl FileDesc { /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> Fd { - let fd = self.fd; - mem::forget(self); - fd + ManuallyDrop::new(self).fd } pub fn read(&self, buf: &mut [u8]) -> io::Result { @@ -70,9 +68,7 @@ impl AsInner for FileDesc { impl IntoInner for FileDesc { fn into_inner(self) -> Fd { - let fd = self.fd; - mem::forget(self); - fd + ManuallyDrop::new(self).fd } } diff --git a/std/src/sys/pal/teeos/thread.rs b/std/src/sys/pal/teeos/thread.rs index f4723b2ea46bf..ef40eba4df2be 100644 --- a/std/src/sys/pal/teeos/thread.rs +++ b/std/src/sys/pal/teeos/thread.rs @@ -1,9 +1,7 @@ -use core::convert::TryInto; - use crate::cmp; use crate::ffi::CStr; use crate::io; -use crate::mem; +use crate::mem::{self, ManuallyDrop}; use crate::num::NonZero; use crate::ptr; use crate::sys::os; @@ -113,11 +111,9 @@ impl Thread { /// must join, because no pthread_detach supported pub fn join(self) { - unsafe { - let ret = libc::pthread_join(self.id, ptr::null_mut()); - mem::forget(self); - assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret)); - } + let id = self.into_id(); + let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; + assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret)); } pub fn id(&self) -> libc::pthread_t { @@ -125,9 +121,7 @@ impl Thread { } pub fn into_id(self) -> libc::pthread_t { - let id = self.id; - mem::forget(self); - id + ManuallyDrop::new(self).id } } diff --git a/std/src/sys/pal/unix/thread.rs b/std/src/sys/pal/unix/thread.rs index 619f4e4121e73..483697b8597f8 100644 --- a/std/src/sys/pal/unix/thread.rs +++ b/std/src/sys/pal/unix/thread.rs @@ -1,7 +1,7 @@ use crate::cmp; use crate::ffi::CStr; use crate::io; -use crate::mem; +use crate::mem::{self, ManuallyDrop}; use crate::num::NonZero; use crate::ptr; use crate::sys::{os, stack_overflow}; @@ -268,11 +268,9 @@ impl Thread { } pub fn join(self) { - unsafe { - let ret = libc::pthread_join(self.id, ptr::null_mut()); - mem::forget(self); - assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret)); - } + let id = self.into_id(); + let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; + assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret)); } pub fn id(&self) -> libc::pthread_t { @@ -280,9 +278,7 @@ impl Thread { } pub fn into_id(self) -> libc::pthread_t { - let id = self.id; - mem::forget(self); - id + ManuallyDrop::new(self).id } } diff --git a/std/src/sys/pal/wasi/thread.rs b/std/src/sys/pal/wasi/thread.rs index 975eef2451f4c..2a3a39aafa704 100644 --- a/std/src/sys/pal/wasi/thread.rs +++ b/std/src/sys/pal/wasi/thread.rs @@ -172,12 +172,10 @@ impl Thread { pub fn join(self) { cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { - unsafe { - let ret = libc::pthread_join(self.id, ptr::null_mut()); - mem::forget(self); - if ret != 0 { - rtabort!("failed to join thread: {}", io::Error::from_raw_os_error(ret)); - } + let id = mem::ManuallyDrop::new(self).id; + let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; + if ret != 0 { + rtabort!("failed to join thread: {}", io::Error::from_raw_os_error(ret)); } } else { self.0 diff --git a/std/src/thread/mod.rs b/std/src/thread/mod.rs index c8ee365392f85..73bf562370829 100644 --- a/std/src/thread/mod.rs +++ b/std/src/thread/mod.rs @@ -165,7 +165,7 @@ use crate::ffi::{CStr, CString}; use crate::fmt; use crate::io; use crate::marker::PhantomData; -use crate::mem::{self, forget}; +use crate::mem::{self, forget, ManuallyDrop}; use crate::num::NonZero; use crate::panic; use crate::panicking; @@ -514,11 +514,10 @@ impl Builder { MaybeDangling(mem::MaybeUninit::new(x)) } fn into_inner(self) -> T { - // SAFETY: we are always initialized. - let ret = unsafe { self.0.assume_init_read() }; // Make sure we don't drop. - mem::forget(self); - ret + let this = ManuallyDrop::new(self); + // SAFETY: we are always initialized. + unsafe { this.0.assume_init_read() } } } impl Drop for MaybeDangling {