]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2015 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 | ||
85aaf69f SL |
11 | //! A pointer type for heap allocation. |
12 | //! | |
62682a34 SL |
13 | //! `Box<T>`, casually referred to as a 'box', provides the simplest form of |
14 | //! heap allocation in Rust. Boxes provide ownership for this allocation, and | |
15 | //! drop their contents when they go out of scope. | |
85aaf69f SL |
16 | //! |
17 | //! # Examples | |
18 | //! | |
19 | //! Creating a box: | |
20 | //! | |
21 | //! ``` | |
22 | //! let x = Box::new(5); | |
23 | //! ``` | |
24 | //! | |
25 | //! Creating a recursive data structure: | |
26 | //! | |
27 | //! ``` | |
28 | //! #[derive(Debug)] | |
29 | //! enum List<T> { | |
30 | //! Cons(T, Box<List<T>>), | |
31 | //! Nil, | |
32 | //! } | |
33 | //! | |
34 | //! fn main() { | |
35 | //! let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); | |
36 | //! println!("{:?}", list); | |
37 | //! } | |
38 | //! ``` | |
39 | //! | |
d9579d0f | 40 | //! This will print `Cons(1, Cons(2, Nil))`. |
9346a6ac | 41 | //! |
62682a34 SL |
42 | //! Recursive structures must be boxed, because if the definition of `Cons` |
43 | //! looked like this: | |
9346a6ac AL |
44 | //! |
45 | //! ```rust,ignore | |
46 | //! Cons(T, List<T>), | |
47 | //! ``` | |
48 | //! | |
62682a34 SL |
49 | //! It wouldn't work. This is because the size of a `List` depends on how many |
50 | //! elements are in the list, and so we don't know how much memory to allocate | |
51 | //! for a `Cons`. By introducing a `Box`, which has a defined size, we know how | |
52 | //! big `Cons` needs to be. | |
1a4d82fc | 53 | |
85aaf69f SL |
54 | #![stable(feature = "rust1", since = "1.0.0")] |
55 | ||
c1a9b12d SL |
56 | use heap; |
57 | use raw_vec::RawVec; | |
58 | ||
1a4d82fc | 59 | use core::any::Any; |
e9174d1e | 60 | use core::borrow; |
85aaf69f | 61 | use core::cmp::Ordering; |
1a4d82fc JJ |
62 | use core::fmt; |
63 | use core::hash::{self, Hash}; | |
c1a9b12d | 64 | use core::marker::{self, Unsize}; |
1a4d82fc | 65 | use core::mem; |
62682a34 | 66 | use core::ops::{CoerceUnsized, Deref, DerefMut}; |
c1a9b12d SL |
67 | use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace}; |
68 | use core::ptr::{self, Unique}; | |
b039eaaf | 69 | use core::raw::TraitObject; |
92a42be0 | 70 | use core::convert::From; |
1a4d82fc | 71 | |
85aaf69f SL |
72 | /// A value that represents the heap. This is the default place that the `box` |
73 | /// keyword allocates into when no place is supplied. | |
1a4d82fc JJ |
74 | /// |
75 | /// The following two examples are equivalent: | |
76 | /// | |
c34b1796 | 77 | /// ``` |
c1a9b12d SL |
78 | /// #![feature(box_heap)] |
79 | /// | |
80 | /// #![feature(box_syntax, placement_in_syntax)] | |
1a4d82fc JJ |
81 | /// use std::boxed::HEAP; |
82 | /// | |
83 | /// fn main() { | |
b039eaaf | 84 | /// let foo: Box<i32> = in HEAP { 5 }; |
85aaf69f | 85 | /// let foo = box 5; |
1a4d82fc JJ |
86 | /// } |
87 | /// ``` | |
62682a34 | 88 | #[unstable(feature = "box_heap", |
e9174d1e SL |
89 | reason = "may be renamed; uncertain about custom allocator design", |
90 | issue = "27779")] | |
92a42be0 | 91 | pub const HEAP: ExchangeHeapSingleton = ExchangeHeapSingleton { _force_singleton: () }; |
c1a9b12d SL |
92 | |
93 | /// This the singleton type used solely for `boxed::HEAP`. | |
94 | #[unstable(feature = "box_heap", | |
e9174d1e SL |
95 | reason = "may be renamed; uncertain about custom allocator design", |
96 | issue = "27779")] | |
c1a9b12d | 97 | #[derive(Copy, Clone)] |
b039eaaf SL |
98 | pub struct ExchangeHeapSingleton { |
99 | _force_singleton: (), | |
100 | } | |
1a4d82fc | 101 | |
85aaf69f SL |
102 | /// A pointer type for heap allocation. |
103 | /// | |
104 | /// See the [module-level documentation](../../std/boxed/index.html) for more. | |
1a4d82fc | 105 | #[lang = "owned_box"] |
85aaf69f | 106 | #[stable(feature = "rust1", since = "1.0.0")] |
c1a9b12d SL |
107 | pub struct Box<T: ?Sized>(Unique<T>); |
108 | ||
109 | /// `IntermediateBox` represents uninitialized backing storage for `Box`. | |
110 | /// | |
111 | /// FIXME (pnkfelix): Ideally we would just reuse `Box<T>` instead of | |
112 | /// introducing a separate `IntermediateBox<T>`; but then you hit | |
113 | /// issues when you e.g. attempt to destructure an instance of `Box`, | |
114 | /// since it is a lang item and so it gets special handling by the | |
115 | /// compiler. Easier just to make this parallel type for now. | |
116 | /// | |
117 | /// FIXME (pnkfelix): Currently the `box` protocol only supports | |
118 | /// creating instances of sized types. This IntermediateBox is | |
119 | /// designed to be forward-compatible with a future protocol that | |
120 | /// supports creating instances of unsized types; that is why the type | |
121 | /// parameter has the `?Sized` generalization marker, and is also why | |
122 | /// this carries an explicit size. However, it probably does not need | |
123 | /// to carry the explicit alignment; that is just a work-around for | |
124 | /// the fact that the `align_of` intrinsic currently requires the | |
125 | /// input type to be Sized (which I do not think is strictly | |
126 | /// necessary). | |
e9174d1e SL |
127 | #[unstable(feature = "placement_in", |
128 | reason = "placement box design is still being worked out.", | |
129 | issue = "27779")] | |
b039eaaf | 130 | pub struct IntermediateBox<T: ?Sized> { |
c1a9b12d SL |
131 | ptr: *mut u8, |
132 | size: usize, | |
133 | align: usize, | |
134 | marker: marker::PhantomData<*mut T>, | |
135 | } | |
136 | ||
92a42be0 SL |
137 | #[unstable(feature = "placement_in", |
138 | reason = "placement box design is still being worked out.", | |
139 | issue = "27779")] | |
c1a9b12d SL |
140 | impl<T> Place<T> for IntermediateBox<T> { |
141 | fn pointer(&mut self) -> *mut T { | |
b039eaaf | 142 | self.ptr as *mut T |
c1a9b12d SL |
143 | } |
144 | } | |
145 | ||
146 | unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> { | |
147 | let p = b.ptr as *mut T; | |
148 | mem::forget(b); | |
149 | mem::transmute(p) | |
150 | } | |
151 | ||
152 | fn make_place<T>() -> IntermediateBox<T> { | |
153 | let size = mem::size_of::<T>(); | |
154 | let align = mem::align_of::<T>(); | |
155 | ||
156 | let p = if size == 0 { | |
157 | heap::EMPTY as *mut u8 | |
158 | } else { | |
b039eaaf | 159 | let p = unsafe { heap::allocate(size, align) }; |
c1a9b12d SL |
160 | if p.is_null() { |
161 | panic!("Box make_place allocation failure."); | |
162 | } | |
163 | p | |
164 | }; | |
165 | ||
b039eaaf SL |
166 | IntermediateBox { |
167 | ptr: p, | |
168 | size: size, | |
169 | align: align, | |
170 | marker: marker::PhantomData, | |
171 | } | |
c1a9b12d SL |
172 | } |
173 | ||
92a42be0 SL |
174 | #[unstable(feature = "placement_in", |
175 | reason = "placement box design is still being worked out.", | |
176 | issue = "27779")] | |
c1a9b12d | 177 | impl<T> BoxPlace<T> for IntermediateBox<T> { |
b039eaaf SL |
178 | fn make_place() -> IntermediateBox<T> { |
179 | make_place() | |
180 | } | |
c1a9b12d SL |
181 | } |
182 | ||
92a42be0 SL |
183 | #[unstable(feature = "placement_in", |
184 | reason = "placement box design is still being worked out.", | |
185 | issue = "27779")] | |
c1a9b12d SL |
186 | impl<T> InPlace<T> for IntermediateBox<T> { |
187 | type Owner = Box<T>; | |
b039eaaf SL |
188 | unsafe fn finalize(self) -> Box<T> { |
189 | finalize(self) | |
190 | } | |
c1a9b12d SL |
191 | } |
192 | ||
92a42be0 | 193 | #[unstable(feature = "placement_new_protocol", issue = "27779")] |
c1a9b12d SL |
194 | impl<T> Boxed for Box<T> { |
195 | type Data = T; | |
196 | type Place = IntermediateBox<T>; | |
b039eaaf SL |
197 | unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> { |
198 | finalize(b) | |
199 | } | |
c1a9b12d SL |
200 | } |
201 | ||
92a42be0 SL |
202 | #[unstable(feature = "placement_in", |
203 | reason = "placement box design is still being worked out.", | |
204 | issue = "27779")] | |
c1a9b12d SL |
205 | impl<T> Placer<T> for ExchangeHeapSingleton { |
206 | type Place = IntermediateBox<T>; | |
207 | ||
208 | fn make_place(self) -> IntermediateBox<T> { | |
209 | make_place() | |
210 | } | |
211 | } | |
212 | ||
92a42be0 SL |
213 | #[unstable(feature = "placement_in", |
214 | reason = "placement box design is still being worked out.", | |
215 | issue = "27779")] | |
c1a9b12d SL |
216 | impl<T: ?Sized> Drop for IntermediateBox<T> { |
217 | fn drop(&mut self) { | |
218 | if self.size > 0 { | |
b039eaaf | 219 | unsafe { heap::deallocate(self.ptr, self.size, self.align) } |
c1a9b12d SL |
220 | } |
221 | } | |
222 | } | |
1a4d82fc JJ |
223 | |
224 | impl<T> Box<T> { | |
85aaf69f SL |
225 | /// Allocates memory on the heap and then moves `x` into it. |
226 | /// | |
227 | /// # Examples | |
228 | /// | |
229 | /// ``` | |
230 | /// let x = Box::new(5); | |
231 | /// ``` | |
232 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 233 | #[inline(always)] |
1a4d82fc JJ |
234 | pub fn new(x: T) -> Box<T> { |
235 | box x | |
236 | } | |
237 | } | |
238 | ||
92a42be0 | 239 | impl<T: ?Sized> Box<T> { |
85aaf69f SL |
240 | /// Constructs a box from the raw pointer. |
241 | /// | |
242 | /// After this function call, pointer is owned by resulting box. | |
243 | /// In particular, it means that `Box` destructor calls destructor | |
244 | /// of `T` and releases memory. Since the way `Box` allocates and | |
c34b1796 AL |
245 | /// releases memory is unspecified, the only valid pointer to pass |
246 | /// to this function is the one taken from another `Box` with | |
c1a9b12d | 247 | /// `Box::into_raw` function. |
85aaf69f SL |
248 | /// |
249 | /// Function is unsafe, because improper use of this function may | |
250 | /// lead to memory problems like double-free, for example if the | |
251 | /// function is called twice on the same raw pointer. | |
e9174d1e | 252 | #[stable(feature = "box_raw", since = "1.4.0")] |
c34b1796 | 253 | #[inline] |
85aaf69f SL |
254 | pub unsafe fn from_raw(raw: *mut T) -> Self { |
255 | mem::transmute(raw) | |
256 | } | |
62682a34 SL |
257 | |
258 | /// Consumes the `Box`, returning the wrapped raw pointer. | |
259 | /// | |
260 | /// After call to this function, caller is responsible for the memory | |
261 | /// previously managed by `Box`, in particular caller should properly | |
262 | /// destroy `T` and release memory. The proper way to do it is to | |
263 | /// convert pointer back to `Box` with `Box::from_raw` function, because | |
264 | /// `Box` does not specify, how memory is allocated. | |
265 | /// | |
266 | /// # Examples | |
62682a34 | 267 | /// |
e9174d1e | 268 | /// ``` |
62682a34 | 269 | /// let seventeen = Box::new(17u32); |
c1a9b12d | 270 | /// let raw = Box::into_raw(seventeen); |
62682a34 SL |
271 | /// let boxed_again = unsafe { Box::from_raw(raw) }; |
272 | /// ``` | |
e9174d1e | 273 | #[stable(feature = "box_raw", since = "1.4.0")] |
62682a34 | 274 | #[inline] |
62682a34 SL |
275 | pub fn into_raw(b: Box<T>) -> *mut T { |
276 | unsafe { mem::transmute(b) } | |
277 | } | |
85aaf69f SL |
278 | } |
279 | ||
85aaf69f | 280 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 281 | impl<T: Default> Default for Box<T> { |
b039eaaf SL |
282 | fn default() -> Box<T> { |
283 | box Default::default() | |
284 | } | |
1a4d82fc JJ |
285 | } |
286 | ||
85aaf69f | 287 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 288 | impl<T> Default for Box<[T]> { |
b039eaaf SL |
289 | fn default() -> Box<[T]> { |
290 | Box::<[T; 0]>::new([]) | |
291 | } | |
1a4d82fc JJ |
292 | } |
293 | ||
85aaf69f | 294 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 295 | impl<T: Clone> Clone for Box<T> { |
85aaf69f SL |
296 | /// Returns a new box with a `clone()` of this box's contents. |
297 | /// | |
298 | /// # Examples | |
299 | /// | |
300 | /// ``` | |
301 | /// let x = Box::new(5); | |
302 | /// let y = x.clone(); | |
303 | /// ``` | |
b039eaaf | 304 | #[rustfmt_skip] |
1a4d82fc | 305 | #[inline] |
b039eaaf SL |
306 | fn clone(&self) -> Box<T> { |
307 | box { (**self).clone() } | |
308 | } | |
85aaf69f SL |
309 | /// Copies `source`'s contents into `self` without creating a new allocation. |
310 | /// | |
311 | /// # Examples | |
312 | /// | |
313 | /// ``` | |
314 | /// let x = Box::new(5); | |
315 | /// let mut y = Box::new(10); | |
316 | /// | |
317 | /// y.clone_from(&x); | |
318 | /// | |
319 | /// assert_eq!(*y, 5); | |
320 | /// ``` | |
1a4d82fc JJ |
321 | #[inline] |
322 | fn clone_from(&mut self, source: &Box<T>) { | |
323 | (**self).clone_from(&(**source)); | |
324 | } | |
325 | } | |
326 | ||
c1a9b12d SL |
327 | |
328 | #[stable(feature = "box_slice_clone", since = "1.3.0")] | |
329 | impl Clone for Box<str> { | |
330 | fn clone(&self) -> Self { | |
331 | let len = self.len(); | |
332 | let buf = RawVec::with_capacity(len); | |
333 | unsafe { | |
334 | ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); | |
335 | mem::transmute(buf.into_box()) // bytes to str ~magic | |
336 | } | |
337 | } | |
338 | } | |
339 | ||
85aaf69f | 340 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
341 | impl<T: ?Sized + PartialEq> PartialEq for Box<T> { |
342 | #[inline] | |
b039eaaf SL |
343 | fn eq(&self, other: &Box<T>) -> bool { |
344 | PartialEq::eq(&**self, &**other) | |
345 | } | |
1a4d82fc | 346 | #[inline] |
b039eaaf SL |
347 | fn ne(&self, other: &Box<T>) -> bool { |
348 | PartialEq::ne(&**self, &**other) | |
349 | } | |
1a4d82fc | 350 | } |
85aaf69f | 351 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
352 | impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> { |
353 | #[inline] | |
354 | fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> { | |
355 | PartialOrd::partial_cmp(&**self, &**other) | |
356 | } | |
357 | #[inline] | |
b039eaaf SL |
358 | fn lt(&self, other: &Box<T>) -> bool { |
359 | PartialOrd::lt(&**self, &**other) | |
360 | } | |
1a4d82fc | 361 | #[inline] |
b039eaaf SL |
362 | fn le(&self, other: &Box<T>) -> bool { |
363 | PartialOrd::le(&**self, &**other) | |
364 | } | |
1a4d82fc | 365 | #[inline] |
b039eaaf SL |
366 | fn ge(&self, other: &Box<T>) -> bool { |
367 | PartialOrd::ge(&**self, &**other) | |
368 | } | |
1a4d82fc | 369 | #[inline] |
b039eaaf SL |
370 | fn gt(&self, other: &Box<T>) -> bool { |
371 | PartialOrd::gt(&**self, &**other) | |
372 | } | |
1a4d82fc | 373 | } |
85aaf69f | 374 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
375 | impl<T: ?Sized + Ord> Ord for Box<T> { |
376 | #[inline] | |
377 | fn cmp(&self, other: &Box<T>) -> Ordering { | |
378 | Ord::cmp(&**self, &**other) | |
379 | } | |
380 | } | |
85aaf69f | 381 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
382 | impl<T: ?Sized + Eq> Eq for Box<T> {} |
383 | ||
85aaf69f SL |
384 | #[stable(feature = "rust1", since = "1.0.0")] |
385 | impl<T: ?Sized + Hash> Hash for Box<T> { | |
386 | fn hash<H: hash::Hasher>(&self, state: &mut H) { | |
1a4d82fc JJ |
387 | (**self).hash(state); |
388 | } | |
389 | } | |
390 | ||
92a42be0 SL |
391 | #[stable(feature = "from_for_ptrs", since = "1.6.0")] |
392 | impl<T> From<T> for Box<T> { | |
393 | fn from(t: T) -> Self { | |
394 | Box::new(t) | |
395 | } | |
396 | } | |
397 | ||
c34b1796 | 398 | impl Box<Any> { |
1a4d82fc | 399 | #[inline] |
c34b1796 | 400 | #[stable(feature = "rust1", since = "1.0.0")] |
bd371182 | 401 | /// Attempt to downcast the box to a concrete type. |
c34b1796 | 402 | pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> { |
1a4d82fc JJ |
403 | if self.is::<T>() { |
404 | unsafe { | |
405 | // Get the raw representation of the trait object | |
62682a34 | 406 | let raw = Box::into_raw(self); |
b039eaaf | 407 | let to: TraitObject = mem::transmute::<*mut Any, TraitObject>(raw); |
1a4d82fc JJ |
408 | |
409 | // Extract the data pointer | |
c34b1796 | 410 | Ok(Box::from_raw(to.data as *mut T)) |
1a4d82fc JJ |
411 | } |
412 | } else { | |
413 | Err(self) | |
414 | } | |
415 | } | |
416 | } | |
417 | ||
bd371182 | 418 | impl Box<Any + Send> { |
c34b1796 AL |
419 | #[inline] |
420 | #[stable(feature = "rust1", since = "1.0.0")] | |
bd371182 AL |
421 | /// Attempt to downcast the box to a concrete type. |
422 | pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> { | |
423 | <Box<Any>>::downcast(self).map_err(|s| unsafe { | |
424 | // reapply the Send marker | |
425 | mem::transmute::<Box<Any>, Box<Any + Send>>(s) | |
426 | }) | |
c34b1796 AL |
427 | } |
428 | } | |
429 | ||
85aaf69f SL |
430 | #[stable(feature = "rust1", since = "1.0.0")] |
431 | impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> { | |
1a4d82fc | 432 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
85aaf69f | 433 | fmt::Display::fmt(&**self, f) |
1a4d82fc JJ |
434 | } |
435 | } | |
436 | ||
85aaf69f SL |
437 | #[stable(feature = "rust1", since = "1.0.0")] |
438 | impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> { | |
1a4d82fc | 439 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
85aaf69f | 440 | fmt::Debug::fmt(&**self, f) |
1a4d82fc JJ |
441 | } |
442 | } | |
443 | ||
9346a6ac AL |
444 | #[stable(feature = "rust1", since = "1.0.0")] |
445 | impl<T> fmt::Pointer for Box<T> { | |
446 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
447 | // It's not possible to extract the inner Uniq directly from the Box, | |
448 | // instead we cast it to a *const which aliases the Unique | |
449 | let ptr: *const T = &**self; | |
450 | fmt::Pointer::fmt(&ptr, f) | |
451 | } | |
452 | } | |
453 | ||
85aaf69f | 454 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
455 | impl<T: ?Sized> Deref for Box<T> { |
456 | type Target = T; | |
457 | ||
b039eaaf SL |
458 | fn deref(&self) -> &T { |
459 | &**self | |
460 | } | |
1a4d82fc JJ |
461 | } |
462 | ||
85aaf69f | 463 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 464 | impl<T: ?Sized> DerefMut for Box<T> { |
b039eaaf SL |
465 | fn deref_mut(&mut self) -> &mut T { |
466 | &mut **self | |
467 | } | |
1a4d82fc JJ |
468 | } |
469 | ||
85aaf69f SL |
470 | #[stable(feature = "rust1", since = "1.0.0")] |
471 | impl<I: Iterator + ?Sized> Iterator for Box<I> { | |
472 | type Item = I::Item; | |
b039eaaf SL |
473 | fn next(&mut self) -> Option<I::Item> { |
474 | (**self).next() | |
475 | } | |
476 | fn size_hint(&self) -> (usize, Option<usize>) { | |
477 | (**self).size_hint() | |
478 | } | |
85aaf69f SL |
479 | } |
480 | #[stable(feature = "rust1", since = "1.0.0")] | |
481 | impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> { | |
b039eaaf SL |
482 | fn next_back(&mut self) -> Option<I::Item> { |
483 | (**self).next_back() | |
484 | } | |
85aaf69f SL |
485 | } |
486 | #[stable(feature = "rust1", since = "1.0.0")] | |
487 | impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {} | |
1a4d82fc | 488 | |
c34b1796 AL |
489 | |
490 | /// `FnBox` is a version of the `FnOnce` intended for use with boxed | |
491 | /// closure objects. The idea is that where one would normally store a | |
492 | /// `Box<FnOnce()>` in a data structure, you should use | |
493 | /// `Box<FnBox()>`. The two traits behave essentially the same, except | |
494 | /// that a `FnBox` closure can only be called if it is boxed. (Note | |
495 | /// that `FnBox` may be deprecated in the future if `Box<FnOnce()>` | |
496 | /// closures become directly usable.) | |
497 | /// | |
498 | /// ### Example | |
499 | /// | |
500 | /// Here is a snippet of code which creates a hashmap full of boxed | |
501 | /// once closures and then removes them one by one, calling each | |
502 | /// closure as it is removed. Note that the type of the closures | |
503 | /// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce() | |
504 | /// -> i32>`. | |
505 | /// | |
506 | /// ``` | |
62682a34 | 507 | /// #![feature(fnbox)] |
c34b1796 AL |
508 | /// |
509 | /// use std::boxed::FnBox; | |
510 | /// use std::collections::HashMap; | |
511 | /// | |
512 | /// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> { | |
513 | /// let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new(); | |
514 | /// map.insert(1, Box::new(|| 22)); | |
515 | /// map.insert(2, Box::new(|| 44)); | |
516 | /// map | |
517 | /// } | |
518 | /// | |
519 | /// fn main() { | |
520 | /// let mut map = make_map(); | |
521 | /// for i in &[1, 2] { | |
522 | /// let f = map.remove(&i).unwrap(); | |
523 | /// assert_eq!(f(), i * 22); | |
524 | /// } | |
525 | /// } | |
526 | /// ``` | |
527 | #[rustc_paren_sugar] | |
e9174d1e | 528 | #[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")] |
c34b1796 AL |
529 | pub trait FnBox<A> { |
530 | type Output; | |
531 | ||
532 | fn call_box(self: Box<Self>, args: A) -> Self::Output; | |
533 | } | |
534 | ||
92a42be0 SL |
535 | #[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")] |
536 | impl<A, F> FnBox<A> for F where F: FnOnce<A> | |
c34b1796 AL |
537 | { |
538 | type Output = F::Output; | |
539 | ||
540 | fn call_box(self: Box<F>, args: A) -> F::Output { | |
541 | self.call_once(args) | |
542 | } | |
543 | } | |
544 | ||
92a42be0 SL |
545 | #[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")] |
546 | impl<'a, A, R> FnOnce<A> for Box<FnBox<A, Output = R> + 'a> { | |
c34b1796 AL |
547 | type Output = R; |
548 | ||
549 | extern "rust-call" fn call_once(self, args: A) -> R { | |
550 | self.call_box(args) | |
551 | } | |
552 | } | |
553 | ||
92a42be0 SL |
554 | #[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")] |
555 | impl<'a, A, R> FnOnce<A> for Box<FnBox<A, Output = R> + Send + 'a> { | |
c34b1796 AL |
556 | type Output = R; |
557 | ||
558 | extern "rust-call" fn call_once(self, args: A) -> R { | |
559 | self.call_box(args) | |
1a4d82fc JJ |
560 | } |
561 | } | |
d9579d0f | 562 | |
92a42be0 SL |
563 | #[unstable(feature = "coerce_unsized", issue = "27732")] |
564 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {} | |
c1a9b12d SL |
565 | |
566 | #[stable(feature = "box_slice_clone", since = "1.3.0")] | |
567 | impl<T: Clone> Clone for Box<[T]> { | |
568 | fn clone(&self) -> Self { | |
569 | let mut new = BoxBuilder { | |
570 | data: RawVec::with_capacity(self.len()), | |
b039eaaf | 571 | len: 0, |
c1a9b12d SL |
572 | }; |
573 | ||
574 | let mut target = new.data.ptr(); | |
575 | ||
576 | for item in self.iter() { | |
577 | unsafe { | |
578 | ptr::write(target, item.clone()); | |
579 | target = target.offset(1); | |
580 | }; | |
581 | ||
582 | new.len += 1; | |
583 | } | |
584 | ||
585 | return unsafe { new.into_box() }; | |
586 | ||
587 | // Helper type for responding to panics correctly. | |
588 | struct BoxBuilder<T> { | |
589 | data: RawVec<T>, | |
590 | len: usize, | |
591 | } | |
592 | ||
593 | impl<T> BoxBuilder<T> { | |
594 | unsafe fn into_box(self) -> Box<[T]> { | |
595 | let raw = ptr::read(&self.data); | |
596 | mem::forget(self); | |
597 | raw.into_box() | |
598 | } | |
599 | } | |
600 | ||
601 | impl<T> Drop for BoxBuilder<T> { | |
602 | fn drop(&mut self) { | |
603 | let mut data = self.data.ptr(); | |
604 | let max = unsafe { data.offset(self.len as isize) }; | |
605 | ||
606 | while data != max { | |
607 | unsafe { | |
608 | ptr::read(data); | |
609 | data = data.offset(1); | |
610 | } | |
611 | } | |
612 | } | |
613 | } | |
614 | } | |
615 | } | |
616 | ||
92a42be0 | 617 | #[stable(feature = "rust1", since = "1.0.0")] |
e9174d1e | 618 | impl<T: ?Sized> borrow::Borrow<T> for Box<T> { |
b039eaaf SL |
619 | fn borrow(&self) -> &T { |
620 | &**self | |
621 | } | |
e9174d1e SL |
622 | } |
623 | ||
92a42be0 | 624 | #[stable(feature = "rust1", since = "1.0.0")] |
e9174d1e | 625 | impl<T: ?Sized> borrow::BorrowMut<T> for Box<T> { |
b039eaaf SL |
626 | fn borrow_mut(&mut self) -> &mut T { |
627 | &mut **self | |
628 | } | |
629 | } | |
630 | ||
631 | #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] | |
632 | impl<T: ?Sized> AsRef<T> for Box<T> { | |
633 | fn as_ref(&self) -> &T { | |
634 | &**self | |
635 | } | |
636 | } | |
637 | ||
638 | #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] | |
639 | impl<T: ?Sized> AsMut<T> for Box<T> { | |
640 | fn as_mut(&mut self) -> &mut T { | |
641 | &mut **self | |
642 | } | |
e9174d1e | 643 | } |