Skip to content

Commit 6bfa7d0

Browse files
committed
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
2 parents a04b88d + 540021f commit 6bfa7d0

File tree

5 files changed

+222
-4
lines changed

5 files changed

+222
-4
lines changed

src/liballoc/boxed.rs

+99-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ use core::cmp::Ordering;
6464
use core::fmt;
6565
use core::hash::{self, Hash, Hasher};
6666
use core::iter::FusedIterator;
67-
use core::marker::{self, Unsize};
68-
use core::mem;
67+
use core::marker::{self, Unpin, Unsize};
68+
use core::mem::{self, Pin};
6969
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
7070
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
7171
use core::ptr::{self, NonNull, Unique};
@@ -896,3 +896,100 @@ impl<T> Generator for Box<T>
896896
(**self).resume()
897897
}
898898
}
899+
900+
/// A pinned, heap allocated reference.
901+
#[unstable(feature = "pin", issue = "49150")]
902+
#[fundamental]
903+
pub struct PinBox<T: ?Sized> {
904+
inner: Box<T>,
905+
}
906+
907+
#[unstable(feature = "pin", issue = "49150")]
908+
impl<T> PinBox<T> {
909+
/// Allocate memory on the heap, move the data into it and pin it.
910+
#[unstable(feature = "pin", issue = "49150")]
911+
pub fn new(data: T) -> PinBox<T> {
912+
PinBox { inner: Box::new(data) }
913+
}
914+
}
915+
916+
#[unstable(feature = "pin", issue = "49150")]
917+
impl<T: ?Sized> PinBox<T> {
918+
/// Get a pinned reference to the data in this PinBox.
919+
pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> {
920+
unsafe { Pin::new_unchecked(&mut *self.inner) }
921+
}
922+
923+
/// Get a mutable reference to the data inside this PinBox.
924+
///
925+
/// This function is unsafe. Users must guarantee that the data is never
926+
/// moved out of this reference.
927+
pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
928+
&mut *this.inner
929+
}
930+
931+
/// Convert this PinBox into an unpinned Box.
932+
///
933+
/// This function is unsafe. Users must guarantee that the data is never
934+
/// moved out of the box.
935+
pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
936+
this.inner
937+
}
938+
}
939+
940+
#[unstable(feature = "pin", issue = "49150")]
941+
impl<T: ?Sized> From<Box<T>> for PinBox<T> {
942+
fn from(boxed: Box<T>) -> PinBox<T> {
943+
PinBox { inner: boxed }
944+
}
945+
}
946+
947+
#[unstable(feature = "pin", issue = "49150")]
948+
impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> {
949+
fn from(pinned: PinBox<T>) -> Box<T> {
950+
pinned.inner
951+
}
952+
}
953+
954+
#[unstable(feature = "pin", issue = "49150")]
955+
impl<T: ?Sized> Deref for PinBox<T> {
956+
type Target = T;
957+
958+
fn deref(&self) -> &T {
959+
&*self.inner
960+
}
961+
}
962+
963+
#[unstable(feature = "pin", issue = "49150")]
964+
impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
965+
fn deref_mut(&mut self) -> &mut T {
966+
&mut *self.inner
967+
}
968+
}
969+
970+
#[unstable(feature = "pin", issue = "49150")]
971+
impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
972+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
973+
fmt::Display::fmt(&*self.inner, f)
974+
}
975+
}
976+
977+
#[unstable(feature = "pin", issue = "49150")]
978+
impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
979+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
980+
fmt::Debug::fmt(&*self.inner, f)
981+
}
982+
}
983+
984+
#[unstable(feature = "pin", issue = "49150")]
985+
impl<T: ?Sized> fmt::Pointer for PinBox<T> {
986+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
987+
// It's not possible to extract the inner Uniq directly from the Box,
988+
// instead we cast it to a *const which aliases the Unique
989+
let ptr: *const T = &*self.inner;
990+
fmt::Pointer::fmt(&ptr, f)
991+
}
992+
}
993+
994+
#[unstable(feature = "pin", issue = "49150")]
995+
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
#![feature(offset_to)]
106106
#![feature(optin_builtin_traits)]
107107
#![feature(pattern)]
108+
#![feature(pin)]
108109
#![feature(placement_in_syntax)]
109110
#![feature(placement_new_protocol)]
110111
#![feature(ptr_internals)]

src/libcore/marker.rs

+10
Original file line numberDiff line numberDiff line change
@@ -578,3 +578,13 @@ unsafe impl<T: ?Sized> Freeze for *const T {}
578578
unsafe impl<T: ?Sized> Freeze for *mut T {}
579579
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
580580
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
581+
582+
/// Types which can be moved out of a `Pin`.
583+
///
584+
/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a
585+
/// type implements `Unpin`, it is safe to move a value of that type out of the
586+
/// `Pin` pointer.
587+
///
588+
/// This trait is automatically implemented for almost every type.
589+
#[unstable(feature = "pin", issue = "49150")]
590+
pub unsafe auto trait Unpin {}

src/libcore/mem.rs

+110-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ use cmp;
2020
use fmt;
2121
use hash;
2222
use intrinsics;
23-
use marker::{Copy, PhantomData, Sized};
23+
use marker::{Copy, PhantomData, Sized, Unpin, Unsize};
2424
use ptr;
25-
use ops::{Deref, DerefMut};
25+
use ops::{Deref, DerefMut, CoerceUnsized};
2626

2727
#[stable(feature = "rust1", since = "1.0.0")]
2828
pub use intrinsics::transmute;
@@ -1105,3 +1105,111 @@ impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
11051105
pub unsafe fn unreachable() -> ! {
11061106
intrinsics::unreachable()
11071107
}
1108+
1109+
/// A pinned reference.
1110+
///
1111+
/// A pinned reference is a lot like a mutable reference, except that it is not
1112+
/// safe to move a value out of a pinned reference unless the type of that
1113+
/// value implements the `Unpin` trait.
1114+
#[unstable(feature = "pin", issue = "49150")]
1115+
#[fundamental]
1116+
pub struct Pin<'a, T: ?Sized + 'a> {
1117+
inner: &'a mut T,
1118+
}
1119+
1120+
#[unstable(feature = "pin", issue = "49150")]
1121+
impl<'a, T: ?Sized + Unpin> Pin<'a, T> {
1122+
/// Construct a new `Pin` around a reference to some data of a type that
1123+
/// implements `Unpin`.
1124+
#[unstable(feature = "pin", issue = "49150")]
1125+
pub fn new(reference: &'a mut T) -> Pin<'a, T> {
1126+
Pin { inner: reference }
1127+
}
1128+
}
1129+
1130+
1131+
#[unstable(feature = "pin", issue = "49150")]
1132+
impl<'a, T: ?Sized> Pin<'a, T> {
1133+
/// Construct a new `Pin` around a reference to some data of a type that
1134+
/// may or may not implement `Unpin`.
1135+
///
1136+
/// This constructor is unsafe because we do not know what will happen with
1137+
/// that data after the reference ends. If you cannot guarantee that the
1138+
/// data will never move again, calling this constructor is invalid.
1139+
#[unstable(feature = "pin", issue = "49150")]
1140+
pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> {
1141+
Pin { inner: reference }
1142+
}
1143+
1144+
/// Borrow a Pin for a shorter lifetime than it already has.
1145+
#[unstable(feature = "pin", issue = "49150")]
1146+
pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> {
1147+
Pin { inner: this.inner }
1148+
}
1149+
1150+
/// Get a mutable reference to the data inside of this `Pin`.
1151+
///
1152+
/// This function is unsafe. You must guarantee that you will never move
1153+
/// the data out of the mutable reference you receive when you call this
1154+
/// function.
1155+
#[unstable(feature = "pin", issue = "49150")]
1156+
pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T {
1157+
this.inner
1158+
}
1159+
1160+
/// Construct a new pin by mapping the interior value.
1161+
///
1162+
/// For example, if you wanted to get a `Pin` of a field of something, you
1163+
/// could use this to get access to that field in one line of code.
1164+
///
1165+
/// This function is unsafe. You must guarantee that the data you return
1166+
/// will not move so long as the argument value does not move (for example,
1167+
/// because it is one of the fields of that value), and also that you do
1168+
/// not move out of the argument you receive to the interior function.
1169+
#[unstable(feature = "pin", issue = "49150")]
1170+
pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where
1171+
F: FnOnce(&mut T) -> &mut U
1172+
{
1173+
Pin { inner: f(this.inner) }
1174+
}
1175+
}
1176+
1177+
#[unstable(feature = "pin", issue = "49150")]
1178+
impl<'a, T: ?Sized> Deref for Pin<'a, T> {
1179+
type Target = T;
1180+
1181+
fn deref(&self) -> &T {
1182+
&*self.inner
1183+
}
1184+
}
1185+
1186+
#[unstable(feature = "pin", issue = "49150")]
1187+
impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> {
1188+
fn deref_mut(&mut self) -> &mut T {
1189+
self.inner
1190+
}
1191+
}
1192+
1193+
#[unstable(feature = "pin", issue = "49150")]
1194+
impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> {
1195+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1196+
fmt::Debug::fmt(&**self, f)
1197+
}
1198+
}
1199+
1200+
#[unstable(feature = "pin", issue = "49150")]
1201+
impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> {
1202+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1203+
fmt::Display::fmt(&**self, f)
1204+
}
1205+
}
1206+
1207+
#[unstable(feature = "pin", issue = "49150")]
1208+
impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> {
1209+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1210+
fmt::Pointer::fmt(&(&*self.inner as *const T), f)
1211+
}
1212+
}
1213+
1214+
#[unstable(feature = "pin", issue = "49150")]
1215+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<'a, U>> for Pin<'a, T> {}

src/test/rustdoc/synthetic_auto/no-redundancy.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// ignore-test
12+
1113
pub struct Inner<T> {
1214
field: T,
1315
}

0 commit comments

Comments
 (0)