diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-04-26 03:50:16 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-26 03:50:16 +0200 |
| commit | 8bdb91d9ffc9d5f008dae971faadcb06cf2a3bb9 (patch) | |
| tree | 2311c0dfcf475c6e72daa5bab966096bbc41020d /src | |
| parent | 878a7d6ea5ddbc5f813bd45dbb3633e4317ad2a9 (diff) | |
| parent | a0e0849a3b1710139d84be846a444c12297cfd2b (diff) | |
| download | rust-8bdb91d9ffc9d5f008dae971faadcb06cf2a3bb9.tar.gz rust-8bdb91d9ffc9d5f008dae971faadcb06cf2a3bb9.zip | |
Rollup merge of #60165 - Nemo157:pin-into-inner, r=cramertj
Add Pin::{into_inner,into_inner_unchecked}
These functions are useful for unsafe code that needs to temporarily pull smart pointers out of the `Pin`, e.g. [the change that inspired them](https://github.com/Nemo157/futures-rs/commit/b4361780faf764c7cb046ed75f863a6fcfd44800#diff-1a4e0ba4d1b539412ca576411ec6c7c2R258) is taking a `Pin<Box<dyn Future>>`, turning it into a `*mut dyn Future` via `Box::into_raw(unsafe { Pin::into_inner_unchecked(pin) })` then later dropping this via `drop(Pin::from(Box::from_raw(ptr)))`. This can be accomplished today via `{ let ptr = unsafe { Pin::get_unchecked_mut(pin.as_mut()) } as *mut dyn Future; mem::forget(pin); ptr }`, but this is far more complicated and loses out on the symmetry of using `Box::into_raw` and `Box::from_raw`.
I'll extend the documentation on what guarantees `into_inner_unchecked` needs to uphold once I get some feedback on whether this API is wanted or not.
r? @withoutboats
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/pin.rs | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index dbf3dcf03a3..e74ed9b7889 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -349,6 +349,18 @@ where // around pinning. unsafe { Pin::new_unchecked(pointer) } } + + /// Unwraps this `Pin<P>` returning the underlying pointer. + /// + /// This requires that the data inside this `Pin` is [`Unpin`] so that we + /// can ignore the pinning invariants when unwrapping it. + /// + /// [`Unpin`]: ../../std/marker/trait.Unpin.html + #[unstable(feature = "pin_into_inner", issue = "60245")] + #[inline(always)] + pub fn into_inner(pin: Pin<P>) -> P { + pin.pointer + } } impl<P: Deref> Pin<P> { @@ -434,6 +446,28 @@ impl<P: Deref> Pin<P> { pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> { unsafe { Pin::new_unchecked(&*self.pointer) } } + + /// Unwraps this `Pin<P>` returning the underlying pointer. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will continue to + /// treat the pointer `P` as pinned after you call this function, so that + /// the invariants on the `Pin` type can be upheld. If the code using the + /// resulting `P` does not continue to maintain the pinning invariants that + /// is a violation of the API contract and may lead to undefined behavior in + /// later (safe) operations. + /// + /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used + /// instead. + /// + /// [`Unpin`]: ../../std/marker/trait.Unpin.html + /// [`Pin::into_inner`]: #method.into_inner + #[unstable(feature = "pin_into_inner", issue = "60245")] + #[inline(always)] + pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P { + pin.pointer + } } impl<P: DerefMut> Pin<P> { |
