Auto merge of #49058 - withoutboats:pin, r=cramertj
Pin, Unpin, PinBox Implementing rust-lang/rfcs#2349 (do not merge until RFC is merged) @bors r? @cramertj
This commit is contained in:
commit
6bfa7d02d6
5 changed files with 222 additions and 4 deletions
|
@ -64,8 +64,8 @@ use core::cmp::Ordering;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{self, Hash, Hasher};
|
use core::hash::{self, Hash, Hasher};
|
||||||
use core::iter::FusedIterator;
|
use core::iter::FusedIterator;
|
||||||
use core::marker::{self, Unsize};
|
use core::marker::{self, Unpin, Unsize};
|
||||||
use core::mem;
|
use core::mem::{self, Pin};
|
||||||
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
|
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
|
||||||
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
|
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
|
||||||
use core::ptr::{self, NonNull, Unique};
|
use core::ptr::{self, NonNull, Unique};
|
||||||
|
@ -896,3 +896,100 @@ impl<T> Generator for Box<T>
|
||||||
(**self).resume()
|
(**self).resume()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A pinned, heap allocated reference.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
#[fundamental]
|
||||||
|
pub struct PinBox<T: ?Sized> {
|
||||||
|
inner: Box<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T> PinBox<T> {
|
||||||
|
/// Allocate memory on the heap, move the data into it and pin it.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub fn new(data: T) -> PinBox<T> {
|
||||||
|
PinBox { inner: Box::new(data) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: ?Sized> PinBox<T> {
|
||||||
|
/// Get a pinned reference to the data in this PinBox.
|
||||||
|
pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> {
|
||||||
|
unsafe { Pin::new_unchecked(&mut *self.inner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the data inside this PinBox.
|
||||||
|
///
|
||||||
|
/// This function is unsafe. Users must guarantee that the data is never
|
||||||
|
/// moved out of this reference.
|
||||||
|
pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
|
||||||
|
&mut *this.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert this PinBox into an unpinned Box.
|
||||||
|
///
|
||||||
|
/// This function is unsafe. Users must guarantee that the data is never
|
||||||
|
/// moved out of the box.
|
||||||
|
pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
|
||||||
|
this.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: ?Sized> From<Box<T>> for PinBox<T> {
|
||||||
|
fn from(boxed: Box<T>) -> PinBox<T> {
|
||||||
|
PinBox { inner: boxed }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> {
|
||||||
|
fn from(pinned: PinBox<T>) -> Box<T> {
|
||||||
|
pinned.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: ?Sized> Deref for PinBox<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&*self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
&mut *self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&*self.inner, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Debug::fmt(&*self.inner, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: ?Sized> fmt::Pointer for PinBox<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
// It's not possible to extract the inner Uniq directly from the Box,
|
||||||
|
// instead we cast it to a *const which aliases the Unique
|
||||||
|
let ptr: *const T = &*self.inner;
|
||||||
|
fmt::Pointer::fmt(&ptr, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
#![feature(offset_to)]
|
#![feature(offset_to)]
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
|
#![feature(pin)]
|
||||||
#![feature(placement_in_syntax)]
|
#![feature(placement_in_syntax)]
|
||||||
#![feature(placement_new_protocol)]
|
#![feature(placement_new_protocol)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
|
|
|
@ -578,3 +578,13 @@ unsafe impl<T: ?Sized> Freeze for *const T {}
|
||||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
||||||
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
|
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
|
||||||
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
|
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
|
||||||
|
|
||||||
|
/// Types which can be moved out of a `Pin`.
|
||||||
|
///
|
||||||
|
/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a
|
||||||
|
/// type implements `Unpin`, it is safe to move a value of that type out of the
|
||||||
|
/// `Pin` pointer.
|
||||||
|
///
|
||||||
|
/// This trait is automatically implemented for almost every type.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub unsafe auto trait Unpin {}
|
||||||
|
|
|
@ -20,9 +20,9 @@ use cmp;
|
||||||
use fmt;
|
use fmt;
|
||||||
use hash;
|
use hash;
|
||||||
use intrinsics;
|
use intrinsics;
|
||||||
use marker::{Copy, PhantomData, Sized};
|
use marker::{Copy, PhantomData, Sized, Unpin, Unsize};
|
||||||
use ptr;
|
use ptr;
|
||||||
use ops::{Deref, DerefMut};
|
use ops::{Deref, DerefMut, CoerceUnsized};
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use intrinsics::transmute;
|
pub use intrinsics::transmute;
|
||||||
|
@ -1105,3 +1105,111 @@ impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
|
||||||
pub unsafe fn unreachable() -> ! {
|
pub unsafe fn unreachable() -> ! {
|
||||||
intrinsics::unreachable()
|
intrinsics::unreachable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A pinned reference.
|
||||||
|
///
|
||||||
|
/// A pinned reference is a lot like a mutable reference, except that it is not
|
||||||
|
/// safe to move a value out of a pinned reference unless the type of that
|
||||||
|
/// value implements the `Unpin` trait.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
#[fundamental]
|
||||||
|
pub struct Pin<'a, T: ?Sized + 'a> {
|
||||||
|
inner: &'a mut T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: ?Sized + Unpin> Pin<'a, T> {
|
||||||
|
/// Construct a new `Pin` around a reference to some data of a type that
|
||||||
|
/// implements `Unpin`.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub fn new(reference: &'a mut T) -> Pin<'a, T> {
|
||||||
|
Pin { inner: reference }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: ?Sized> Pin<'a, T> {
|
||||||
|
/// Construct a new `Pin` around a reference to some data of a type that
|
||||||
|
/// may or may not implement `Unpin`.
|
||||||
|
///
|
||||||
|
/// This constructor is unsafe because we do not know what will happen with
|
||||||
|
/// that data after the reference ends. If you cannot guarantee that the
|
||||||
|
/// data will never move again, calling this constructor is invalid.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> {
|
||||||
|
Pin { inner: reference }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrow a Pin for a shorter lifetime than it already has.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> {
|
||||||
|
Pin { inner: this.inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the data inside of this `Pin`.
|
||||||
|
///
|
||||||
|
/// This function is unsafe. You must guarantee that you will never move
|
||||||
|
/// the data out of the mutable reference you receive when you call this
|
||||||
|
/// function.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T {
|
||||||
|
this.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new pin by mapping the interior value.
|
||||||
|
///
|
||||||
|
/// For example, if you wanted to get a `Pin` of a field of something, you
|
||||||
|
/// could use this to get access to that field in one line of code.
|
||||||
|
///
|
||||||
|
/// This function is unsafe. You must guarantee that the data you return
|
||||||
|
/// will not move so long as the argument value does not move (for example,
|
||||||
|
/// because it is one of the fields of that value), and also that you do
|
||||||
|
/// not move out of the argument you receive to the interior function.
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where
|
||||||
|
F: FnOnce(&mut T) -> &mut U
|
||||||
|
{
|
||||||
|
Pin { inner: f(this.inner) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: ?Sized> Deref for Pin<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&*self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Debug::fmt(&**self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&**self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(&(&*self.inner as *const T), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
|
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<'a, U>> for Pin<'a, T> {}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// ignore-test
|
||||||
|
|
||||||
pub struct Inner<T> {
|
pub struct Inner<T> {
|
||||||
field: T,
|
field: T,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue