rune_alloc/boxed.rs
1//! The `Box<T>` type for heap allocation.
2//!
3//! [`Box<T>`], casually referred to as a 'box', provides the simplest form of
4//! heap allocation in Rust. Boxes provide ownership for this allocation, and
5//! drop their contents when they go out of scope. Boxes also ensure that they
6//! never allocate more than `isize::MAX` bytes.
7//!
8//! # Examples
9//!
10//! Move a value from the stack to the heap by creating a [`Box`]:
11//!
12//! ```
13//! use rune::alloc::Box;
14//!
15//! let val: u8 = 5;
16//! let boxed: Box<u8> = Box::try_new(val)?;
17//! # Ok::<_, rune::alloc::Error>(())
18//! ```
19//!
20//! Move a value from a [`Box`] back to the stack using [Box::into_inner]:
21//!
22//! ```
23//! use rune::alloc::Box;
24//!
25//! let boxed: Box<u8> = Box::try_new(5)?;
26//! let val: u8 = Box::into_inner(boxed);
27//! # Ok::<_, rune::alloc::Error>(())
28//! ```
29//!
30//! Creating a recursive data structure:
31//!
32//! ```
33//! use rune::alloc::Box;
34//!
35//! #[derive(Debug)]
36//! enum List<T> {
37//! Cons(T, Box<List<T>>),
38//! Nil,
39//! }
40//!
41//! let list: List<i32> = List::Cons(1, Box::try_new(List::Cons(2, Box::try_new(List::Nil)?))?);
42//! println!("{list:?}");
43//! # Ok::<_, rune::alloc::Error>(())
44//! ```
45//!
46//! This will print `Cons(1, Cons(2, Nil))`.
47//!
48//! Recursive structures must be boxed, because if the definition of `Cons`
49//! looked like this:
50//!
51//! ```compile_fail,E0072
52//! # enum List<T> {
53//! Cons(T, List<T>),
54//! # }
55//! ```
56//!
57//! It wouldn't work. This is because the size of a `List` depends on how many
58//! elements are in the list, and so we don't know how much memory to allocate
59//! for a `Cons`. By introducing a [`Box<T>`], which has a defined size, we know
60//! how big `Cons` needs to be.
61//!
62//! # Memory layout
63//!
64//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for
65//! its allocation. It is valid to convert both ways between a [`Box`] and a raw
66//! pointer allocated with the [`Global`] allocator, given that the [`Layout`]
67//! used with the allocator is correct for the type. More precisely, a `value:
68//! *mut T` that has been allocated with the [`Global`] allocator with
69//! `Layout::for_value(&*value)` may be converted into a box using
70//! [`Box::<T>::from_raw_in(value)`]. Conversely, the memory backing a `value:
71//! *mut T` obtained from [`Box::<T>::into_raw_with_allocator`] may be
72//! deallocated using the [`Global`] allocator with
73//! [`Layout::for_value(&*value)`].
74//!
75//! For zero-sized values, the `Box` pointer still has to be [valid] for reads
76//! and writes and sufficiently aligned. In particular, casting any aligned
77//! non-zero integer literal to a raw pointer produces a valid pointer, but a
78//! pointer pointing into previously allocated memory that since got freed is
79//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot
80//! be used is to use [`ptr::NonNull::dangling`].
81//!
82//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented as a
83//! single pointer and is also ABI-compatible with C pointers (i.e. the C type
84//! `T*`). This means that if you have extern "C" Rust functions that will be
85//! called from C, you can define those Rust functions using `Box<T>` types, and
86//! use `T*` as corresponding type on the C side. As an example, consider this C
87//! header which declares functions that create and destroy some kind of `Foo`
88//! value:
89//!
90//! ```c
91//! /* C header */
92//!
93//! /* Returns ownership to the caller */
94//! struct Foo* foo_new(void);
95//!
96//! /* Takes ownership from the caller; no-op when invoked with null */
97//! void foo_delete(struct Foo*);
98//! ```
99//!
100//! These two functions might be implemented in Rust as follows. Here, the
101//! `struct Foo*` type from C is translated to `Box<Foo>`, which captures the
102//! ownership constraints. Note also that the nullable argument to `foo_delete`
103//! is represented in Rust as `Option<Box<Foo>>`, since `Box<Foo>` cannot be
104//! null.
105//!
106//! ```
107//! use rune::alloc::Box;
108//! use rune::alloc::alloc::AllocError;
109//!
110//! #[repr(C)]
111//! pub struct Foo;
112//!
113//! #[no_mangle]
114//! pub extern "C" fn foo_new() -> Result<Box<Foo>, AllocError> {
115//! Box::try_new(Foo)
116//! }
117//!
118//! #[no_mangle]
119//! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
120//! ```
121//!
122//! Even though `Box<T>` has the same representation and C ABI as a C pointer,
123//! this does not mean that you can convert an arbitrary `T*` into a `Box<T>`
124//! and expect things to work. `Box<T>` values will always be fully aligned,
125//! non-null pointers. Moreover, the destructor for `Box<T>` will attempt to
126//! free the value with the global allocator. In general, the best practice is
127//! to only use `Box<T>` for pointers that originated from the global allocator.
128//!
129//! **Important.** At least at present, you should avoid using `Box<T>` types
130//! for functions that are defined in C but invoked from Rust. In those cases,
131//! you should directly mirror the C types as closely as possible. Using types
132//! like `Box<T>` where the C definition is just using `T*` can lead to
133//! undefined behavior, as described in
134//! [rust-lang/unsafe-code-guidelines#198][ucg#198].
135//!
136//! # Considerations for unsafe code
137//!
138//! **Warning: This section is not normative and is subject to change, possibly
139//! being relaxed in the future! It is a simplified summary of the rules
140//! currently implemented in the compiler.**
141//!
142//! The aliasing rules for `Box<T>` are the same as for `&mut T`. `Box<T>`
143//! asserts uniqueness over its content. Using raw pointers derived from a box
144//! after that box has been mutated through, moved or borrowed as `&mut T` is
145//! not allowed. For more guidance on working with box from unsafe code, see
146//! [rust-lang/unsafe-code-guidelines#326][ucg#326].
147//!
148//!
149//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
150//! [ucg#326]: https://github.com/rust-lang/unsafe-code-guidelines/issues/326
151//! [dereferencing]: core::ops::Deref
152//! [`Box::<T>::from_raw_in(value)`]: Box::from_raw_in
153//! [`Global`]: crate::alloc::Global
154//! [`Layout`]: core::alloc::Layout
155//! [`Layout::for_value(&*value)`]: core::alloc::Layout::for_value
156//! [valid]: core::ptr#safety
157
158use core::alloc::Layout;
159use core::borrow::{Borrow, BorrowMut};
160use core::cmp::Ordering;
161use core::fmt;
162use core::hash::{Hash, Hasher};
163use core::mem;
164use core::ops::{Deref, DerefMut};
165use core::pin::Pin;
166
167use crate::alloc::{AllocError, Allocator, Global};
168use crate::clone::TryClone;
169use crate::error::Error;
170use crate::iter::TryFromIteratorIn;
171use crate::path::Path;
172use crate::ptr::{self, Unique};
173use crate::raw_vec::RawVec;
174use crate::vec::Vec;
175
176#[test]
177fn ensure_niche_size() {
178 assert_eq!(
179 ::core::mem::size_of::<Option<Box<u32>>>(),
180 ::core::mem::size_of::<Box<u32>>()
181 );
182}
183
184/// A pointer type that uniquely owns a heap allocation of type `T`.
185pub struct Box<T: ?Sized, A: Allocator = Global> {
186 ptr: Unique<T>,
187 alloc: A,
188}
189
190impl<T> Box<T, Global> {
191 /// Allocates memory on the heap and then places `x` into it.
192 ///
193 /// This doesn't actually allocate if `T` is zero-sized.
194 ///
195 /// # Examples
196 ///
197 /// ```
198 /// use rune::alloc::Box;
199 ///
200 /// let five = Box::try_new(5)?;
201 /// # Ok::<_, rune::alloc::Error>(())
202 /// ```
203 pub fn try_new(value: T) -> Result<Self, AllocError> {
204 Self::try_new_in(value, Global)
205 }
206
207 /// Constructs a new `Pin<Box<T>>`. If `T` does not implement [`Unpin`],
208 /// then `x` will be pinned in memory and unable to be moved.
209 ///
210 /// Constructing and pinning of the `Box` can also be done in two steps:
211 /// `Box::try?pin(x)` does the same as
212 /// <code>[Box::into_pin]\([Box::try?new]\(x))</code>. Consider using
213 /// [`into_pin`](Box::into_pin) if you already have a `Box<T>`, or if you
214 /// want to construct a (pinned) `Box` in a different way than with
215 /// [`Box::try_new`].
216 #[inline(always)]
217 pub fn try_pin(x: T) -> Result<Pin<Box<T>>, AllocError> {
218 Ok(Box::try_new(x)?.into())
219 }
220}
221
222impl<T: ?Sized> Box<T> {
223 /// Convert from a std `Box`.
224 ///
225 /// This causes the underlying allocation to be accounted for by the
226 /// [`Global`] allocator.
227 ///
228 /// A caveat of this method is that the allocation is already in use, but
229 /// this might still be necessary because we want access to certain methods
230 /// in std `Box` such as the ability to coerce to unsized values.
231 ///
232 /// # Examples
233 ///
234 /// ```
235 /// use rune::alloc::{Box, Vec};
236 /// use rune::alloc::limit;
237 /// use std::boxed::Box as StdBox;
238 ///
239 /// assert_eq!(limit::get(), usize::MAX);
240 ///
241 /// let b: StdBox<dyn Iterator<Item = u32>> = StdBox::new(1..3);
242 /// let mut b = Box::from_std(b)?;
243 /// assert_eq!(b.next(), Some(1));
244 /// assert_eq!(b.next(), Some(2));
245 /// assert_eq!(b.next(), None);
246 ///
247 /// assert!(limit::get() < usize::MAX);
248 /// drop(b);
249 ///
250 /// assert_eq!(limit::get(), usize::MAX);
251 /// # Ok::<_, rune::alloc::Error>(())
252 /// ```
253 #[cfg(feature = "alloc")]
254 pub fn from_std(b: ::rust_alloc::boxed::Box<T>) -> Result<Self, Error> {
255 // SAFETY: We've ensured that standard allocations only happen in an
256 // allocator which is compatible with our `Global`.
257 unsafe {
258 // NB: Layout::for_value will return the size of the pointed to
259 // value by the box, which for unsized types is the size of the
260 // metadata. For sized types the value inside of the box.
261 Global.take(Layout::for_value(b.as_ref()))?;
262 let raw = ::rust_alloc::boxed::Box::into_raw(b);
263 Ok(Box::from_raw_in(raw, Global))
264 }
265 }
266}
267
268impl<T, A: Allocator> Box<T, A> {
269 /// Allocates memory in the given allocator then places `x` into it,
270 /// returning an error if the allocation fails
271 ///
272 /// This doesn't actually allocate if `T` is zero-sized.
273 ///
274 /// # Examples
275 ///
276 /// ```
277 /// use rune::alloc::Box;
278 /// use rune::alloc::alloc::Global;
279 ///
280 /// let five = Box::try_new_in(5, Global)?;
281 /// # Ok::<_, rune::alloc::Error>(())
282 /// ```
283 #[inline]
284 pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
285 let mut boxed = Self::try_new_uninit_in(alloc)?;
286
287 unsafe {
288 boxed.as_mut_ptr().write(x);
289 Ok(boxed.assume_init())
290 }
291 }
292
293 /// Constructs a new box with uninitialized contents in the provided
294 /// allocator, returning an error if the allocation fails
295 ///
296 /// # Examples
297 ///
298 /// ```
299 /// use rune::alloc::Box;
300 /// use rune::alloc::alloc::Global;
301 ///
302 /// let mut five = Box::<u32>::try_new_uninit_in(Global)?;
303 ///
304 /// let five: Box<u32> = unsafe {
305 /// // Deferred initialization:
306 /// five.as_mut_ptr().write(5);
307 ///
308 /// five.assume_init()
309 /// };
310 ///
311 /// assert_eq!(*five, 5);
312 /// # Ok::<_, rune::alloc::Error>(())
313 /// ```
314 pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
315 where
316 A: Allocator,
317 {
318 let layout = Layout::new::<mem::MaybeUninit<T>>();
319 let ptr = alloc.allocate(layout)?.cast();
320 unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
321 }
322
323 /// Converts a `Box<T>` into a `Box<[T]>`
324 ///
325 /// This conversion does not allocate on the heap and happens in place.
326 pub(crate) fn into_boxed_slice(boxed: Self) -> Box<[T], A> {
327 let (raw, alloc) = Box::into_raw_with_allocator(boxed);
328 unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) }
329 }
330
331 /// Consumes the `Box`, returning the wrapped value.
332 #[inline]
333 pub fn into_inner(boxed: Self) -> T {
334 let this = mem::ManuallyDrop::new(boxed);
335 let value = unsafe { ptr::read(this.ptr.as_ptr()) };
336
337 // Free memory associated with the box.
338 //
339 // SAFETY: We own the box, so we know we can safely deallocate it.
340 unsafe {
341 let layout = for_value_raw(this.ptr.as_ptr());
342
343 if layout.size() != 0 {
344 this.alloc.deallocate(From::from(this.ptr.cast()), layout);
345 }
346 }
347
348 value
349 }
350}
351
352impl<T: ?Sized, A: Allocator> Box<T, A> {
353 /// Consumes and leaks the `Box`, returning a mutable reference, `&'a mut
354 /// T`. Note that the type `T` must outlive the chosen lifetime `'a`. If the
355 /// type has only static references, or none at all, then this may be chosen
356 /// to be `'static`.
357 ///
358 /// This function is mainly useful for data that lives for the remainder of
359 /// the program's life. Dropping the returned reference will cause a memory
360 /// leak. If this is not acceptable, the reference should first be wrapped
361 /// with the [`Box::from_raw_in`] function producing a `Box`. This `Box` can
362 /// then be dropped which will properly destroy `T` and release the
363 /// allocated memory.
364 ///
365 /// Note: this is an associated function, which means that you have to call
366 /// it as `Box::leak(b)` instead of `b.leak()`. This is so that there is no
367 /// conflict with a method on the inner type.
368 ///
369 /// # Examples
370 ///
371 /// Simple usage:
372 ///
373 /// ```
374 /// # #[cfg(not(miri))]
375 /// # fn main() -> Result<(), rune::alloc::Error> {
376 /// use rune::alloc::Box;
377 ///
378 /// let x = Box::try_new(41)?;
379 /// let static_ref: &'static mut usize = Box::leak(x);
380 /// *static_ref += 1;
381 /// assert_eq!(*static_ref, 42);
382 /// # Ok(())
383 /// # }
384 /// # #[cfg(miri)] fn main() {}
385 /// ```
386 ///
387 /// Unsized data:
388 ///
389 /// ```
390 /// # #[cfg(not(miri))]
391 /// # fn main() -> Result<(), rune::alloc::Error> {
392 /// use rune::alloc::{try_vec, Box};
393 ///
394 /// let x = try_vec![1, 2, 3].try_into_boxed_slice()?;
395 /// let static_ref = Box::leak(x);
396 /// static_ref[0] = 4;
397 /// assert_eq!(*static_ref, [4, 2, 3]);
398 /// # Ok(())
399 /// # }
400 /// # #[cfg(miri)] fn main() {}
401 /// ```
402 #[inline]
403 pub fn leak<'a>(b: Self) -> &'a mut T
404 where
405 A: 'a,
406 {
407 unsafe { &mut *mem::ManuallyDrop::new(b).ptr.as_ptr() }
408 }
409
410 /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then
411 /// `*boxed` will be pinned in memory and unable to be moved.
412 ///
413 /// This conversion does not allocate on the heap and happens in place.
414 ///
415 /// This is also available via [`From`].
416 ///
417 /// Constructing and pinning a `Box` with <code>Box::into_pin([Box::try?new]\(x))</code>
418 /// can also be written more concisely using <code>[Box::try?pin]\(x)</code>.
419 /// This `into_pin` method is useful if you already have a `Box<T>`, or you are
420 /// constructing a (pinned) `Box` in a different way than with [`Box::try_new`].
421 ///
422 /// # Notes
423 ///
424 /// It's not recommended that crates add an impl like `From<Box<T>> for Pin<T>`,
425 /// as it'll introduce an ambiguity when calling `Pin::from`.
426 /// A demonstration of such a poor impl is shown below.
427 ///
428 /// ```compile_fail
429 /// # use core::pin::Pin;
430 /// use rune::alloc::Box;
431 ///
432 /// struct Foo; // A type defined in this crate.
433 /// impl From<Box<()>> for Pin<Foo> {
434 /// fn from(_: Box<()>) -> Pin<Foo> {
435 /// Pin::new(Foo)
436 /// }
437 /// }
438 ///
439 /// let foo = Box::try_new(())?;
440 /// let bar = Pin::from(foo);
441 /// # Ok::<_, rune::alloc::Error>(())
442 /// ```
443 pub fn into_pin(boxed: Self) -> Pin<Self>
444 where
445 A: 'static,
446 {
447 // It's not possible to move or replace the insides of a `Pin<Box<T>>`
448 // when `T: !Unpin`, so it's safe to pin it directly without any
449 // additional requirements.
450 unsafe { Pin::new_unchecked(boxed) }
451 }
452
453 /// Constructs a box from a raw pointer in the given allocator.
454 ///
455 /// After calling this function, the raw pointer is owned by the resulting
456 /// `Box`. Specifically, the `Box` destructor will call the destructor of
457 /// `T` and free the allocated memory. For this to be safe, the memory must
458 /// have been allocated in accordance with the [memory layout] used by `Box`
459 /// .
460 ///
461 /// # Safety
462 ///
463 /// This function is unsafe because improper use may lead to memory
464 /// problems. For example, a double-free may occur if the function is called
465 /// twice on the same raw pointer.
466 ///
467 /// # Examples
468 ///
469 /// Recreate a `Box` which was previously converted to a raw pointer using
470 /// [`Box::into_raw_with_allocator`]:
471 ///
472 /// ```
473 /// use rune::alloc::Box;
474 /// use rune::alloc::alloc::Global;
475 ///
476 /// let x = Box::try_new_in(5, Global)?;
477 /// let (ptr, alloc) = Box::into_raw_with_allocator(x);
478 /// let x = unsafe { Box::from_raw_in(ptr, alloc) };
479 /// # Ok::<_, rune::alloc::Error>(())
480 /// ```
481 ///
482 /// Manually create a `Box` from scratch by using the system allocator:
483 ///
484 /// ```
485 /// use core::alloc::Layout;
486 ///
487 /// use rune::alloc::Box;
488 /// use rune::alloc::alloc::{Allocator, Global};
489 ///
490 /// unsafe {
491 /// let ptr = Global.allocate(Layout::new::<i32>())?.as_ptr() as *mut i32;
492 /// // In general .write is required to avoid attempting to destruct
493 /// // the (uninitialized) previous contents of `ptr`, though for this
494 /// // simple example `*ptr = 5` would have worked as well.
495 /// ptr.write(5);
496 /// let x = Box::from_raw_in(ptr, Global);
497 /// }
498 /// # Ok::<_, rune::alloc::Error>(())
499 /// ```
500 ///
501 /// [memory layout]: self#memory-layout
502 /// [`Layout`]: crate::Layout
503 #[inline]
504 pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
505 Self {
506 ptr: unsafe { Unique::new_unchecked(raw) },
507 alloc,
508 }
509 }
510
511 /// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
512 ///
513 /// The pointer will be properly aligned and non-null.
514 ///
515 /// After calling this function, the caller is responsible for the
516 /// memory previously managed by the `Box`. In particular, the
517 /// caller should properly destroy `T` and release the memory, taking
518 /// into account the [memory layout] used by `Box`. The easiest way to
519 /// do this is to convert the raw pointer back into a `Box` with the
520 /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform
521 /// the cleanup.
522 ///
523 /// Note: this is an associated function, which means that you have
524 /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This
525 /// is so that there is no conflict with a method on the inner type.
526 ///
527 /// # Examples
528 ///
529 /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`]
530 /// for automatic cleanup:
531 ///
532 /// ```
533 /// use rune::alloc::{Box, String};
534 /// use rune::alloc::alloc::Global;
535 ///
536 /// let x = Box::try_new_in(String::try_from("Hello")?, Global)?;
537 /// let (ptr, alloc) = Box::into_raw_with_allocator(x);
538 /// let x = unsafe { Box::from_raw_in(ptr, alloc) };
539 /// # Ok::<_, rune::alloc::Error>(())
540 /// ```
541 ///
542 /// Manual cleanup by explicitly running the destructor and deallocating the
543 /// memory:
544 ///
545 /// ```
546 /// use core::alloc::Layout;
547 /// use core::ptr::{self, NonNull};
548 ///
549 /// use rune::alloc::{Box, String};
550 /// use rune::alloc::alloc::{Allocator, Global};
551 ///
552 /// let x = Box::try_new_in(String::try_from("Hello")?, Global)?;
553 ///
554 /// let (ptr, alloc) = Box::into_raw_with_allocator(x);
555 ///
556 /// unsafe {
557 /// ptr::drop_in_place(ptr);
558 /// let non_null = NonNull::new_unchecked(ptr);
559 /// alloc.deallocate(non_null.cast(), Layout::new::<String>());
560 /// }
561 /// # Ok::<_, rune::alloc::Error>(())
562 /// ```
563 ///
564 /// [memory layout]: self#memory-layout
565 #[inline]
566 pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
567 let leaked = mem::ManuallyDrop::new(b);
568 // SAFETY: We prevent the alloc field from being dropped, so we can
569 // safely smuggle it out.
570 let alloc = unsafe { ptr::read(&leaked.alloc) };
571 (leaked.ptr.as_ptr(), alloc)
572 }
573}
574
575impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
576 /// Converts to `Box<T, A>`.
577 ///
578 /// # Safety
579 ///
580 /// As with [`MaybeUninit::assume_init`],
581 /// it is up to the caller to guarantee that the value
582 /// really is in an initialized state.
583 /// Calling this when the content is not yet fully initialized
584 /// causes immediate undefined behavior.
585 ///
586 /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
587 ///
588 /// # Examples
589 ///
590 /// ```
591 /// use rune::alloc::Box;
592 /// use rune::alloc::alloc::Global;
593 ///
594 /// let mut five = Box::<u32>::try_new_uninit_in(Global)?;
595 ///
596 /// let five: Box<u32> = unsafe {
597 /// // Deferred initialization:
598 /// five.as_mut_ptr().write(5);
599 ///
600 /// five.assume_init()
601 /// };
602 ///
603 /// assert_eq!(*five, 5);
604 /// # Ok::<_, rune::alloc::Error>(())
605 /// ```
606 #[inline]
607 pub unsafe fn assume_init(self) -> Box<T, A> {
608 let (raw, alloc) = Box::into_raw_with_allocator(self);
609 unsafe { Box::from_raw_in(raw as *mut T, alloc) }
610 }
611}
612
613impl<T, A: Allocator> Box<[T], A> {
614 /// Constructs a new boxed slice with uninitialized contents. Returns an error if
615 /// the allocation fails
616 ///
617 /// # Examples
618 ///
619 /// ```
620 /// use rune::alloc::Box;
621 /// use rune::alloc::alloc::Global;
622 ///
623 /// let mut values = Box::<[u32]>::try_new_uninit_slice_in(3, Global)?;
624 ///
625 /// let values = unsafe {
626 /// // Deferred initialization:
627 /// values[0].as_mut_ptr().write(1);
628 /// values[1].as_mut_ptr().write(2);
629 /// values[2].as_mut_ptr().write(3);
630 /// values.assume_init()
631 /// };
632 ///
633 /// assert_eq!(*values, [1, 2, 3]);
634 /// # Ok::<_, rune::alloc::Error>(())
635 /// ```
636 #[inline]
637 pub fn try_new_uninit_slice_in(
638 len: usize,
639 alloc: A,
640 ) -> Result<Box<[mem::MaybeUninit<T>], A>, Error> {
641 unsafe {
642 let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
643 Ok(l) => l,
644 Err(_) => return Err(Error::LayoutError),
645 };
646 let ptr = alloc.allocate(layout)?;
647 Ok(RawVec::from_raw_parts_in(ptr.as_ptr() as *mut _, len, alloc).into_box(len))
648 }
649 }
650}
651
652impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {
653 /// Converts to `Box<[T], A>`.
654 ///
655 /// # Safety
656 ///
657 /// As with [`MaybeUninit::assume_init`],
658 /// it is up to the caller to guarantee that the values
659 /// really are in an initialized state.
660 /// Calling this when the content is not yet fully initialized
661 /// causes immediate undefined behavior.
662 ///
663 /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
664 ///
665 /// # Examples
666 ///
667 /// ```
668 /// use rune::alloc::Box;
669 /// use rune::alloc::alloc::Global;
670 ///
671 /// let mut values = Box::<[u32]>::try_new_uninit_slice_in(3, Global)?;
672 ///
673 /// let values = unsafe {
674 /// // Deferred initialization:
675 /// values[0].as_mut_ptr().write(1);
676 /// values[1].as_mut_ptr().write(2);
677 /// values[2].as_mut_ptr().write(3);
678 /// values.assume_init()
679 /// };
680 ///
681 /// assert_eq!(*values, [1, 2, 3]);
682 /// # Ok::<_, rune::alloc::Error>(())
683 /// ```
684 #[inline]
685 pub unsafe fn assume_init(self) -> Box<[T], A> {
686 let (raw, alloc) = Box::into_raw_with_allocator(self);
687 unsafe { Box::from_raw_in(raw as *mut [T], alloc) }
688 }
689}
690
691impl<T, A: Allocator + Clone> TryClone for Box<T, A>
692where
693 T: TryClone,
694{
695 #[inline]
696 fn try_clone(&self) -> Result<Self, Error> {
697 let value = (**self).try_clone()?;
698 let alloc = self.alloc.clone();
699 Ok(Box::try_new_in(value, alloc)?)
700 }
701}
702
703impl<T, A: Allocator + Clone> TryClone for Box<[T], A>
704where
705 T: TryClone,
706{
707 #[inline]
708 fn try_clone(&self) -> Result<Self, Error> {
709 let alloc = self.alloc.clone();
710 let vec = crate::slice::to_vec(self, alloc)?;
711 vec.try_into_boxed_slice()
712 }
713}
714
715impl<A: Allocator + Clone> TryClone for Box<str, A> {
716 #[inline]
717 fn try_clone(&self) -> Result<Self, Error> {
718 let alloc = self.alloc.clone();
719 Box::try_from_string_in(self.as_ref(), alloc)
720 }
721}
722
723impl<T: ?Sized, A: Allocator> Borrow<T> for Box<T, A> {
724 fn borrow(&self) -> &T {
725 self
726 }
727}
728
729impl<T: ?Sized, A: Allocator> BorrowMut<T> for Box<T, A> {
730 fn borrow_mut(&mut self) -> &mut T {
731 self
732 }
733}
734
735impl<T: ?Sized, A: Allocator> AsRef<T> for Box<T, A> {
736 fn as_ref(&self) -> &T {
737 self
738 }
739}
740
741impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
742 fn as_mut(&mut self) -> &mut T {
743 self
744 }
745}
746
747/* Nota bene
748 *
749 * We could have chosen not to add this impl, and instead have written a
750 * function of Pin<Box<T>> to Pin<T>. Such a function would not be sound,
751 * because Box<T> implements Unpin even when T does not, as a result of
752 * this impl.
753 *
754 * We chose this API instead of the alternative for a few reasons:
755 * - Logically, it is helpful to understand pinning in regard to the
756 * memory region being pointed to. For this reason none of the
757 * standard library pointer types support projecting through a pin
758 * (Box<T> is the only pointer type in std for which this would be
759 * safe.)
760 * - It is in practice very useful to have Box<T> be unconditionally
761 * Unpin because of trait objects, for which the structural auto
762 * trait functionality does not apply (e.g., Box<dyn Foo> would
763 * otherwise not be Unpin).
764 *
765 * Another type with the same semantics as Box but only a conditional
766 * implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and
767 * could have a method to project a Pin<T> from it.
768 */
769impl<T: ?Sized, A: Allocator> Unpin for Box<T, A> where A: 'static {}
770
771impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
772 type Target = T;
773
774 #[inline]
775 fn deref(&self) -> &T {
776 unsafe { self.ptr.as_ref() }
777 }
778}
779
780impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
781 #[inline]
782 fn deref_mut(&mut self) -> &mut T {
783 unsafe { self.ptr.as_mut() }
784 }
785}
786
787impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
788 #[inline]
789 fn drop(&mut self) {
790 unsafe {
791 let ptr = self.ptr;
792
793 if mem::needs_drop::<T>() {
794 ptr::drop_in_place(ptr.as_ptr());
795 }
796
797 let layout = for_value_raw(ptr.as_ptr());
798
799 if layout.size() != 0 {
800 self.alloc.deallocate(From::from(ptr.cast()), layout);
801 }
802 }
803 }
804}
805
806impl Default for Box<str, Global> {
807 fn default() -> Self {
808 // SAFETY: The layout of `Box<[u8]>` is the same as `Box<str>`.
809 unsafe {
810 let b = Box::<[u8]>::default();
811 let (ptr, alloc) = Box::into_raw_with_allocator(b);
812 Box::from_raw_in(ptr as *mut str, alloc)
813 }
814 }
815}
816
817impl<T> Default for Box<[T], Global> {
818 fn default() -> Self {
819 Box {
820 ptr: Unique::dangling_empty_slice(),
821 alloc: Global,
822 }
823 }
824}
825
826impl<T: ?Sized, A: Allocator> fmt::Display for Box<T, A>
827where
828 T: fmt::Display,
829{
830 #[inline]
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 (**self).fmt(f)
833 }
834}
835
836impl<T: ?Sized, A: Allocator> fmt::Debug for Box<T, A>
837where
838 T: fmt::Debug,
839{
840 #[inline]
841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
842 (**self).fmt(f)
843 }
844}
845
846impl<A: Allocator> From<Box<str, A>> for Box<[u8], A> {
847 fn from(value: Box<str, A>) -> Self {
848 // SAFETY: `[u8]` is layout compatible with `str` and there are no
849 // checks needed.
850 unsafe {
851 let (ptr, alloc) = Box::into_raw_with_allocator(value);
852 Box::from_raw_in(ptr as *mut [u8], alloc)
853 }
854 }
855}
856
857#[cfg(feature = "alloc")]
858impl<T> TryFrom<::rust_alloc::boxed::Box<[T]>> for Box<[T]> {
859 type Error = Error;
860
861 #[inline]
862 fn try_from(values: ::rust_alloc::boxed::Box<[T]>) -> Result<Self, Error> {
863 let mut vec = Vec::try_with_capacity(values.len())?;
864
865 for value in ::rust_alloc::vec::Vec::from(values) {
866 vec.try_push(value)?;
867 }
868
869 vec.try_into_boxed_slice()
870 }
871}
872
873impl<T, const N: usize> TryFrom<[T; N]> for Box<[T]> {
874 type Error = Error;
875
876 #[inline]
877 fn try_from(values: [T; N]) -> Result<Self, Error> {
878 let mut vec = Vec::try_with_capacity(values.len())?;
879
880 for value in values {
881 vec.try_push(value)?;
882 }
883
884 vec.try_into_boxed_slice()
885 }
886}
887
888impl<T, A: Allocator> TryFrom<Vec<T, A>> for Box<[T], A> {
889 type Error = Error;
890
891 #[inline]
892 fn try_from(vec: Vec<T, A>) -> Result<Self, Error> {
893 vec.try_into_boxed_slice()
894 }
895}
896
897impl<A: Allocator> Box<[u8], A> {
898 pub(crate) fn try_from_bytes_in(bytes: &[u8], alloc: A) -> Result<Self, Error> {
899 let mut vec = Vec::<u8, A>::try_with_capacity_in(bytes.len(), alloc)?;
900
901 unsafe {
902 ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr(), bytes.len());
903 vec.set_len(bytes.len());
904 vec.try_into_boxed_slice()
905 }
906 }
907}
908
909impl<A: Allocator> Box<str, A> {
910 pub(crate) fn try_from_string_in(string: &str, alloc: A) -> Result<Self, Error> {
911 unsafe {
912 let b = Box::try_from_bytes_in(string.as_bytes(), alloc)?;
913 let (raw, alloc) = Box::into_raw_with_allocator(b);
914 Ok(Box::from_raw_in(raw as *mut str, alloc))
915 }
916 }
917}
918
919impl<A: Allocator> Box<Path, A> {
920 pub(crate) fn try_from_path_in(path: &Path, alloc: A) -> Result<Self, Error> {
921 unsafe {
922 const _: () = assert!(mem::size_of::<&Path>() == mem::size_of::<&[u8]>());
923 // Replace with path.as_os_str().as_encoded_bytes() once that is
924 // stable.
925 let bytes = &*(path as *const _ as *const [u8]);
926 let b = Box::try_from_bytes_in(bytes, alloc)?;
927 let (raw, alloc) = Box::into_raw_with_allocator(b);
928 Ok(Box::from_raw_in(raw as *mut Path, alloc))
929 }
930 }
931}
932
933impl<A: Allocator + Clone> TryClone for Box<Path, A> {
934 #[inline]
935 fn try_clone(&self) -> Result<Self, Error> {
936 let alloc = self.alloc.clone();
937 Box::try_from_path_in(self.as_ref(), alloc)
938 }
939}
940
941impl TryFrom<&str> for Box<str> {
942 type Error = Error;
943
944 /// Converts a `&str` into a `Box<str>`.
945 ///
946 /// # Examples
947 ///
948 /// ```
949 /// use rune::alloc::Box;
950 ///
951 /// let s: Box<str> = Box::try_from("Hello World")?;
952 /// assert_eq!(s.as_ref(), "Hello World");
953 /// # Ok::<_, rune::alloc::Error>(())
954 /// ```
955 #[inline]
956 fn try_from(values: &str) -> Result<Self, Error> {
957 Box::try_from_string_in(values, Global)
958 }
959}
960
961#[cfg(feature = "alloc")]
962impl TryFrom<::rust_alloc::string::String> for Box<str> {
963 type Error = Error;
964
965 /// Converts a std `String` into a `Box<str>`.
966 ///
967 /// # Examples
968 ///
969 /// ```
970 /// use rune::alloc::Box;
971 ///
972 /// let s = String::from("Hello World");
973 /// let s: Box<str> = Box::try_from(s)?;
974 /// assert_eq!(s.as_ref(), "Hello World");
975 /// # Ok::<_, rune::alloc::Error>(())
976 /// ```
977 #[inline]
978 fn try_from(string: ::rust_alloc::string::String) -> Result<Self, Error> {
979 Box::from_std(string.into_boxed_str())
980 }
981}
982
983impl TryFrom<&[u8]> for Box<[u8]> {
984 type Error = Error;
985
986 /// Converts a `&[u8]` into a `Box<[u8]>`.
987 ///
988 /// # Examples
989 ///
990 /// ```
991 /// use rune::alloc::Box;
992 ///
993 /// let s: Box<[u8]> = Box::try_from(&b"Hello World"[..])?;
994 /// assert_eq!(s.as_ref(), b"Hello World");
995 /// # Ok::<_, rune::alloc::Error>(())
996 /// ```
997 #[inline]
998 fn try_from(values: &[u8]) -> Result<Self, Error> {
999 Box::try_from_bytes_in(values, Global)
1000 }
1001}
1002
1003impl TryFrom<&Path> for Box<Path> {
1004 type Error = Error;
1005
1006 /// Converts a `&[u8]` into a `Box<[u8]>`.
1007 ///
1008 /// # Examples
1009 ///
1010 /// ```
1011 /// use std::path::Path;
1012 /// use rune::alloc::Box;
1013 ///
1014 /// let path = Path::new("foo/bar");
1015 ///
1016 /// let s: Box<Path> = Box::try_from(path)?;
1017 /// assert_eq!(s.as_ref(), Path::new("foo/bar"));
1018 /// # Ok::<_, rune::alloc::Error>(())
1019 /// ```
1020 #[inline]
1021 fn try_from(path: &Path) -> Result<Self, Error> {
1022 Box::try_from_path_in(path, Global)
1023 }
1024}
1025
1026impl<T, A: Allocator> TryFromIteratorIn<T, A> for Box<[T], A> {
1027 fn try_from_iter_in<I>(iter: I, alloc: A) -> Result<Self, Error>
1028 where
1029 I: IntoIterator<Item = T>,
1030 {
1031 Vec::<T, A>::try_from_iter_in(iter, alloc)?.try_into_boxed_slice()
1032 }
1033}
1034
1035unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Layout {
1036 // SAFETY: we pass along the prerequisites of these functions to the caller
1037 // TODO: Use mem::{size_of_val_raw, align_of_val_raw} when they become
1038 // stable, for now we privately know that this can safely be turned into a
1039 // reference since it's only used while dropping an owned value of type `T`.
1040 let (size, align) = (mem::size_of_val(&*t), mem::align_of_val(&*t));
1041 // SAFETY: see rationale in `new` for why this is using the unsafe variant
1042 Layout::from_size_align_unchecked(size, align)
1043}
1044
1045impl<T: ?Sized, A: Allocator> Hash for Box<T, A>
1046where
1047 T: Hash,
1048{
1049 #[inline]
1050 fn hash<H: Hasher>(&self, state: &mut H) {
1051 (**self).hash(state);
1052 }
1053}
1054
1055impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Pin<Box<T, A>>
1056where
1057 A: 'static,
1058{
1059 /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement
1060 /// [`Unpin`], then `*boxed` will be pinned in memory and unable to be
1061 /// moved.
1062 ///
1063 /// This conversion does not allocate on the heap and happens in place.
1064 ///
1065 /// This is also available via [`Box::into_pin`].
1066 ///
1067 /// Constructing and pinning a `Box` with
1068 /// <code><Pin<Box\<T>>>::from([Box::try?new]\(x))</code> can also be
1069 /// written more concisely using <code>[Box::try?pin]\(x)</code>. This
1070 /// `From` implementation is useful if you already have a `Box<T>`, or you
1071 /// are constructing a (pinned) `Box` in a different way than with
1072 /// [`Box::try_new`].
1073 fn from(boxed: Box<T, A>) -> Self {
1074 Box::into_pin(boxed)
1075 }
1076}
1077
1078impl<T: ?Sized, A: Allocator> PartialEq for Box<T, A>
1079where
1080 T: PartialEq,
1081{
1082 #[inline]
1083 fn eq(&self, other: &Self) -> bool {
1084 (**self).eq(other)
1085 }
1086}
1087
1088impl<T: ?Sized, A: Allocator> Eq for Box<T, A> where T: Eq {}
1089
1090impl<T: ?Sized, A: Allocator> PartialOrd for Box<T, A>
1091where
1092 T: PartialOrd,
1093{
1094 #[inline]
1095 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1096 (**self).partial_cmp(other)
1097 }
1098}
1099
1100impl<T: ?Sized, A: Allocator> Ord for Box<T, A>
1101where
1102 T: Ord,
1103{
1104 #[inline]
1105 fn cmp(&self, other: &Self) -> Ordering {
1106 (**self).cmp(other)
1107 }
1108}