From 13da951868a1b48108592cadbf7627d48322c859 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Thu, 9 Aug 2018 18:20:22 +0300 Subject: move PinMut into pin module and export through std --- src/liballoc/boxed.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 32292e61f94..94c7b873179 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -64,7 +64,8 @@ use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; use core::marker::{Unpin, Unsize}; -use core::mem::{self, PinMut}; +use core::mem; +use core::pin::PinMut; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError}; -- cgit 1.4.1-3-g733a5 From 971d7ed24966e64c8ec8352ada433b672c25012f Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Thu, 9 Aug 2018 19:33:57 +0300 Subject: move PinBox into pin module and export through std --- src/liballoc/boxed.rs | 202 ---------------------------------- src/liballoc/lib.rs | 1 + src/liballoc/pin.rs | 225 ++++++++++++++++++++++++++++++++++++++ src/libstd/pin.rs | 2 + src/test/run-pass/async-await.rs | 2 +- src/test/run-pass/futures-api.rs | 2 +- src/test/rustdoc-js/pinbox-new.js | 4 +- src/test/rustdoc-js/vec-new.js | 2 +- 8 files changed, 233 insertions(+), 207 deletions(-) create mode 100644 src/liballoc/pin.rs (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 94c7b873179..b5c2fd7526d 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -759,166 +759,6 @@ impl Generator for Box } } -/// A pinned, heap allocated reference. -#[unstable(feature = "pin", issue = "49150")] -#[fundamental] -#[repr(transparent)] -pub struct PinBox { - inner: Box, -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Allocate memory on the heap, move the data into it and pin it. - #[unstable(feature = "pin", issue = "49150")] - pub fn new(data: T) -> PinBox { - PinBox { inner: Box::new(data) } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Get a pinned reference to the data in this PinBox. - #[inline] - pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { - unsafe { PinMut::new_unchecked(&mut *self.inner) } - } - - /// Constructs a `PinBox` from a raw pointer. - /// - /// After calling this function, the raw pointer is owned by the - /// resulting `PinBox`. Specifically, the `PinBox` destructor will call - /// the destructor of `T` and free the allocated memory. Since the - /// way `PinBox` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `PinBox` via the [`PinBox::into_raw`] function. - /// - /// This function is unsafe because improper use may lead to - /// memory problems. For example, a double-free may occur if the - /// function is called twice on the same raw pointer. - /// - /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::boxed::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// let x = unsafe { PinBox::from_raw(ptr) }; - /// ``` - #[inline] - pub unsafe fn from_raw(raw: *mut T) -> Self { - PinBox { inner: Box::from_raw(raw) } - } - - /// Consumes the `PinBox`, returning the wrapped raw pointer. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `PinBox`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `PinBox` with the [`PinBox::from_raw`] function. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::boxed::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// ``` - #[inline] - pub fn into_raw(b: PinBox) -> *mut T { - Box::into_raw(b.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. - #[inline] - pub unsafe fn get_mut<'a>(this: &'a mut PinBox) -> &'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. - #[inline] - pub unsafe fn unpin(this: PinBox) -> Box { - this.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl From> for PinBox { - fn from(boxed: Box) -> PinBox { - PinBox { inner: boxed } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl From> for Box { - fn from(pinned: PinBox) -> Box { - pinned.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl Deref for PinBox { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl DerefMut for PinBox { - fn deref_mut(&mut self) -> &mut T { - &mut *self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Display for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Debug for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Pointer for PinBox { - 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, U: ?Sized> CoerceUnsized> for PinBox {} - -#[unstable(feature = "pin", issue = "49150")] -impl Unpin for PinBox {} - #[unstable(feature = "futures_api", issue = "50547")] impl Future for Box { type Output = F::Output; @@ -928,15 +768,6 @@ impl Future for Box { } } -#[unstable(feature = "futures_api", issue = "50547")] -impl Future for PinBox { - type Output = F::Output; - - fn poll(mut self: PinMut, cx: &mut Context) -> Poll { - self.as_pin_mut().poll(cx) - } -} - #[unstable(feature = "futures_api", issue = "50547")] unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box where F: Future + 'a @@ -956,25 +787,6 @@ unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box } } -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox - where F: Future + 'a -{ - fn into_raw(self) -> *mut () { - PinBox::into_raw(self) as *mut () - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - let ptr = ptr as *mut F; - let pin: PinMut = PinMut::new_unchecked(&mut *ptr); - pin.poll(cx) - } - - unsafe fn drop(ptr: *mut ()) { - drop(PinBox::from_raw(ptr as *mut F)) - } -} - #[unstable(feature = "futures_api", issue = "50547")] impl Spawn for Box where Sp: Spawn + ?Sized @@ -991,13 +803,6 @@ impl Spawn for Box } } -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { - FutureObj::new(boxed) - } -} - #[unstable(feature = "futures_api", issue = "50547")] impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: Box) -> Self { @@ -1005,13 +810,6 @@ impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> } } -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { - LocalFutureObj::new(boxed) - } -} - #[unstable(feature = "futures_api", issue = "50547")] impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { fn from(boxed: Box) -> Self { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index bcdfd8c9aa5..99e8f8df0d9 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -159,6 +159,7 @@ pub mod collections; pub mod sync; pub mod rc; pub mod raw_vec; +pub mod pin; pub mod prelude; pub mod borrow; pub mod fmt; diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs new file mode 100644 index 00000000000..221a55472ab --- /dev/null +++ b/src/liballoc/pin.rs @@ -0,0 +1,225 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Types which pin data to its location in memory + +#![unstable(feature = "pin", issue = "49150")] + +use core::convert::From; +use core::fmt; +use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; +use core::marker::{Unpin, Unsize}; +use core::pin::PinMut; +use core::ops::{CoerceUnsized, Deref, DerefMut}; +use core::task::{Context, Poll}; + +use boxed::Box; + +/// A pinned, heap allocated reference. +#[unstable(feature = "pin", issue = "49150")] +#[fundamental] +#[repr(transparent)] +pub struct PinBox { + inner: Box, +} + +#[unstable(feature = "pin", issue = "49150")] +impl PinBox { + /// Allocate memory on the heap, move the data into it and pin it. + #[unstable(feature = "pin", issue = "49150")] + pub fn new(data: T) -> PinBox { + PinBox { inner: Box::new(data) } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl PinBox { + /// Get a pinned reference to the data in this PinBox. + #[inline] + pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { + unsafe { PinMut::new_unchecked(&mut *self.inner) } + } + + /// Constructs a `PinBox` from a raw pointer. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `PinBox`. Specifically, the `PinBox` destructor will call + /// the destructor of `T` and free the allocated memory. Since the + /// way `PinBox` allocates and releases memory is unspecified, the + /// only valid pointer to pass to this function is the one taken + /// from another `PinBox` via the [`PinBox::into_raw`] function. + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw + /// + /// # Examples + /// + /// ``` + /// #![feature(pin)] + /// use std::pin::PinBox; + /// let x = PinBox::new(5); + /// let ptr = PinBox::into_raw(x); + /// let x = unsafe { PinBox::from_raw(ptr) }; + /// ``` + #[inline] + pub unsafe fn from_raw(raw: *mut T) -> Self { + PinBox { inner: Box::from_raw(raw) } + } + + /// Consumes the `PinBox`, returning the wrapped raw pointer. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `PinBox`. In particular, the + /// caller should properly destroy `T` and release the memory. The + /// proper way to do so is to convert the raw pointer back into a + /// `PinBox` with the [`PinBox::from_raw`] function. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw + /// + /// # Examples + /// + /// ``` + /// #![feature(pin)] + /// use std::pin::PinBox; + /// let x = PinBox::new(5); + /// let ptr = PinBox::into_raw(x); + /// ``` + #[inline] + pub fn into_raw(b: PinBox) -> *mut T { + Box::into_raw(b.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. + #[inline] + pub unsafe fn get_mut<'a>(this: &'a mut PinBox) -> &'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. + #[inline] + pub unsafe fn unpin(this: PinBox) -> Box { + this.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl From> for PinBox { + fn from(boxed: Box) -> PinBox { + PinBox { inner: boxed } + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl From> for Box { + fn from(pinned: PinBox) -> Box { + pinned.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl Deref for PinBox { + type Target = T; + + fn deref(&self) -> &T { + &*self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl DerefMut for PinBox { + fn deref_mut(&mut self) -> &mut T { + &mut *self.inner + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Display for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&*self.inner, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Debug for PinBox { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&*self.inner, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl fmt::Pointer for PinBox { + 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, U: ?Sized> CoerceUnsized> for PinBox {} + +#[unstable(feature = "pin", issue = "49150")] +impl Unpin for PinBox {} + +#[unstable(feature = "futures_api", issue = "50547")] +impl Future for PinBox { + type Output = F::Output; + + fn poll(mut self: PinMut, cx: &mut Context) -> Poll { + self.as_pin_mut().poll(cx) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox + where F: Future + 'a +{ + fn into_raw(self) -> *mut () { + PinBox::into_raw(self) as *mut () + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + let ptr = ptr as *mut F; + let pin: PinMut = PinMut::new_unchecked(&mut *ptr); + pin.poll(cx) + } + + unsafe fn drop(ptr: *mut ()) { + drop(PinBox::from_raw(ptr as *mut F)) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { + fn from(boxed: PinBox) -> Self { + FutureObj::new(boxed) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { + fn from(boxed: PinBox) -> Self { + LocalFutureObj::new(boxed) + } +} diff --git a/src/libstd/pin.rs b/src/libstd/pin.rs index 9d7a9d4404a..b3c5b5feb8c 100644 --- a/src/libstd/pin.rs +++ b/src/libstd/pin.rs @@ -13,3 +13,5 @@ #![unstable(feature = "pin", issue = "49150")] pub use core::pin::*; + +pub use alloc_crate::pin::*; diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 7e79a210f15..46f22845907 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -12,7 +12,7 @@ #![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)] -use std::boxed::PinBox; +use std::pin::PinBox; use std::pin::PinMut; use std::future::Future; use std::sync::{ diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index ff2facd3cd2..69a04437691 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -11,7 +11,7 @@ #![feature(arbitrary_self_types, futures_api, pin)] #![allow(unused)] -use std::boxed::PinBox; +use std::pin::PinBox; use std::future::Future; use std::pin::PinMut; use std::rc::Rc; diff --git a/src/test/rustdoc-js/pinbox-new.js b/src/test/rustdoc-js/pinbox-new.js index 061c7b30741..55842dc8e45 100644 --- a/src/test/rustdoc-js/pinbox-new.js +++ b/src/test/rustdoc-js/pinbox-new.js @@ -14,7 +14,7 @@ const QUERY = 'pinbox::new'; const EXPECTED = { 'others': [ - { 'path': 'std::boxed::PinBox', 'name': 'new' }, - { 'path': 'alloc::boxed::PinBox', 'name': 'new' }, + { 'path': 'std::pin::PinBox', 'name': 'new' }, + { 'path': 'alloc::pin::PinBox', 'name': 'new' }, ], }; diff --git a/src/test/rustdoc-js/vec-new.js b/src/test/rustdoc-js/vec-new.js index 702953e2e9d..4a654ccb135 100644 --- a/src/test/rustdoc-js/vec-new.js +++ b/src/test/rustdoc-js/vec-new.js @@ -14,6 +14,6 @@ const EXPECTED = { 'others': [ { 'path': 'std::vec::Vec', 'name': 'new' }, { 'path': 'std::vec::Vec', 'name': 'ne' }, - { 'path': 'std::boxed::PinBox', 'name': 'new' }, + { 'path': 'std::pin::PinBox', 'name': 'new' }, ], }; -- cgit 1.4.1-3-g733a5 From 30bb4af5d8191f016a82c75a0c2b4700b23bd724 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Thu, 9 Aug 2018 20:10:30 +0300 Subject: add top-level documentation to the std pin module --- src/liballoc/pin.rs | 4 +++ src/libcore/pin.rs | 4 +++ src/libstd/pin.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 1 deletion(-) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index 221a55472ab..1b6ccae456a 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -9,6 +9,10 @@ // except according to those terms. //! Types which pin data to its location in memory +//! +//! see the [standard library module] for more information +//! +//! [standard library module]: ../../std/pin/index.html #![unstable(feature = "pin", issue = "49150")] diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index a41185e231b..74fb02d2e11 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -9,6 +9,10 @@ // except according to those terms. //! Types which pin data to its location in memory +//! +//! see the [standard library module] for more information +//! +//! [standard library module]: ../../std/pin/index.html #![unstable(feature = "pin", issue = "49150")] diff --git a/src/libstd/pin.rs b/src/libstd/pin.rs index b3c5b5feb8c..0b78414e4bf 100644 --- a/src/libstd/pin.rs +++ b/src/libstd/pin.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,6 +9,85 @@ // except according to those terms. //! Types which pin data to its location in memory +//! +//! It is sometimes useful to have objects that are guaranteed to not move, +//! in the sense that their placement in memory in consistent, and can thus be relied upon. +//! +//! A prime example of such a scenario would be building self-referencial structs, +//! since moving an object with pointers to itself will invalidate them, +//! which could cause undefined behavior. +//! +//! In order to prevent objects from moving, they must be *pinned*, +//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`]. +//! These restrict access to the underlying data to only be immutable by implementing [`Deref`], +//! unless the type implements the [`Unpin`] trait, +//! which indicates that it doesn't need these restrictions and can be safely mutated, +//! by implementing [`DerefMut`]. +//! +//! This is done because, while modifying an object can be done in-place, +//! it might also relocate a buffer when its at full capacity, +//! or it might replace one object with another without logically "moving" them with [`swap`]. +//! +//! [`PinMut`]: struct.PinMut.html +//! [`PinBox`]: struct.PinBox.html +//! [`Unpin`]: ../marker/trait.Unpin.html +//! [`DerefMut`]: ../ops/trait.DerefMut.html +//! [`Deref`]: ../ops/trait.Deref.html +//! [`swap`]: ../mem/fn.swap.html +//! +//! # Examples +//! +//! ```rust +//! #![feature(pin)] +//! +//! use std::pin::PinBox; +//! use std::marker::Pinned; +//! use std::ptr::NonNull; +//! +//! // This is a self referencial struct since the slice field points to the data field. +//! // We cannot inform the compiler about that with a normal reference, +//! // since this pattern cannot be described with the usual borrowing rules. +//! // Instead we use a raw pointer, though one which is known to not be null, +//! // since we know it's pointing at the string. +//! struct Unmovable { +//! data: String, +//! slice: NonNull, +//! _pin: Pinned, +//! } +//! +//! impl Unmovable { +//! // To ensure the data doesn't move when the function returns, +//! // we place it in the heap where it will stay for the lifetime of the object, +//! // and the only way to access it would be through a pointer to it. +//! fn new(data: String) -> PinBox { +//! let res = Unmovable { +//! data, +//! // we only create the pointer once the data is in place +//! // otherwise it will have already moved before we even started +//! slice: NonNull::dangling(), +//! _pin: Pinned, +//! }; +//! let mut boxed = PinBox::new(res); +//! +//! let slice = NonNull::from(&boxed.data); +//! // we know this is safe because modifying a field doesn't move the whole struct +//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; +//! boxed +//! } +//! } +//! +//! let unmoved = Unmovable::new("hello".to_string()); +//! // The pointer should point to the correct location, +//! // so long as the struct hasn't moved. +//! // Meanwhile, we are free to move the pointer around. +//! let mut still_unmoved = unmoved; +//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); +//! +//! // Now the only way to access to data (safely) is immutably, +//! // so this will fail to compile: +//! // still_unmoved.data.push_str(" world"); +//! +//! ``` #![unstable(feature = "pin", issue = "49150")] -- cgit 1.4.1-3-g733a5 From c4ec0cd36927a4a010dc6789bdd88eaa503dadd6 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Fri, 10 Aug 2018 10:10:35 +0300 Subject: attempt to work around Box not being recognized as local type --- src/liballoc/boxed.rs | 8 ++++++++ src/liballoc/pin.rs | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b5c2fd7526d..c25f3eb8f17 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -71,6 +71,7 @@ use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError}; use raw_vec::RawVec; +use pin::PinBox; use str::from_boxed_utf8_unchecked; /// A pointer type for heap allocation. @@ -816,3 +817,10 @@ impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { LocalFutureObj::new(boxed) } } + +#[unstable(feature = "pin", issue = "49150")] +impl From> for Box { + fn from(pinned: PinBox) -> Box { + unsafe { PinBox::unpin(pinned) } + } +} diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index 1b6ccae456a..bacc13fa74a 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -133,13 +133,6 @@ impl From> for PinBox { } } -#[unstable(feature = "pin", issue = "49150")] -impl From> for Box { - fn from(pinned: PinBox) -> Box { - pinned.inner - } -} - #[unstable(feature = "pin", issue = "49150")] impl Deref for PinBox { type Target = T; -- cgit 1.4.1-3-g733a5 From f9efd0578a890d9441da468cc5eed6b9f2ed87df Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 14 Aug 2018 19:06:51 +0300 Subject: move pin module to liballoc and reexport that --- src/liballoc/pin.rs | 82 +++++++++++++++++++++++++++++++++++++++++++-- src/libstd/lib.rs | 3 +- src/libstd/pin.rs | 96 ----------------------------------------------------- 3 files changed, 81 insertions(+), 100 deletions(-) delete mode 100644 src/libstd/pin.rs (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index bacc13fa74a..0ecf4ac0a69 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -10,17 +10,93 @@ //! Types which pin data to its location in memory //! -//! see the [standard library module] for more information +//! It is sometimes useful to have objects that are guaranteed to not move, +//! in the sense that their placement in memory in consistent, and can thus be relied upon. //! -//! [standard library module]: ../../std/pin/index.html +//! A prime example of such a scenario would be building self-referencial structs, +//! since moving an object with pointers to itself will invalidate them, +//! which could cause undefined behavior. +//! +//! In order to prevent objects from moving, they must be *pinned*, +//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`]. +//! These restrict access to the underlying data to only be immutable by implementing [`Deref`], +//! unless the type implements the [`Unpin`] trait, +//! which indicates that it doesn't need these restrictions and can be safely mutated, +//! by implementing [`DerefMut`]. +//! +//! This is done because, while modifying an object can be done in-place, +//! it might also relocate a buffer when its at full capacity, +//! or it might replace one object with another without logically "moving" them with [`swap`]. +//! +//! [`PinMut`]: struct.PinMut.html +//! [`PinBox`]: struct.PinBox.html +//! [`Unpin`]: ../../core/marker/trait.Unpin.html +//! [`DerefMut`]: ../../core/ops/trait.DerefMut.html +//! [`Deref`]: ../../core/ops/trait.Deref.html +//! [`swap`]: ../../core/mem/fn.swap.html +//! +//! # Examples +//! +//! ```rust +//! #![feature(pin)] +//! +//! use std::pin::PinBox; +//! use std::marker::Pinned; +//! use std::ptr::NonNull; +//! +//! // This is a self referencial struct since the slice field points to the data field. +//! // We cannot inform the compiler about that with a normal reference, +//! // since this pattern cannot be described with the usual borrowing rules. +//! // Instead we use a raw pointer, though one which is known to not be null, +//! // since we know it's pointing at the string. +//! struct Unmovable { +//! data: String, +//! slice: NonNull, +//! _pin: Pinned, +//! } +//! +//! impl Unmovable { +//! // To ensure the data doesn't move when the function returns, +//! // we place it in the heap where it will stay for the lifetime of the object, +//! // and the only way to access it would be through a pointer to it. +//! fn new(data: String) -> PinBox { +//! let res = Unmovable { +//! data, +//! // we only create the pointer once the data is in place +//! // otherwise it will have already moved before we even started +//! slice: NonNull::dangling(), +//! _pin: Pinned, +//! }; +//! let mut boxed = PinBox::new(res); +//! +//! let slice = NonNull::from(&boxed.data); +//! // we know this is safe because modifying a field doesn't move the whole struct +//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; +//! boxed +//! } +//! } +//! +//! let unmoved = Unmovable::new("hello".to_string()); +//! // The pointer should point to the correct location, +//! // so long as the struct hasn't moved. +//! // Meanwhile, we are free to move the pointer around. +//! let mut still_unmoved = unmoved; +//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); +//! +//! // Now the only way to access to data (safely) is immutably, +//! // so this will fail to compile: +//! // still_unmoved.data.push_str(" world"); +//! +//! ``` #![unstable(feature = "pin", issue = "49150")] +pub use core::pin::*; + use core::convert::From; use core::fmt; use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; use core::marker::{Unpin, Unsize}; -use core::pin::PinMut; use core::ops::{CoerceUnsized, Deref, DerefMut}; use core::task::{Context, Poll}; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ac65274d254..c60ebafd46c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -434,6 +434,8 @@ pub use alloc_crate::borrow; pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::format; +#[unstable(feature = "pin", issue = "49150")] +pub use alloc_crate::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::slice; #[stable(feature = "rust1", since = "1.0.0")] @@ -466,7 +468,6 @@ pub mod num; pub mod os; pub mod panic; pub mod path; -pub mod pin; pub mod process; pub mod sync; pub mod time; diff --git a/src/libstd/pin.rs b/src/libstd/pin.rs deleted file mode 100644 index 0b78414e4bf..00000000000 --- a/src/libstd/pin.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Types which pin data to its location in memory -//! -//! It is sometimes useful to have objects that are guaranteed to not move, -//! in the sense that their placement in memory in consistent, and can thus be relied upon. -//! -//! A prime example of such a scenario would be building self-referencial structs, -//! since moving an object with pointers to itself will invalidate them, -//! which could cause undefined behavior. -//! -//! In order to prevent objects from moving, they must be *pinned*, -//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`]. -//! These restrict access to the underlying data to only be immutable by implementing [`Deref`], -//! unless the type implements the [`Unpin`] trait, -//! which indicates that it doesn't need these restrictions and can be safely mutated, -//! by implementing [`DerefMut`]. -//! -//! This is done because, while modifying an object can be done in-place, -//! it might also relocate a buffer when its at full capacity, -//! or it might replace one object with another without logically "moving" them with [`swap`]. -//! -//! [`PinMut`]: struct.PinMut.html -//! [`PinBox`]: struct.PinBox.html -//! [`Unpin`]: ../marker/trait.Unpin.html -//! [`DerefMut`]: ../ops/trait.DerefMut.html -//! [`Deref`]: ../ops/trait.Deref.html -//! [`swap`]: ../mem/fn.swap.html -//! -//! # Examples -//! -//! ```rust -//! #![feature(pin)] -//! -//! use std::pin::PinBox; -//! use std::marker::Pinned; -//! use std::ptr::NonNull; -//! -//! // This is a self referencial struct since the slice field points to the data field. -//! // We cannot inform the compiler about that with a normal reference, -//! // since this pattern cannot be described with the usual borrowing rules. -//! // Instead we use a raw pointer, though one which is known to not be null, -//! // since we know it's pointing at the string. -//! struct Unmovable { -//! data: String, -//! slice: NonNull, -//! _pin: Pinned, -//! } -//! -//! impl Unmovable { -//! // To ensure the data doesn't move when the function returns, -//! // we place it in the heap where it will stay for the lifetime of the object, -//! // and the only way to access it would be through a pointer to it. -//! fn new(data: String) -> PinBox { -//! let res = Unmovable { -//! data, -//! // we only create the pointer once the data is in place -//! // otherwise it will have already moved before we even started -//! slice: NonNull::dangling(), -//! _pin: Pinned, -//! }; -//! let mut boxed = PinBox::new(res); -//! -//! let slice = NonNull::from(&boxed.data); -//! // we know this is safe because modifying a field doesn't move the whole struct -//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; -//! boxed -//! } -//! } -//! -//! let unmoved = Unmovable::new("hello".to_string()); -//! // The pointer should point to the correct location, -//! // so long as the struct hasn't moved. -//! // Meanwhile, we are free to move the pointer around. -//! let mut still_unmoved = unmoved; -//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); -//! -//! // Now the only way to access to data (safely) is immutably, -//! // so this will fail to compile: -//! // still_unmoved.data.push_str(" world"); -//! -//! ``` - -#![unstable(feature = "pin", issue = "49150")] - -pub use core::pin::*; - -pub use alloc_crate::pin::*; -- cgit 1.4.1-3-g733a5 From 1bb05797c26b77f9541b03ac1c44c723b01959f5 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 14 Aug 2018 19:25:08 +0300 Subject: expand the documentation on PinBox --- src/liballoc/pin.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index 0ecf4ac0a69..92414f5555e 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -103,6 +103,15 @@ use core::task::{Context, Poll}; use boxed::Box; /// A pinned, heap allocated reference. +/// +/// This type is similar to [`Box`], except that it pins its value, +/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. +/// +/// See the [module documentation] for furthur explaination on pinning. +/// +/// [`Box`]: ../boxed/struct.Box.html +/// [`Unpin`]: ../../core/marker/trait.Unpin.html +/// [module documentation]: index.html #[unstable(feature = "pin", issue = "49150")] #[fundamental] #[repr(transparent)] -- cgit 1.4.1-3-g733a5 From 8e9aad268ef0994a2edfb77b33cffc4d5a220970 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 14 Aug 2018 21:04:39 +0300 Subject: deemphasize immutability and improve swap explanation in pin module --- src/liballoc/pin.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index 92414f5555e..8cb57ade865 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -11,7 +11,7 @@ //! Types which pin data to its location in memory //! //! It is sometimes useful to have objects that are guaranteed to not move, -//! in the sense that their placement in memory in consistent, and can thus be relied upon. +//! in the sense that their placement in memory does not change, and can thus be relied upon. //! //! A prime example of such a scenario would be building self-referencial structs, //! since moving an object with pointers to itself will invalidate them, @@ -19,20 +19,17 @@ //! //! In order to prevent objects from moving, they must be *pinned*, //! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`]. -//! These restrict access to the underlying data to only be immutable by implementing [`Deref`], +//! On top of ensuring the data cannot be taked by value by being pointers, +//! these types restrict access to the underlying data such that it cannot be moved out of them, //! unless the type implements the [`Unpin`] trait, -//! which indicates that it doesn't need these restrictions and can be safely mutated, -//! by implementing [`DerefMut`]. +//! which indicates that it can be used safely without these restrictions. //! -//! This is done because, while modifying an object can be done in-place, -//! it might also relocate a buffer when its at full capacity, -//! or it might replace one object with another without logically "moving" them with [`swap`]. +//! A type may be moved out of a reference to it using a function like [`swap`], +//! which replaces the contents of the references, and thus changes their place in memory. //! //! [`PinMut`]: struct.PinMut.html //! [`PinBox`]: struct.PinBox.html //! [`Unpin`]: ../../core/marker/trait.Unpin.html -//! [`DerefMut`]: ../../core/ops/trait.DerefMut.html -//! [`Deref`]: ../../core/ops/trait.Deref.html //! [`swap`]: ../../core/mem/fn.swap.html //! //! # Examples @@ -83,10 +80,9 @@ //! let mut still_unmoved = unmoved; //! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); //! -//! // Now the only way to access to data (safely) is immutably, -//! // so this will fail to compile: -//! // still_unmoved.data.push_str(" world"); -//! +//! // Since our type doesn't implement Unpin, this will fail to compile: +//! // let new_unmoved = Unmovable::new("world".to_string()); +//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` #![unstable(feature = "pin", issue = "49150")] -- cgit 1.4.1-3-g733a5 From 6b47a6105c69c018792f07ae9d472b478a45bed9 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Sat, 18 Aug 2018 12:52:38 +0300 Subject: allow unused mut for pinning explanation --- src/liballoc/pin.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index 8cb57ade865..f7c804b2aba 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -77,6 +77,7 @@ //! // The pointer should point to the correct location, //! // so long as the struct hasn't moved. //! // Meanwhile, we are free to move the pointer around. +//! # #[allow(unused_mut)] //! let mut still_unmoved = unmoved; //! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); //! -- cgit 1.4.1-3-g733a5 From 1304cee86244a8cad0d7547a56fcad50a2b73916 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 21 Aug 2018 15:19:18 +0300 Subject: add more info on Unpin and connect paragraphs better --- src/liballoc/pin.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index f7c804b2aba..a1abaf74b26 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -18,19 +18,26 @@ //! which could cause undefined behavior. //! //! In order to prevent objects from moving, they must be *pinned*, -//! by wrapping the data in special pointer types, such as [`PinMut`] and [`PinBox`]. -//! On top of ensuring the data cannot be taked by value by being pointers, -//! these types restrict access to the underlying data such that it cannot be moved out of them, -//! unless the type implements the [`Unpin`] trait, -//! which indicates that it can be used safely without these restrictions. +//! by wrapping the data in pinning pointer types, such as [`PinMut`] and [`PinBox`], +//! which are otherwise equivalent to `& mut` and [`Box`], respectively. //! -//! A type may be moved out of a reference to it using a function like [`swap`], -//! which replaces the contents of the references, and thus changes their place in memory. +//! First of all, these are pointer types because pinned data mustn't be passed around by value +//! (that would change its location in memory). +//! Secondly, since data can be moved out of `&mut` and [`Box`] with functions such as [`swap`], +//! which causes their contents to swap places in memory, +//! we need dedicated types that prohibit such operations. +//! +//! However, these restrictions are usually not necessary, +//! so most types implement the [`Unpin`] auto-trait, +//! which indicates that the type can be moved out safely. +//! Doing so removes the limitations of pinning types, +//! making them the same as their non-pinning counterparts. //! //! [`PinMut`]: struct.PinMut.html //! [`PinBox`]: struct.PinBox.html //! [`Unpin`]: ../../core/marker/trait.Unpin.html //! [`swap`]: ../../core/mem/fn.swap.html +//! [`Box`]: ../boxed/struct.Box.html //! //! # Examples //! -- cgit 1.4.1-3-g733a5 From bfed149020cc48260056c8621d93a7931fba6bde Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 21 Aug 2018 15:24:14 +0300 Subject: reexport Unpin into pin module --- src/liballoc/pin.rs | 3 ++- src/libcore/marker.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index a1abaf74b26..a5bc4c75bd5 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -96,11 +96,12 @@ #![unstable(feature = "pin", issue = "49150")] pub use core::pin::*; +pub use core::marker::Unpin; use core::convert::From; use core::fmt; use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; -use core::marker::{Unpin, Unsize}; +use core::marker::Unsize; use core::ops::{CoerceUnsized, Deref, DerefMut}; use core::task::{Context, Poll}; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 8e674c0bb7f..11f4821a925 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -630,7 +630,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// /// This trait is automatically implemented for almost every type. /// -/// [`replace`]: ../mem/fn.replace.html +/// [`replace`]: ../../core/mem/fn.replace.html /// [`PinMut`]: ../pin/struct.PinMut.html #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} -- cgit 1.4.1-3-g733a5 From b26cce5ec045391d5d38e46c32aae30439b4560f Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Thu, 23 Aug 2018 01:16:35 +0300 Subject: link to items in pin module to std docs --- src/liballoc/pin.rs | 6 +++--- src/libcore/marker.rs | 4 ++-- src/libcore/pin.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index a5bc4c75bd5..625c42a6490 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -35,8 +35,8 @@ //! //! [`PinMut`]: struct.PinMut.html //! [`PinBox`]: struct.PinBox.html -//! [`Unpin`]: ../../core/marker/trait.Unpin.html -//! [`swap`]: ../../core/mem/fn.swap.html +//! [`Unpin`]: trait.Unpin.html +//! [`swap`]: ../../std/mem/fn.swap.html //! [`Box`]: ../boxed/struct.Box.html //! //! # Examples @@ -115,7 +115,7 @@ use boxed::Box; /// See the [module documentation] for furthur explaination on pinning. /// /// [`Box`]: ../boxed/struct.Box.html -/// [`Unpin`]: ../../core/marker/trait.Unpin.html +/// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [module documentation]: index.html #[unstable(feature = "pin", issue = "49150")] #[fundamental] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 191634a9930..dd57d2dd009 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -632,9 +632,9 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// /// This trait is automatically implemented for almost every type. /// -/// [`replace`]: ../../core/mem/fn.replace.html +/// [`replace`]: ../../std/mem/fn.replace.html /// [`PinMut`]: ../pin/struct.PinMut.html -/// [`pin module`]: ../../alloc/pin/index.html +/// [`pin module`]: ../../std/pin/index.html #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 380330d2eb1..65057dfdace 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -29,8 +29,8 @@ use ops::{Deref, DerefMut, CoerceUnsized}; /// /// See the [`pin` module] documentation for furthur explanation on pinning. /// -/// [`Unpin`]: ../../core/marker/trait.Unpin.html -/// [`pin` module]: ../../alloc/pin/index.html +/// [`Unpin`]: ../../std/marker/trait.Unpin.html +/// [`pin` module]: ../../std/pin/index.html #[unstable(feature = "pin", issue = "49150")] #[fundamental] pub struct PinMut<'a, T: ?Sized + 'a> { -- cgit 1.4.1-3-g733a5 From 83ca347343f5783779b908c264c9470634d3758c Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Sat, 25 Aug 2018 00:07:00 +0300 Subject: remove copyright headers now that they are not madatory --- src/liballoc/pin.rs | 10 ---------- src/libcore/pin.rs | 10 ---------- 2 files changed, 20 deletions(-) (limited to 'src/liballoc') diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs index 625c42a6490..17bbc9882d9 100644 --- a/src/liballoc/pin.rs +++ b/src/liballoc/pin.rs @@ -1,13 +1,3 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Types which pin data to its location in memory //! //! It is sometimes useful to have objects that are guaranteed to not move, diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 65057dfdace..e9001f86b35 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -1,13 +1,3 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Types which pin data to its location in memory //! //! See the [standard library module] for more information. -- cgit 1.4.1-3-g733a5