]>
Commit | Line | Data |
---|---|---|
041b39d2 XL |
1 | // Copyright 2012 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | /// Both `PLACE <- EXPR` and `box EXPR` desugar into expressions | |
12 | /// that allocate an intermediate "place" that holds uninitialized | |
13 | /// state. The desugaring evaluates EXPR, and writes the result at | |
14 | /// the address returned by the `pointer` method of this trait. | |
15 | /// | |
16 | /// A `Place` can be thought of as a special representation for a | |
17 | /// hypothetical `&uninit` reference (which Rust cannot currently | |
18 | /// express directly). That is, it represents a pointer to | |
19 | /// uninitialized storage. | |
20 | /// | |
21 | /// The client is responsible for two steps: First, initializing the | |
22 | /// payload (it can access its address via `pointer`). Second, | |
23 | /// converting the agent to an instance of the owning pointer, via the | |
24 | /// appropriate `finalize` method (see the `InPlace`. | |
25 | /// | |
26 | /// If evaluating EXPR fails, then it is up to the destructor for the | |
27 | /// implementation of Place to clean up any intermediate state | |
28 | /// (e.g. deallocate box storage, pop a stack, etc). | |
29 | #[unstable(feature = "placement_new_protocol", issue = "27779")] | |
30 | pub trait Place<Data: ?Sized> { | |
31 | /// Returns the address where the input value will be written. | |
32 | /// Note that the data at this address is generally uninitialized, | |
33 | /// and thus one should use `ptr::write` for initializing it. | |
34 | fn pointer(&mut self) -> *mut Data; | |
35 | } | |
36 | ||
37 | /// Interface to implementations of `PLACE <- EXPR`. | |
38 | /// | |
39 | /// `PLACE <- EXPR` effectively desugars into: | |
40 | /// | |
41 | /// ``` | |
42 | /// # #![feature(placement_new_protocol, box_heap)] | |
43 | /// # use std::ops::{Placer, Place, InPlace}; | |
44 | /// # #[allow(non_snake_case)] | |
45 | /// # fn main() { | |
46 | /// # let PLACE = std::boxed::HEAP; | |
47 | /// # let EXPR = 1; | |
48 | /// let p = PLACE; | |
49 | /// let mut place = Placer::make_place(p); | |
50 | /// let raw_place = Place::pointer(&mut place); | |
51 | /// let value = EXPR; | |
52 | /// unsafe { | |
53 | /// std::ptr::write(raw_place, value); | |
54 | /// InPlace::finalize(place) | |
55 | /// } | |
56 | /// # ; } | |
57 | /// ``` | |
58 | /// | |
59 | /// The type of `PLACE <- EXPR` is derived from the type of `PLACE`; | |
60 | /// if the type of `PLACE` is `P`, then the final type of the whole | |
61 | /// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` | |
62 | /// traits). | |
63 | /// | |
64 | /// Values for types implementing this trait usually are transient | |
65 | /// intermediate values (e.g. the return value of `Vec::emplace_back`) | |
66 | /// or `Copy`, since the `make_place` method takes `self` by value. | |
67 | #[unstable(feature = "placement_new_protocol", issue = "27779")] | |
68 | pub trait Placer<Data: ?Sized> { | |
3b2f2976 | 69 | /// `Place` is the intermediate agent guarding the |
041b39d2 XL |
70 | /// uninitialized state for `Data`. |
71 | type Place: InPlace<Data>; | |
72 | ||
73 | /// Creates a fresh place from `self`. | |
74 | fn make_place(self) -> Self::Place; | |
75 | } | |
76 | ||
77 | /// Specialization of `Place` trait supporting `PLACE <- EXPR`. | |
78 | #[unstable(feature = "placement_new_protocol", issue = "27779")] | |
79 | pub trait InPlace<Data: ?Sized>: Place<Data> { | |
80 | /// `Owner` is the type of the end value of `PLACE <- EXPR` | |
81 | /// | |
82 | /// Note that when `PLACE <- EXPR` is solely used for | |
83 | /// side-effecting an existing data-structure, | |
84 | /// e.g. `Vec::emplace_back`, then `Owner` need not carry any | |
85 | /// information at all (e.g. it can be the unit type `()` in that | |
86 | /// case). | |
87 | type Owner; | |
88 | ||
89 | /// Converts self into the final value, shifting | |
90 | /// deallocation/cleanup responsibilities (if any remain), over to | |
91 | /// the returned instance of `Owner` and forgetting self. | |
92 | unsafe fn finalize(self) -> Self::Owner; | |
93 | } | |
94 | ||
95 | /// Core trait for the `box EXPR` form. | |
96 | /// | |
97 | /// `box EXPR` effectively desugars into: | |
98 | /// | |
99 | /// ``` | |
100 | /// # #![feature(placement_new_protocol)] | |
101 | /// # use std::ops::{BoxPlace, Place, Boxed}; | |
102 | /// # #[allow(non_snake_case)] | |
103 | /// # fn main() { | |
104 | /// # let EXPR = 1; | |
105 | /// let mut place = BoxPlace::make_place(); | |
106 | /// let raw_place = Place::pointer(&mut place); | |
107 | /// let value = EXPR; | |
108 | /// # let _: Box<_> = | |
109 | /// unsafe { | |
110 | /// ::std::ptr::write(raw_place, value); | |
111 | /// Boxed::finalize(place) | |
112 | /// } | |
113 | /// # ; } | |
114 | /// ``` | |
115 | /// | |
116 | /// The type of `box EXPR` is supplied from its surrounding | |
117 | /// context; in the above expansion, the result type `T` is used | |
118 | /// to determine which implementation of `Boxed` to use, and that | |
119 | /// `<T as Boxed>` in turn dictates determines which | |
120 | /// implementation of `BoxPlace` to use, namely: | |
121 | /// `<<T as Boxed>::Place as BoxPlace>`. | |
122 | #[unstable(feature = "placement_new_protocol", issue = "27779")] | |
123 | pub trait Boxed { | |
124 | /// The kind of data that is stored in this kind of box. | |
125 | type Data; /* (`Data` unused b/c cannot yet express below bound.) */ | |
126 | /// The place that will negotiate the storage of the data. | |
127 | type Place: BoxPlace<Self::Data>; | |
128 | ||
129 | /// Converts filled place into final owning value, shifting | |
130 | /// deallocation/cleanup responsibilities (if any remain), over to | |
131 | /// returned instance of `Self` and forgetting `filled`. | |
132 | unsafe fn finalize(filled: Self::Place) -> Self; | |
133 | } | |
134 | ||
135 | /// Specialization of `Place` trait supporting `box EXPR`. | |
136 | #[unstable(feature = "placement_new_protocol", issue = "27779")] | |
137 | pub trait BoxPlace<Data: ?Sized> : Place<Data> { | |
138 | /// Creates a globally fresh place. | |
139 | fn make_place() -> Self; | |
140 | } |