diff options
| author | bors <bors@rust-lang.org> | 2015-07-24 10:12:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-07-24 10:12:20 +0000 |
| commit | 9413a926fcfc88c46ea04534508284a822e1109f (patch) | |
| tree | 191a7b86544a79d59a31a1c2080dc2bc9b5f4aa3 /src/libcore | |
| parent | 607f74df2ad6b6fb32ce5b862a9e48a8c4afdad2 (diff) | |
| parent | d066a7b5069ff857a5bffe7cb5168fe63158144f (diff) | |
| download | rust-9413a926fcfc88c46ea04534508284a822e1109f.tar.gz rust-9413a926fcfc88c46ea04534508284a822e1109f.zip | |
Auto merge of #27215 - pnkfelix:fsk-placer-take-5-just-in, r=nikomatsakis
Macro desugaring of `in PLACE { BLOCK }` into "simpler" expressions following the in-development "Placer" protocol.
Includes Placer API that one can override to integrate support for `in` into one's own type. (See [RFC 809].)
[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md
Part of #22181
Replaced PR #26180.
Turns on the `in PLACE { BLOCK }` syntax, while leaving in support for the old `box (PLACE) EXPR` syntax (since we need to support that at least until we have a snapshot with support for `in PLACE { BLOCK }`.
(Note that we are not 100% committed to the `in PLACE { BLOCK }` syntax. In particular I still want to play around with some other alternatives. Still, I want to get the fundamental framework for the protocol landed so we can play with implementing it for non `Box` types.)
----
Also, this PR leaves out support for desugaring-based `box EXPR`. We will hopefully land that in the future, but for the short term there are type-inference issues injected by that change that we want to resolve separately.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/intrinsics.rs | 8 | ||||
| -rw-r--r-- | src/libcore/ops.rs | 117 |
2 files changed, 125 insertions, 0 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ef022179772..1d466895f2c 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -184,6 +184,14 @@ extern "rust-intrinsic" { /// elements. pub fn size_of<T>() -> usize; + #[cfg(not(stage0))] + /// Moves a value to an uninitialized memory location. + /// + /// Drop glue is not run on the destination. + pub fn move_val_init<T>(dst: *mut T, src: T); + + // SNAP d4432b3 + #[cfg(stage0)] /// Moves a value to an uninitialized memory location. /// /// Drop glue is not run on the destination. diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index c2a9b8c8308..2ea42011a5c 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1266,3 +1266,120 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {} + +/// Both `in (PLACE) EXPR` and `box EXPR` desugar into expressions +/// that allocate an intermediate "place" that holds uninitialized +/// state. The desugaring evaluates EXPR, and writes the result at +/// the address returned by the `pointer` method of this trait. +/// +/// A `Place` can be thought of as a special representation for a +/// hypothetical `&uninit` reference (which Rust cannot currently +/// express directly). That is, it represents a pointer to +/// uninitialized storage. +/// +/// The client is responsible for two steps: First, initializing the +/// payload (it can access its address via `pointer`). Second, +/// converting the agent to an instance of the owning pointer, via the +/// appropriate `finalize` method (see the `InPlace`. +/// +/// If evaluating EXPR fails, then the destructor for the +/// implementation of Place to clean up any intermediate state +/// (e.g. deallocate box storage, pop a stack, etc). +#[unstable(feature = "placement_new_protocol")] +pub trait Place<Data: ?Sized> { + /// Returns the address where the input value will be written. + /// Note that the data at this address is generally uninitialized, + /// and thus one should use `ptr::write` for initializing it. + fn pointer(&mut self) -> *mut Data; +} + +/// Interface to implementations of `in (PLACE) EXPR`. +/// +/// `in (PLACE) EXPR` effectively desugars into: +/// +/// ```rust,ignore +/// let p = PLACE; +/// let mut place = Placer::make_place(p); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// std::ptr::write(raw_place, value); +/// InPlace::finalize(place) +/// } +/// ``` +/// +/// The type of `in (PLACE) EXPR` is derived from the type of `PLACE`; +/// if the type of `PLACE` is `P`, then the final type of the whole +/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` +/// traits). +/// +/// Values for types implementing this trait usually are transient +/// intermediate values (e.g. the return value of `Vec::emplace_back`) +/// or `Copy`, since the `make_place` method takes `self` by value. +#[unstable(feature = "placement_new_protocol")] +pub trait Placer<Data: ?Sized> { + /// `Place` is the intermedate agent guarding the + /// uninitialized state for `Data`. + type Place: InPlace<Data>; + + /// Creates a fresh place from `self`. + fn make_place(self) -> Self::Place; +} + +/// Specialization of `Place` trait supporting `in (PLACE) EXPR`. +#[unstable(feature = "placement_new_protocol")] +pub trait InPlace<Data: ?Sized>: Place<Data> { + /// `Owner` is the type of the end value of `in (PLACE) EXPR` + /// + /// Note that when `in (PLACE) EXPR` is solely used for + /// side-effecting an existing data-structure, + /// e.g. `Vec::emplace_back`, then `Owner` need not carry any + /// information at all (e.g. it can be the unit type `()` in that + /// case). + type Owner; + + /// Converts self into the final value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// the returned instance of `Owner` and forgetting self. + unsafe fn finalize(self) -> Self::Owner; +} + +/// Core trait for the `box EXPR` form. +/// +/// `box EXPR` effectively desugars into: +/// +/// ```rust,ignore +/// let mut place = BoxPlace::make_place(); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// ::std::ptr::write(raw_place, value); +/// Boxed::finalize(place) +/// } +/// ``` +/// +/// The type of `box EXPR` is supplied from its surrounding +/// context; in the above expansion, the result type `T` is used +/// to determine which implementation of `Boxed` to use, and that +/// `<T as Boxed>` in turn dictates determines which +/// implementation of `BoxPlace` to use, namely: +/// `<<T as Boxed>::Place as BoxPlace>`. +#[unstable(feature = "placement_new_protocol")] +pub trait Boxed { + /// The kind of data that is stored in this kind of box. + type Data; /* (`Data` unused b/c cannot yet express below bound.) */ + /// The place that will negotiate the storage of the data. + type Place: BoxPlace<Self::Data>; + + /// Converts filled place into final owning value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// returned instance of `Self` and forgetting `filled`. + unsafe fn finalize(filled: Self::Place) -> Self; +} + +/// Specialization of `Place` trait supporting `box EXPR`. +#[unstable(feature = "placement_new_protocol")] +pub trait BoxPlace<Data: ?Sized> : Place<Data> { + /// Creates a globally fresh place. + fn make_place() -> Self; +} |
