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;
166use core::ptr;
167
168#[cfg(feature = "std")]
169use std::path::Path;
170
171use crate::alloc::{AllocError, Allocator, Global};
172use crate::clone::TryClone;
173use crate::error::Error;
174use crate::iter::TryFromIteratorIn;
175use crate::ptr::Unique;
176use crate::raw_vec::RawVec;
177use crate::vec::Vec;
178
179#[test]
180fn ensure_niche_size() {
181    assert_eq!(
182        core::mem::size_of::<Option<Box<u32>>>(),
183        core::mem::size_of::<Box<u32>>()
184    );
185}
186
187/// A pointer type that uniquely owns a heap allocation of type `T`.
188pub struct Box<T, A = Global>
189where
190    T: ?Sized,
191    A: Allocator,
192{
193    ptr: Unique<T>,
194    alloc: A,
195}
196
197impl<T> Box<T, Global> {
198    /// Allocates memory on the heap and then places `x` into it.
199    ///
200    /// This doesn't actually allocate if `T` is zero-sized.
201    ///
202    /// # Examples
203    ///
204    /// ```
205    /// use rune::alloc::Box;
206    ///
207    /// let five = Box::try_new(5)?;
208    /// # Ok::<_, rune::alloc::Error>(())
209    /// ```
210    pub fn try_new(value: T) -> Result<Self, AllocError> {
211        Self::try_new_in(value, Global)
212    }
213
214    /// Constructs a new `Pin<Box<T>>`. If `T` does not implement [`Unpin`],
215    /// then `x` will be pinned in memory and unable to be moved.
216    ///
217    /// Constructing and pinning of the `Box` can also be done in two steps:
218    /// `Box::try?pin(x)` does the same as
219    /// <code>[Box::into_pin]\([Box::try?new]\(x))</code>. Consider using
220    /// [`into_pin`](Box::into_pin) if you already have a `Box<T>`, or if you
221    /// want to construct a (pinned) `Box` in a different way than with
222    /// [`Box::try_new`].
223    #[inline(always)]
224    pub fn try_pin(x: T) -> Result<Pin<Box<T>>, AllocError> {
225        Ok(Box::try_new(x)?.into())
226    }
227}
228
229impl<T: ?Sized> Box<T> {
230    /// Convert from a std `Box`.
231    ///
232    /// This causes the underlying allocation to be accounted for by the
233    /// [`Global`] allocator.
234    ///
235    /// A caveat of this method is that the allocation is already in use, but
236    /// this might still be necessary because we want access to certain methods
237    /// in std `Box` such as the ability to coerce to unsized values.
238    ///
239    /// # Examples
240    ///
241    /// ```
242    /// use rune::alloc::{Box, Vec};
243    /// use rune::alloc::limit;
244    /// use std::boxed::Box as StdBox;
245    ///
246    /// assert_eq!(limit::get(), usize::MAX);
247    ///
248    /// let b: StdBox<dyn Iterator<Item = u32>> = StdBox::new(1..3);
249    /// let mut b = Box::from_std(b)?;
250    /// assert_eq!(b.next(), Some(1));
251    /// assert_eq!(b.next(), Some(2));
252    /// assert_eq!(b.next(), None);
253    ///
254    /// assert!(limit::get() < usize::MAX);
255    /// drop(b);
256    ///
257    /// assert_eq!(limit::get(), usize::MAX);
258    /// # Ok::<_, rune::alloc::Error>(())
259    /// ```
260    #[cfg(feature = "alloc")]
261    pub fn from_std(b: rust_alloc::boxed::Box<T>) -> Result<Self, Error> {
262        // SAFETY: We've ensured that standard allocations only happen in an
263        // allocator which is compatible with our `Global`.
264        unsafe {
265            // NB: Layout::for_value will return the size of the pointed to
266            // value by the box, which for unsized types is the size of the
267            // metadata. For sized types the value inside of the box.
268            Global.take(Layout::for_value(b.as_ref()))?;
269            let raw = rust_alloc::boxed::Box::into_raw(b);
270            Ok(Box::from_raw_in(raw, Global))
271        }
272    }
273}
274
275impl<T, A> Box<T, A>
276where
277    A: Allocator,
278{
279    /// Allocates memory in the given allocator then places `x` into it,
280    /// returning an error if the allocation fails
281    ///
282    /// This doesn't actually allocate if `T` is zero-sized.
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// use rune::alloc::Box;
288    /// use rune::alloc::alloc::Global;
289    ///
290    /// let five = Box::try_new_in(5, Global)?;
291    /// # Ok::<_, rune::alloc::Error>(())
292    /// ```
293    #[inline]
294    pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
295        let mut boxed = Self::try_new_uninit_in(alloc)?;
296
297        unsafe {
298            boxed.as_mut_ptr().write(x);
299            Ok(boxed.assume_init())
300        }
301    }
302
303    /// Constructs a new box with uninitialized contents in the provided
304    /// allocator, returning an error if the allocation fails
305    ///
306    /// # Examples
307    ///
308    /// ```
309    /// use rune::alloc::Box;
310    /// use rune::alloc::alloc::Global;
311    ///
312    /// let mut five = Box::<u32>::try_new_uninit_in(Global)?;
313    ///
314    /// let five: Box<u32> = unsafe {
315    ///     // Deferred initialization:
316    ///     five.as_mut_ptr().write(5);
317    ///
318    ///     five.assume_init()
319    /// };
320    ///
321    /// assert_eq!(*five, 5);
322    /// # Ok::<_, rune::alloc::Error>(())
323    /// ```
324    pub fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> {
325        let layout = Layout::new::<mem::MaybeUninit<T>>();
326        let ptr = alloc.allocate(layout)?.cast();
327        unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) }
328    }
329
330    /// Consumes the `Box`, returning the wrapped value.
331    #[inline]
332    pub fn into_inner(boxed: Self) -> T {
333        let this = mem::ManuallyDrop::new(boxed);
334        let value = unsafe { ptr::read(this.ptr.as_ptr()) };
335
336        // Free memory associated with the box.
337        //
338        // SAFETY: We own the box, so we know we can safely deallocate it.
339        unsafe {
340            let layout = for_value_raw(this.ptr.as_ptr());
341
342            if layout.size() != 0 {
343                this.alloc.deallocate(From::from(this.ptr.cast()), layout);
344            }
345        }
346
347        value
348    }
349}
350
351impl<T, A> Box<T, A>
352where
353    T: ?Sized,
354    A: Allocator,
355{
356    /// Consumes and leaks the `Box`, returning a mutable reference, `&'a mut
357    /// T`. Note that the type `T` must outlive the chosen lifetime `'a`. If the
358    /// type has only static references, or none at all, then this may be chosen
359    /// to be `'static`.
360    ///
361    /// This function is mainly useful for data that lives for the remainder of
362    /// the program's life. Dropping the returned reference will cause a memory
363    /// leak. If this is not acceptable, the reference should first be wrapped
364    /// with the [`Box::from_raw_in`] function producing a `Box`. This `Box` can
365    /// then be dropped which will properly destroy `T` and release the
366    /// allocated memory.
367    ///
368    /// Note: this is an associated function, which means that you have to call
369    /// it as `Box::leak(b)` instead of `b.leak()`. This is so that there is no
370    /// conflict with a method on the inner type.
371    ///
372    /// # Examples
373    ///
374    /// Simple usage:
375    ///
376    /// ```
377    /// # #[cfg(not(miri))]
378    /// # fn main() -> Result<(), rune::alloc::Error> {
379    /// use rune::alloc::Box;
380    ///
381    /// let x = Box::try_new(41)?;
382    /// let static_ref: &'static mut usize = Box::leak(x);
383    /// *static_ref += 1;
384    /// assert_eq!(*static_ref, 42);
385    /// # Ok(())
386    /// # }
387    /// # #[cfg(miri)] fn main() {}
388    /// ```
389    ///
390    /// Unsized data:
391    ///
392    /// ```
393    /// # #[cfg(not(miri))]
394    /// # fn main() -> Result<(), rune::alloc::Error> {
395    /// use rune::alloc::{try_vec, Box};
396    ///
397    /// let x = try_vec![1, 2, 3].try_into_boxed_slice()?;
398    /// let static_ref = Box::leak(x);
399    /// static_ref[0] = 4;
400    /// assert_eq!(*static_ref, [4, 2, 3]);
401    /// # Ok(())
402    /// # }
403    /// # #[cfg(miri)] fn main() {}
404    /// ```
405    #[inline]
406    pub fn leak<'a>(b: Self) -> &'a mut T
407    where
408        A: 'a,
409    {
410        unsafe { &mut *mem::ManuallyDrop::new(b).ptr.as_ptr() }
411    }
412
413    /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then
414    /// `*boxed` will be pinned in memory and unable to be moved.
415    ///
416    /// This conversion does not allocate on the heap and happens in place.
417    ///
418    /// This is also available via [`From`].
419    ///
420    /// Constructing and pinning a `Box` with <code>Box::into_pin([Box::try?new]\(x))</code>
421    /// can also be written more concisely using <code>[Box::try?pin]\(x)</code>.
422    /// This `into_pin` method is useful if you already have a `Box<T>`, or you are
423    /// constructing a (pinned) `Box` in a different way than with [`Box::try_new`].
424    ///
425    /// # Notes
426    ///
427    /// It's not recommended that crates add an impl like `From<Box<T>> for Pin<T>`,
428    /// as it'll introduce an ambiguity when calling `Pin::from`.
429    /// A demonstration of such a poor impl is shown below.
430    ///
431    /// ```compile_fail
432    /// # use core::pin::Pin;
433    /// use rune::alloc::Box;
434    ///
435    /// struct Foo; // A type defined in this crate.
436    /// impl From<Box<()>> for Pin<Foo> {
437    ///     fn from(_: Box<()>) -> Pin<Foo> {
438    ///         Pin::new(Foo)
439    ///     }
440    /// }
441    ///
442    /// let foo = Box::try_new(())?;
443    /// let bar = Pin::from(foo);
444    /// # Ok::<_, rune::alloc::Error>(())
445    /// ```
446    pub fn into_pin(boxed: Self) -> Pin<Self>
447    where
448        A: 'static,
449    {
450        // It's not possible to move or replace the insides of a `Pin<Box<T>>`
451        // when `T: !Unpin`, so it's safe to pin it directly without any
452        // additional requirements.
453        unsafe { Pin::new_unchecked(boxed) }
454    }
455
456    /// Constructs a box from a raw pointer in the given allocator.
457    ///
458    /// After calling this function, the raw pointer is owned by the resulting
459    /// `Box`. Specifically, the `Box` destructor will call the destructor of
460    /// `T` and free the allocated memory. For this to be safe, the memory must
461    /// have been allocated in accordance with the [memory layout] used by `Box`
462    /// .
463    ///
464    /// # Safety
465    ///
466    /// This function is unsafe because improper use may lead to memory
467    /// problems. For example, a double-free may occur if the function is called
468    /// twice on the same raw pointer.
469    ///
470    /// # Examples
471    ///
472    /// Recreate a `Box` which was previously converted to a raw pointer using
473    /// [`Box::into_raw_with_allocator`]:
474    ///
475    /// ```
476    /// use rune::alloc::Box;
477    /// use rune::alloc::alloc::Global;
478    ///
479    /// let x = Box::try_new_in(5, Global)?;
480    /// let (ptr, alloc) = Box::into_raw_with_allocator(x);
481    /// let x = unsafe { Box::from_raw_in(ptr, alloc) };
482    /// # Ok::<_, rune::alloc::Error>(())
483    /// ```
484    ///
485    /// Manually create a `Box` from scratch by using the system allocator:
486    ///
487    /// ```
488    /// use core::alloc::Layout;
489    ///
490    /// use rune::alloc::Box;
491    /// use rune::alloc::alloc::{Allocator, Global};
492    ///
493    /// unsafe {
494    ///     let ptr = Global.allocate(Layout::new::<i32>())?.as_ptr() as *mut i32;
495    ///     // In general .write is required to avoid attempting to destruct
496    ///     // the (uninitialized) previous contents of `ptr`, though for this
497    ///     // simple example `*ptr = 5` would have worked as well.
498    ///     ptr.write(5);
499    ///     let x = Box::from_raw_in(ptr, Global);
500    /// }
501    /// # Ok::<_, rune::alloc::Error>(())
502    /// ```
503    ///
504    /// [memory layout]: self#memory-layout
505    /// [`Layout`]: core::alloc::Layout
506    #[inline]
507    pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
508        Self {
509            ptr: unsafe { Unique::new_unchecked(raw) },
510            alloc,
511        }
512    }
513
514    /// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
515    ///
516    /// The pointer will be properly aligned and non-null.
517    ///
518    /// After calling this function, the caller is responsible for the
519    /// memory previously managed by the `Box`. In particular, the
520    /// caller should properly destroy `T` and release the memory, taking
521    /// into account the [memory layout] used by `Box`. The easiest way to
522    /// do this is to convert the raw pointer back into a `Box` with the
523    /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform
524    /// the cleanup.
525    ///
526    /// Note: this is an associated function, which means that you have
527    /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This
528    /// is so that there is no conflict with a method on the inner type.
529    ///
530    /// # Examples
531    ///
532    /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`]
533    /// for automatic cleanup:
534    ///
535    /// ```
536    /// use rune::alloc::{Box, String};
537    /// use rune::alloc::alloc::Global;
538    ///
539    /// let x = Box::try_new_in(String::try_from("Hello")?, Global)?;
540    /// let (ptr, alloc) = Box::into_raw_with_allocator(x);
541    /// let x = unsafe { Box::from_raw_in(ptr, alloc) };
542    /// # Ok::<_, rune::alloc::Error>(())
543    /// ```
544    ///
545    /// Manual cleanup by explicitly running the destructor and deallocating the
546    /// memory:
547    ///
548    /// ```
549    /// use core::alloc::Layout;
550    /// use core::ptr::{self, NonNull};
551    ///
552    /// use rune::alloc::{Box, String};
553    /// use rune::alloc::alloc::{Allocator, Global};
554    ///
555    /// let x = Box::try_new_in(String::try_from("Hello")?, Global)?;
556    ///
557    /// let (ptr, alloc) = Box::into_raw_with_allocator(x);
558    ///
559    /// unsafe {
560    ///     ptr::drop_in_place(ptr);
561    ///     let non_null = NonNull::new_unchecked(ptr);
562    ///     alloc.deallocate(non_null.cast(), Layout::new::<String>());
563    /// }
564    /// # Ok::<_, rune::alloc::Error>(())
565    /// ```
566    ///
567    /// [memory layout]: self#memory-layout
568    #[inline]
569    pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
570        let leaked = mem::ManuallyDrop::new(b);
571        // SAFETY: We prevent the alloc field from being dropped, so we can
572        // safely smuggle it out.
573        let alloc = unsafe { ptr::read(&leaked.alloc) };
574        (leaked.ptr.as_ptr(), alloc)
575    }
576
577    #[inline]
578    pub(crate) fn into_unique_with_allocator(b: Self) -> (Unique<T>, A) {
579        let (ptr, alloc) = Box::into_raw_with_allocator(b);
580        unsafe { (Unique::from(&mut *ptr), alloc) }
581    }
582}
583
584impl<T, A> Box<mem::MaybeUninit<T>, A>
585where
586    A: Allocator,
587{
588    /// Converts to `Box<T, A>`.
589    ///
590    /// # Safety
591    ///
592    /// As with [`MaybeUninit::assume_init`],
593    /// it is up to the caller to guarantee that the value
594    /// really is in an initialized state.
595    /// Calling this when the content is not yet fully initialized
596    /// causes immediate undefined behavior.
597    ///
598    /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
599    ///
600    /// # Examples
601    ///
602    /// ```
603    /// use rune::alloc::Box;
604    /// use rune::alloc::alloc::Global;
605    ///
606    /// let mut five = Box::<u32>::try_new_uninit_in(Global)?;
607    ///
608    /// let five: Box<u32> = unsafe {
609    ///     // Deferred initialization:
610    ///     five.as_mut_ptr().write(5);
611    ///
612    ///     five.assume_init()
613    /// };
614    ///
615    /// assert_eq!(*five, 5);
616    /// # Ok::<_, rune::alloc::Error>(())
617    /// ```
618    #[inline]
619    pub unsafe fn assume_init(self) -> Box<T, A> {
620        let (raw, alloc) = Box::into_raw_with_allocator(self);
621        unsafe { Box::from_raw_in(raw as *mut T, alloc) }
622    }
623}
624
625impl<T, A> Box<[T], A>
626where
627    A: Allocator,
628{
629    /// Constructs a new boxed slice with uninitialized contents. Returns an error if
630    /// the allocation fails
631    ///
632    /// # Examples
633    ///
634    /// ```
635    /// use rune::alloc::Box;
636    /// use rune::alloc::alloc::Global;
637    ///
638    /// let mut values = Box::<[u32]>::try_new_uninit_slice_in(3, Global)?;
639    ///
640    /// let values = unsafe {
641    ///     // Deferred initialization:
642    ///     values[0].as_mut_ptr().write(1);
643    ///     values[1].as_mut_ptr().write(2);
644    ///     values[2].as_mut_ptr().write(3);
645    ///     values.assume_init()
646    /// };
647    ///
648    /// assert_eq!(*values, [1, 2, 3]);
649    /// # Ok::<_, rune::alloc::Error>(())
650    /// ```
651    #[inline]
652    pub fn try_new_uninit_slice_in(
653        len: usize,
654        alloc: A,
655    ) -> Result<Box<[mem::MaybeUninit<T>], A>, Error> {
656        unsafe {
657            let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
658                Ok(l) => l,
659                Err(_) => return Err(Error::LayoutError),
660            };
661            let ptr = alloc.allocate(layout)?;
662            Ok(RawVec::from_raw_parts_in(ptr.as_ptr() as *mut _, len, alloc).into_box(len))
663        }
664    }
665}
666
667impl<T, A> Box<[mem::MaybeUninit<T>], A>
668where
669    A: Allocator,
670{
671    /// Converts to `Box<[T], A>`.
672    ///
673    /// # Safety
674    ///
675    /// As with [`MaybeUninit::assume_init`],
676    /// it is up to the caller to guarantee that the values
677    /// really are in an initialized state.
678    /// Calling this when the content is not yet fully initialized
679    /// causes immediate undefined behavior.
680    ///
681    /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
682    ///
683    /// # Examples
684    ///
685    /// ```
686    /// use rune::alloc::Box;
687    /// use rune::alloc::alloc::Global;
688    ///
689    /// let mut values = Box::<[u32]>::try_new_uninit_slice_in(3, Global)?;
690    ///
691    /// let values = unsafe {
692    ///     // Deferred initialization:
693    ///     values[0].as_mut_ptr().write(1);
694    ///     values[1].as_mut_ptr().write(2);
695    ///     values[2].as_mut_ptr().write(3);
696    ///     values.assume_init()
697    /// };
698    ///
699    /// assert_eq!(*values, [1, 2, 3]);
700    /// # Ok::<_, rune::alloc::Error>(())
701    /// ```
702    #[inline]
703    pub unsafe fn assume_init(self) -> Box<[T], A> {
704        let (raw, alloc) = Box::into_raw_with_allocator(self);
705        unsafe { Box::from_raw_in(raw as *mut [T], alloc) }
706    }
707}
708
709impl<T, A> TryClone for Box<T, A>
710where
711    T: TryClone,
712    A: Allocator + Clone,
713{
714    #[inline]
715    fn try_clone(&self) -> Result<Self, Error> {
716        let value = (**self).try_clone()?;
717        let alloc = self.alloc.clone();
718        Ok(Box::try_new_in(value, alloc)?)
719    }
720}
721
722impl<T, A> TryClone for Box<[T], A>
723where
724    T: TryClone,
725    A: Allocator + Clone,
726{
727    #[inline]
728    fn try_clone(&self) -> Result<Self, Error> {
729        let alloc = self.alloc.clone();
730        let vec = crate::slice::to_vec(self, alloc)?;
731        vec.try_into_boxed_slice()
732    }
733}
734
735impl<A> TryClone for Box<str, A>
736where
737    A: Allocator + Clone,
738{
739    #[inline]
740    fn try_clone(&self) -> Result<Self, Error> {
741        let alloc = self.alloc.clone();
742        Box::try_from_string_in(self.as_ref(), alloc)
743    }
744}
745
746impl<T, A> Borrow<T> for Box<T, A>
747where
748    T: ?Sized,
749    A: Allocator,
750{
751    #[inline]
752    fn borrow(&self) -> &T {
753        self
754    }
755}
756
757impl<T, A> BorrowMut<T> for Box<T, A>
758where
759    T: ?Sized,
760    A: Allocator,
761{
762    #[inline]
763    fn borrow_mut(&mut self) -> &mut T {
764        self
765    }
766}
767
768impl<T, A> AsRef<T> for Box<T, A>
769where
770    T: ?Sized,
771    A: Allocator,
772{
773    #[inline]
774    fn as_ref(&self) -> &T {
775        self
776    }
777}
778
779impl<T, A> AsMut<T> for Box<T, A>
780where
781    T: ?Sized,
782    A: Allocator,
783{
784    #[inline]
785    fn as_mut(&mut self) -> &mut T {
786        self
787    }
788}
789
790/* Nota bene
791 *
792 *  We could have chosen not to add this impl, and instead have written a
793 *  function of Pin<Box<T>> to Pin<T>. Such a function would not be sound,
794 *  because Box<T> implements Unpin even when T does not, as a result of
795 *  this impl.
796 *
797 *  We chose this API instead of the alternative for a few reasons:
798 *      - Logically, it is helpful to understand pinning in regard to the
799 *        memory region being pointed to. For this reason none of the
800 *        standard library pointer types support projecting through a pin
801 *        (Box<T> is the only pointer type in std for which this would be
802 *        safe.)
803 *      - It is in practice very useful to have Box<T> be unconditionally
804 *        Unpin because of trait objects, for which the structural auto
805 *        trait functionality does not apply (e.g., Box<dyn Foo> would
806 *        otherwise not be Unpin).
807 *
808 *  Another type with the same semantics as Box but only a conditional
809 *  implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and
810 *  could have a method to project a Pin<T> from it.
811 */
812impl<T, A> Unpin for Box<T, A>
813where
814    A: 'static,
815    T: ?Sized,
816    A: Allocator,
817{
818}
819
820impl<T, A> Deref for Box<T, A>
821where
822    T: ?Sized,
823    A: Allocator,
824{
825    type Target = T;
826
827    #[inline]
828    fn deref(&self) -> &T {
829        unsafe { self.ptr.as_ref() }
830    }
831}
832
833impl<T, A> DerefMut for Box<T, A>
834where
835    T: ?Sized,
836    A: Allocator,
837{
838    #[inline]
839    fn deref_mut(&mut self) -> &mut T {
840        unsafe { self.ptr.as_mut() }
841    }
842}
843
844impl<T, A> Drop for Box<T, A>
845where
846    T: ?Sized,
847    A: Allocator,
848{
849    #[inline]
850    fn drop(&mut self) {
851        unsafe {
852            let ptr = self.ptr;
853
854            if mem::needs_drop::<T>() {
855                ptr::drop_in_place(ptr.as_ptr());
856            }
857
858            let layout = for_value_raw(ptr.as_ptr());
859
860            if layout.size() != 0 {
861                self.alloc.deallocate(From::from(ptr.cast()), layout);
862            }
863        }
864    }
865}
866
867impl Default for Box<str, Global> {
868    #[inline]
869    fn default() -> Self {
870        // SAFETY: The layout of `Box<[u8]>` is the same as `Box<str>`.
871        unsafe {
872            let b = Box::<[u8]>::default();
873            let (ptr, alloc) = Box::into_raw_with_allocator(b);
874            Box::from_raw_in(ptr as *mut str, alloc)
875        }
876    }
877}
878
879impl<T> Default for Box<[T], Global> {
880    #[inline]
881    fn default() -> Self {
882        Box {
883            ptr: Unique::dangling_empty_slice(),
884            alloc: Global,
885        }
886    }
887}
888
889impl<T, A> fmt::Display for Box<T, A>
890where
891    T: ?Sized + fmt::Display,
892    A: Allocator,
893{
894    #[inline]
895    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
896        (**self).fmt(f)
897    }
898}
899
900impl<T, A> fmt::Debug for Box<T, A>
901where
902    T: ?Sized + fmt::Debug,
903    A: Allocator,
904{
905    #[inline]
906    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
907        (**self).fmt(f)
908    }
909}
910
911impl<A> From<Box<str, A>> for Box<[u8], A>
912where
913    A: Allocator,
914{
915    fn from(value: Box<str, A>) -> Self {
916        // SAFETY: `[u8]` is layout compatible with `str` and there are no
917        // checks needed.
918        unsafe {
919            let (ptr, alloc) = Box::into_raw_with_allocator(value);
920            Box::from_raw_in(ptr as *mut [u8], alloc)
921        }
922    }
923}
924
925impl<T, const N: usize> TryFrom<[T; N]> for Box<[T]> {
926    type Error = Error;
927
928    #[inline]
929    fn try_from(values: [T; N]) -> Result<Self, Self::Error> {
930        let mut vec = Vec::try_with_capacity(values.len())?;
931
932        for value in values {
933            vec.try_push(value)?;
934        }
935
936        vec.try_into_boxed_slice()
937    }
938}
939
940/// Casts a boxed slice to a boxed array.
941///
942/// # Safety
943///
944/// `boxed_slice.len()` must be exactly `N`.
945unsafe fn boxed_slice_as_array_unchecked<T, A, const N: usize>(
946    boxed_slice: Box<[T], A>,
947) -> Box<[T; N], A>
948where
949    A: Allocator,
950{
951    debug_assert_eq!(boxed_slice.len(), N);
952
953    let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice);
954    // SAFETY: Pointer and allocator came from an existing box,
955    // and our safety condition requires that the length is exactly `N`
956    unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) }
957}
958
959impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
960    type Error = Box<[T]>;
961
962    /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`.
963    ///
964    /// The conversion occurs in-place and does not require a
965    /// new memory allocation.
966    ///
967    /// # Errors
968    ///
969    /// Returns the old `Box<[T]>` in the `Err` variant if
970    /// `boxed_slice.len()` does not equal `N`.
971    fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
972        if boxed_slice.len() == N {
973            Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
974        } else {
975            Err(boxed_slice)
976        }
977    }
978}
979
980impl<T, A> TryFrom<Vec<T, A>> for Box<[T], A>
981where
982    A: Allocator,
983{
984    type Error = Error;
985
986    #[inline]
987    fn try_from(vec: Vec<T, A>) -> Result<Self, Error> {
988        vec.try_into_boxed_slice()
989    }
990}
991
992impl<A> Box<[u8], A>
993where
994    A: Allocator,
995{
996    #[inline]
997    pub(crate) fn try_from_bytes_in(bytes: &[u8], alloc: A) -> Result<Self, Error> {
998        let mut vec = Vec::<u8, A>::try_with_capacity_in(bytes.len(), alloc)?;
999
1000        unsafe {
1001            ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr(), bytes.len());
1002            vec.set_len(bytes.len());
1003            vec.try_into_boxed_slice()
1004        }
1005    }
1006}
1007
1008impl<A> Box<str, A>
1009where
1010    A: Allocator,
1011{
1012    #[inline]
1013    pub(crate) fn try_from_string_in(string: &str, alloc: A) -> Result<Self, Error> {
1014        unsafe {
1015            let b = Box::try_from_bytes_in(string.as_bytes(), alloc)?;
1016            let (raw, alloc) = Box::into_raw_with_allocator(b);
1017            Ok(Box::from_raw_in(raw as *mut str, alloc))
1018        }
1019    }
1020}
1021
1022#[cfg(feature = "std")]
1023#[cfg_attr(rune_docsrs, doc(cfg(feature = "std")))]
1024impl<A> Box<Path, A>
1025where
1026    A: Allocator,
1027{
1028    #[inline]
1029    pub(crate) fn try_from_path_in(path: &Path, alloc: A) -> Result<Self, Error> {
1030        unsafe {
1031            let bytes = path.as_os_str().as_encoded_bytes();
1032            let b = Box::try_from_bytes_in(bytes, alloc)?;
1033            let (raw, alloc) = Box::into_raw_with_allocator(b);
1034            Ok(Box::from_raw_in(raw as *mut Path, alloc))
1035        }
1036    }
1037}
1038
1039#[cfg(feature = "std")]
1040#[cfg_attr(rune_docsrs, doc(cfg(feature = "std")))]
1041impl<A> TryClone for Box<Path, A>
1042where
1043    A: Allocator + Clone,
1044{
1045    #[inline]
1046    fn try_clone(&self) -> Result<Self, Error> {
1047        let alloc = self.alloc.clone();
1048        Box::try_from_path_in(self.as_ref(), alloc)
1049    }
1050}
1051
1052impl TryFrom<&str> for Box<str> {
1053    type Error = Error;
1054
1055    /// Converts a `&str` into a `Box<str>`.
1056    ///
1057    /// # Examples
1058    ///
1059    /// ```
1060    /// use rune::alloc::Box;
1061    ///
1062    /// let s: Box<str> = Box::try_from("Hello World")?;
1063    /// assert_eq!(s.as_ref(), "Hello World");
1064    /// # Ok::<_, rune::alloc::Error>(())
1065    /// ```
1066    #[inline]
1067    fn try_from(values: &str) -> Result<Self, Error> {
1068        Box::try_from_string_in(values, Global)
1069    }
1070}
1071
1072#[cfg(feature = "alloc")]
1073impl TryFrom<rust_alloc::string::String> for Box<str> {
1074    type Error = Error;
1075
1076    /// Converts a std `String` into a `Box<str>`.
1077    ///
1078    /// # Examples
1079    ///
1080    /// ```
1081    /// use rune::alloc::Box;
1082    ///
1083    /// let s = String::from("Hello World");
1084    /// let s: Box<str> = Box::try_from(s)?;
1085    /// assert_eq!(s.as_ref(), "Hello World");
1086    /// # Ok::<_, rune::alloc::Error>(())
1087    /// ```
1088    #[inline]
1089    fn try_from(string: rust_alloc::string::String) -> Result<Self, Error> {
1090        Box::from_std(string.into_boxed_str())
1091    }
1092}
1093
1094impl TryFrom<&[u8]> for Box<[u8]> {
1095    type Error = Error;
1096
1097    /// Converts a `&[u8]` into a `Box<[u8]>`.
1098    ///
1099    /// # Examples
1100    ///
1101    /// ```
1102    /// use rune::alloc::Box;
1103    ///
1104    /// let s: Box<[u8]> = Box::try_from(&b"Hello World"[..])?;
1105    /// assert_eq!(s.as_ref(), b"Hello World");
1106    /// # Ok::<_, rune::alloc::Error>(())
1107    /// ```
1108    #[inline]
1109    fn try_from(values: &[u8]) -> Result<Self, Self::Error> {
1110        Box::try_from_bytes_in(values, Global)
1111    }
1112}
1113
1114#[cfg(feature = "std")]
1115#[cfg_attr(rune_docsrs, doc(cfg(feature = "std")))]
1116impl TryFrom<&Path> for Box<Path> {
1117    type Error = Error;
1118
1119    /// Converts a `&[u8]` into a `Box<[u8]>`.
1120    ///
1121    /// # Examples
1122    ///
1123    /// ```
1124    /// use std::path::Path;
1125    /// use rune::alloc::Box;
1126    ///
1127    /// let path = Path::new("foo/bar");
1128    ///
1129    /// let s: Box<Path> = Box::try_from(path)?;
1130    /// assert_eq!(s.as_ref(), Path::new("foo/bar"));
1131    /// # Ok::<_, rune::alloc::Error>(())
1132    /// ```
1133    #[inline]
1134    fn try_from(path: &Path) -> Result<Self, Error> {
1135        Box::try_from_path_in(path, Global)
1136    }
1137}
1138
1139impl<T, A> TryFromIteratorIn<T, A> for Box<[T], A>
1140where
1141    A: Allocator,
1142{
1143    #[inline]
1144    fn try_from_iter_in<I>(iter: I, alloc: A) -> Result<Self, Error>
1145    where
1146        I: IntoIterator<Item = T>,
1147    {
1148        Vec::<T, A>::try_from_iter_in(iter, alloc)?.try_into_boxed_slice()
1149    }
1150}
1151
1152unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Layout {
1153    // SAFETY: we pass along the prerequisites of these functions to the caller
1154    // TODO: Use mem::{size_of_val_raw, align_of_val_raw} when they become
1155    // stable, for now we privately know that this can safely be turned into a
1156    // reference since it's only used while dropping an owned value of type `T`.
1157    let (size, align) = (mem::size_of_val(&*t), mem::align_of_val(&*t));
1158    // SAFETY: see rationale in `new` for why this is using the unsafe variant
1159    Layout::from_size_align_unchecked(size, align)
1160}
1161
1162impl<T, A> Hash for Box<T, A>
1163where
1164    T: ?Sized + Hash,
1165    A: Allocator,
1166{
1167    #[inline]
1168    fn hash<H>(&self, state: &mut H)
1169    where
1170        H: Hasher,
1171    {
1172        (**self).hash(state);
1173    }
1174}
1175
1176impl<T, A> From<Box<T, A>> for Pin<Box<T, A>>
1177where
1178    T: ?Sized,
1179    A: 'static + Allocator,
1180{
1181    /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement
1182    /// [`Unpin`], then `*boxed` will be pinned in memory and unable to be
1183    /// moved.
1184    ///
1185    /// This conversion does not allocate on the heap and happens in place.
1186    ///
1187    /// This is also available via [`Box::into_pin`].
1188    ///
1189    /// Constructing and pinning a `Box` with
1190    /// <code><Pin<Box\<T>>>::from([Box::try?new]\(x))</code> can also be
1191    /// written more concisely using <code>[Box::try?pin]\(x)</code>. This
1192    /// `From` implementation is useful if you already have a `Box<T>`, or you
1193    /// are constructing a (pinned) `Box` in a different way than with
1194    /// [`Box::try_new`].
1195    #[inline]
1196    fn from(boxed: Box<T, A>) -> Self {
1197        Box::into_pin(boxed)
1198    }
1199}
1200
1201impl<T, A> PartialEq for Box<T, A>
1202where
1203    T: ?Sized + PartialEq,
1204    A: Allocator,
1205{
1206    #[inline]
1207    fn eq(&self, other: &Self) -> bool {
1208        (**self).eq(other)
1209    }
1210}
1211
1212impl<T, A> Eq for Box<T, A>
1213where
1214    T: ?Sized + Eq,
1215    A: Allocator,
1216{
1217}
1218
1219impl<T, A> PartialOrd for Box<T, A>
1220where
1221    T: ?Sized + PartialOrd,
1222    A: Allocator,
1223{
1224    #[inline]
1225    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1226        (**self).partial_cmp(other)
1227    }
1228}
1229
1230impl<T, A> Ord for Box<T, A>
1231where
1232    T: ?Sized + Ord,
1233    A: Allocator,
1234{
1235    #[inline]
1236    fn cmp(&self, other: &Self) -> Ordering {
1237        (**self).cmp(other)
1238    }
1239}
1240
1241#[cfg(feature = "alloc")]
1242impl<T> TryFrom<rust_alloc::boxed::Box<[T]>> for Box<[T]> {
1243    type Error = Error;
1244
1245    #[inline]
1246    fn try_from(values: rust_alloc::boxed::Box<[T]>) -> Result<Self, Self::Error> {
1247        let mut vec = Vec::try_with_capacity(values.len())?;
1248
1249        for value in rust_alloc::vec::Vec::from(values) {
1250            vec.try_push(value)?;
1251        }
1252
1253        vec.try_into_boxed_slice()
1254    }
1255}