flex_alloc/
boxed.rs

1//! Support for values contained within allocated memory.
2
3use core::borrow;
4use core::cmp::Ordering;
5use core::mem::{ManuallyDrop, MaybeUninit};
6use core::ops::{Deref, DerefMut};
7use core::ptr::NonNull;
8use core::str;
9use core::{fmt, ptr};
10
11#[cfg(feature = "zeroize")]
12use zeroize::{Zeroize, ZeroizeOnDrop};
13
14use crate::alloc::{AllocateIn, Allocator, AllocatorDefault, Global};
15use crate::storage::boxed::RawBox;
16use crate::vec::config::VecConfigAlloc;
17use crate::vec::Vec;
18use crate::StorageError;
19
20#[cfg(feature = "alloc")]
21use crate::alloc::ConvertAlloc;
22
23/// A pointer type that uniquely owns an allocation of type `T`.
24pub struct Box<T: ?Sized, A: Allocator = Global> {
25    pub(crate) handle: RawBox<T, A>,
26}
27
28impl<T, A: AllocatorDefault> Box<T, A> {
29    /// Allocates in the associated allocator and then places `value` into it.
30    /// This doesn’t actually allocate if `T` is zero-sized.
31    pub fn new(value: T) -> Box<T, A> {
32        match Self::try_new(value) {
33            Ok(slf) => slf,
34            Err(e) => e.panic(),
35        }
36    }
37
38    /// Allocates uninitialized memory in the associated allocator.
39    /// This doesn’t actually allocate if `T` is zero-sized.
40    pub fn new_uninit() -> Box<MaybeUninit<T>, A> {
41        match Self::try_new_uninit() {
42            Ok(uninit) => uninit,
43            Err(e) => e.panic(),
44        }
45    }
46
47    /// Tries to allocate in the associated allocator and then places `value` into it.
48    /// This doesn’t actually allocate if `T` is zero-sized.
49    pub fn try_new(value: T) -> Result<Box<T, A>, StorageError> {
50        RawBox::alloc().map(|boxed| Self {
51            handle: boxed.write(value),
52        })
53    }
54
55    /// Tries to allocate uninitialized memory in the associated allocator.
56    /// This doesn’t actually allocate if `T` is zero-sized.
57    pub fn try_new_uninit() -> Result<Box<MaybeUninit<T>, A>, StorageError> {
58        RawBox::alloc().map(|inner| Box { handle: inner })
59    }
60
61    /// Unwraps this `Box` into its contained value.
62    pub fn into_inner(boxed: Self) -> T {
63        boxed.into_handle().into_inner()
64    }
65}
66
67impl<T, A: AllocatorDefault> Box<[T], A> {
68    /// Allocate uninitialized memory in the associated allocator.
69    /// This doesn’t actually allocate if `T` is zero-sized.
70    pub fn new_uninit_slice(len: usize) -> Box<[MaybeUninit<T>], A> {
71        match Self::try_new_uninit_slice(len) {
72            Ok(res) => res,
73            Err(err) => err.panic(),
74        }
75    }
76
77    /// Tries to allocate uninitialized memory in the associated allocator.
78    /// This doesn’t actually allocate if `T` is zero-sized.
79    pub fn try_new_uninit_slice(len: usize) -> Result<Box<[MaybeUninit<T>], A>, StorageError> {
80        RawBox::alloc_slice(len, true).map(|inner| Box { handle: inner })
81    }
82}
83
84impl<T: ?Sized, A: AllocatorDefault> Box<T, A> {
85    /// Constructs a box from a raw pointer.
86    ///
87    /// After calling this function, the raw pointer is owned by the resulting `Box`.
88    /// Specifically, the box destructor will call the destructor of `T` and free the
89    /// allocated memory.
90    ///
91    /// # Safety
92    /// The memory must have been allocated in accordance with the memory layout used by `Box`.
93    pub unsafe fn from_raw(raw: *mut T) -> Self {
94        Self::from_raw_in(raw, A::DEFAULT)
95    }
96
97    /// Consumes the `Box`, returning a wrapped raw pointer.
98    ///
99    /// The pointer will be properly aligned and non-null.
100    ///
101    /// After calling this function, the caller is responsible for the memory
102    /// previously managed by the `Box`. In particular, the caller should properly
103    /// destroy `T` and release the memory, taking into account the memory layout
104    /// used by `Box`. The easiest way to do this is to convert the raw pointer back
105    /// into a `Box` with the [`Box::from_raw`] function, allowing the `Box` destructor to
106    /// perform the cleanup.
107    ///
108    /// Note: this is an associated function, which means that you have to call it as
109    /// `Box::into_raw(b)` instead of `b.into_raw()`. This is so that there is no conflict
110    /// with a method on the inner type.
111    pub fn into_raw(boxed: Self) -> *mut T {
112        Self::into_raw_with_allocator(boxed).0
113    }
114}
115
116impl<T, A: Allocator> Box<T, A> {
117    /// Allocates in the associated allocation target and then places `value` into it.
118    /// This doesn’t actually allocate if `T` is zero-sized.
119    pub fn new_in<I>(value: T, alloc_in: I) -> Box<T, A>
120    where
121        I: AllocateIn<Alloc = A>,
122    {
123        match Self::try_new_in(value, alloc_in) {
124            Ok(slf) => slf,
125            Err(e) => e.panic(),
126        }
127    }
128
129    /// Allocates uninitialized memory in the associated allocation target.
130    /// This doesn’t actually allocate if `T` is zero-sized.
131    pub fn new_uninit_in<I>(alloc_in: I) -> Box<MaybeUninit<T>, A>
132    where
133        I: AllocateIn<Alloc = A>,
134    {
135        match Self::try_new_uninit_in(alloc_in) {
136            Ok(uninit) => uninit,
137            Err(e) => e.panic(),
138        }
139    }
140
141    /// Tries to allocate in the associated allocation target and then places `value` into it.
142    /// This doesn’t actually allocate if `T` is zero-sized.
143    pub fn try_new_in<I>(value: T, alloc_in: I) -> Result<Box<T, A>, StorageError>
144    where
145        I: AllocateIn<Alloc = A>,
146    {
147        RawBox::alloc_in(alloc_in).map(|boxed| Self {
148            handle: boxed.write(value),
149        })
150    }
151
152    /// Tries to allocate uninitialized memory in the associated allocation target.
153    /// This doesn’t actually allocate if `T` is zero-sized.
154    pub fn try_new_uninit_in<I>(alloc_in: I) -> Result<Box<MaybeUninit<T>, A>, StorageError>
155    where
156        I: AllocateIn<Alloc = A>,
157    {
158        RawBox::alloc_in(alloc_in).map(|inner| Box { handle: inner })
159    }
160}
161
162impl<T, A: Allocator> Box<[T], A> {
163    /// Allocates uninitialized memory in the associated allocation target.
164    /// This doesn’t actually allocate if `T` is zero-sized.
165    pub fn new_uninit_slice_in<I>(len: usize, alloc_in: I) -> Box<[MaybeUninit<T>], A>
166    where
167        I: AllocateIn<Alloc = A>,
168    {
169        match Self::try_new_uninit_slice_in(len, alloc_in) {
170            Ok(res) => res,
171            Err(err) => err.panic(),
172        }
173    }
174
175    /// Tries to allocates uninitialized memory in the associated allocation target.
176    /// This doesn’t actually allocate if `T` is zero-sized.
177    pub fn try_new_uninit_slice_in<I>(
178        len: usize,
179        alloc_in: I,
180    ) -> Result<Box<[MaybeUninit<T>], A>, StorageError>
181    where
182        I: AllocateIn<Alloc = A>,
183    {
184        RawBox::alloc_slice_in(alloc_in, len, true).map(|inner| Box { handle: inner })
185    }
186
187    /// Convert this boxed slice into a `Vec<T, A>` without reallocating.
188    pub fn into_vec(self) -> Vec<T, A> {
189        let (ptr, alloc) = self.into_handle().into_parts();
190        let len = ptr.len();
191        // SAFETY: a boxed slice has a matching length and capacity. The pointer
192        // is a valid allocation for this allocator.
193        unsafe { Vec::from_parts(ptr.cast::<T>(), len, len, alloc) }
194    }
195
196    fn dangling(alloc: A) -> Box<[T], A> {
197        Self {
198            handle: RawBox::dangling(alloc),
199        }
200    }
201}
202
203impl<A: Allocator> Box<str, A> {
204    /// Convert a boxed slice of bytes into a `Box<str>`.
205    ///
206    /// If you are sure that the byte slice is valid UTF-8, and you don’t
207    /// want to incur the overhead of the validity check, there is an unsafe
208    /// version of this function, [`Box::from_utf8_unchecked`], which has the
209    /// same behavior but skips the check.
210    pub fn from_utf8(boxed: Box<[u8], A>) -> Result<Self, str::Utf8Error> {
211        let (ptr, alloc) = Box::into_raw_with_allocator(boxed);
212        unsafe {
213            // SAFETY: the pointer is guaranteed to be a valid and unaliased.
214            let strval = str::from_utf8_mut(&mut *ptr)?;
215            // SAFETY: only the type of the pointer has changed. The alignment
216            // of `str` is the same as `[u8]` and the allocation size is the same.
217            Ok(Self::from_raw_in(strval, alloc))
218        }
219    }
220
221    /// Convert a boxed slice of bytes into a `Box<str>`.
222    ///
223    /// # Safety
224    /// The contained bytes must be valid UTF-8.
225    pub unsafe fn from_utf8_unchecked(boxed: Box<[u8], A>) -> Self {
226        let (ptr, alloc) = Box::into_raw_with_allocator(boxed);
227        // SAFETY: the pointer is guaranteed to be a valid and unaliased.
228        let strval = str::from_utf8_unchecked_mut(&mut *ptr);
229        // SAFETY: only the type of the pointer has changed. The alignment
230        // of `str` is the same as `[u8]` and the allocation size is the same.
231        Self::from_raw_in(strval, alloc)
232    }
233}
234
235impl<T: Clone, A: AllocatorDefault> Box<[T], A> {
236    /// Create a boxed slice by cloning a slice reference.
237    pub fn from_slice(data: &[T]) -> Self {
238        match Self::try_from_slice(data) {
239            Ok(res) => res,
240            Err(err) => err.panic(),
241        }
242    }
243
244    /// Try to create a boxed slice by cloning a slice reference.
245    pub fn try_from_slice(data: &[T]) -> Result<Self, StorageError> {
246        let len = data.len();
247        let handle = RawBox::alloc_slice(len, true)?;
248        Ok(Self {
249            handle: handle.write_slice(|insert| {
250                insert.push_slice(data);
251            }),
252        })
253    }
254}
255
256impl<T: Clone, A: Allocator> Box<[T], A> {
257    /// Create a boxed slice directly in an allocation target by cloning a slice reference.
258    pub fn from_slice_in<I>(data: &[T], alloc_in: I) -> Self
259    where
260        I: AllocateIn<Alloc = A>,
261    {
262        match Self::try_from_slice_in(data, alloc_in) {
263            Ok(res) => res,
264            Err(err) => err.panic(),
265        }
266    }
267
268    /// Try to create a boxed slice directly in an allocation target by cloning a slice reference.
269    pub fn try_from_slice_in<I>(data: &[T], alloc_in: I) -> Result<Self, StorageError>
270    where
271        I: AllocateIn<Alloc = A>,
272    {
273        let len = data.len();
274        let handle = RawBox::alloc_slice_in(alloc_in, len, true)?;
275        Ok(Self {
276            handle: handle.write_slice(|insert| {
277                insert.push_slice(data);
278            }),
279        })
280    }
281}
282
283impl<T: ?Sized, A: Allocator> Box<T, A> {
284    /// Obtain a reference to the contained allocator instance.
285    pub fn allocator(&self) -> &A {
286        self.handle.allocator()
287    }
288
289    /// Get a read pointer to the beginning of the data allocation. This may be a
290    /// dangling pointer if `T` is zero sized or the current capacity is zero.
291    #[inline]
292    pub fn as_ptr(&self) -> *const T {
293        self.handle.as_ptr()
294    }
295
296    /// Get a mutable pointer to the beginning of the data allocation. This may be a
297    /// dangling pointer if `T` is zero sized or the current capacity is zero.
298    #[inline]
299    pub fn as_mut_ptr(&mut self) -> *mut T {
300        self.handle.as_mut_ptr()
301    }
302
303    /// Constructs a box from a raw pointer and an allocator instance.
304    ///
305    /// After calling this function, the raw pointer is owned by the resulting `Box`.
306    /// Specifically, the box destructor will call the destructor of `T` and free the
307    /// allocated memory.
308    ///
309    /// # Safety
310    /// The memory must have been allocated in accordance with the memory layout used by `Box`.
311    pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
312        let ptr = NonNull::new(raw).expect("from_raw: pointer must not be null");
313        Self {
314            handle: RawBox::from_parts(ptr, alloc),
315        }
316    }
317
318    /// Consumes the `Box`, returning a wrapped raw pointer and an allocator instance.
319    ///
320    /// The pointer will be properly aligned and non-null.
321    ///
322    /// After calling this function, the caller is responsible for the memory
323    /// previously managed by the `Box`. In particular, the caller should properly
324    /// destroy `T` and release the memory, taking into account the memory layout
325    /// used by `Box`. The easiest way to do this is to convert the raw pointer back
326    /// into a `Box` with the [`Box::from_raw_in`] function, allowing the `Box` destructor
327    /// to perform the cleanup.
328    ///
329    /// Note: this is an associated function, which means that you have to call it as
330    /// `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This is
331    /// so that there is no conflict with a method on the inner type.
332    pub fn into_raw_with_allocator(boxed: Self) -> (*mut T, A) {
333        let (ptr, alloc) = boxed.into_handle().into_parts();
334        (ptr.as_ptr(), alloc)
335    }
336
337    /// Consumes and leaks the `Box`, returning a mutable reference, `&'a mut T`.
338    ///
339    /// Note that the type `T` must outlive the chosen lifetime `'a`. If the type has
340    /// only static references, or none at all, then this may be chosen to be `'static`.
341    ///
342    /// This function is mainly useful for data that lives for the remainder of the program's
343    /// life. Dropping the returned reference will cause a memory leak. If this is not
344    /// acceptable, the reference should first be wrapped with the `Box::from_raw` function
345    /// producing a `Box`. This `Box` can then be dropped which will properly destroy `T` and
346    /// release the allocated memory.
347    ///
348    /// Note: this is an associated function, which means that you have to call it as
349    /// `Box::leak(b)` instead of `b.leak()`. This is so that there is no conflict with a
350    /// method on the inner type.
351    pub fn leak<'a>(boxed: Self) -> &'a mut T
352    where
353        A: 'a,
354    {
355        boxed.into_handle().leak()
356    }
357
358    #[inline]
359    pub(crate) fn into_handle(self) -> RawBox<T, A> {
360        // SAFETY: this simply extracts the handle without running
361        // the `Drop` implementation for this `Box`. It is safe to
362        // read from a pointer derived from a reference and the
363        // aliasing rules are not violated.
364        unsafe { ptr::read(&ManuallyDrop::new(self).handle) }
365    }
366}
367
368impl<T, A: Allocator> Box<MaybeUninit<T>, A> {
369    /// Converts to `Box<T, A>`.
370    ///
371    /// # Safety
372    /// The contents of the box must be initialized prior to calling, or else
373    /// undefined behavior may result from the use of uninitialized memory.
374    #[inline]
375    pub unsafe fn assume_init(self) -> Box<T, A> {
376        Box {
377            handle: self.into_handle().assume_init(),
378        }
379    }
380
381    /// Writes the value and converts to `Box<T, A>`.
382    ///
383    /// This method converts the box similarly to `Box::assume_init` but writes value
384    /// into it before conversion, thus guaranteeing safety. In some scenarios use of
385    /// this method may improve performance because the compiler may be able to optimize
386    /// copying from stack.
387    #[inline(always)]
388    pub fn write(boxed: Self, value: T) -> Box<T, A> {
389        Box {
390            handle: boxed.into_handle().write(value),
391        }
392    }
393}
394
395impl<T, A: Allocator> Box<[MaybeUninit<T>], A> {
396    /// Converts to `Box<[T], A>`.
397    ///
398    /// # Safety
399    /// The contents of the box must be initialized prior to calling, or else
400    /// undefined behavior may result from the use of uninitialized memory.
401    #[inline]
402    pub unsafe fn assume_init(self) -> Box<[T], A> {
403        Box {
404            handle: self.into_handle().assume_init(),
405        }
406    }
407}
408
409impl<T, A: Allocator, const N: usize> Box<[T; N], A> {
410    /// Converts a `Box<T, A>` into a `Box<[T], A>`.
411    ///
412    /// This conversion does not allocate on the heap and happens in place.
413    pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> {
414        let (ptr, alloc) = boxed.into_handle().into_parts();
415        Box {
416            handle: RawBox::from_parts(NonNull::slice_from_raw_parts(ptr.cast::<T>(), N), alloc),
417        }
418    }
419}
420
421impl<T: ?Sized, A: Allocator> AsRef<T> for Box<T, A> {
422    fn as_ref(&self) -> &T {
423        self.handle.as_ref()
424    }
425}
426
427impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
428    fn as_mut(&mut self) -> &mut T {
429        self.handle.as_mut()
430    }
431}
432
433impl<T: ?Sized, A: Allocator> borrow::Borrow<T> for Box<T, A> {
434    fn borrow(&self) -> &T {
435        self.handle.as_ref()
436    }
437}
438
439impl<T: ?Sized, A: Allocator> borrow::BorrowMut<T> for Box<T, A> {
440    fn borrow_mut(&mut self) -> &mut T {
441        self.handle.as_mut()
442    }
443}
444
445impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
446    fn clone(&self) -> Self {
447        let boxed = Self::new_uninit_in(self.allocator().clone());
448        Box::write(boxed, self.as_ref().clone())
449    }
450}
451
452impl<T: Clone, A: Allocator + Clone> Clone for Box<[T], A> {
453    fn clone(&self) -> Self {
454        Self::from_slice_in(self.as_ref(), self.allocator().clone())
455    }
456}
457
458impl<A: Allocator + Clone> Clone for Box<str, A> {
459    fn clone(&self) -> Self {
460        let boxed = Box::<[u8], A>::from_slice_in(self.as_bytes(), self.allocator().clone());
461        // SAFETY: the Box contents are guaranteed to be valid UTF-8 data.
462        unsafe { Box::from_utf8_unchecked(boxed) }
463    }
464}
465
466#[cfg(feature = "nightly")]
467impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized, A: Allocator>
468    core::ops::CoerceUnsized<Box<U, A>> for Box<T, A>
469{
470}
471
472impl<T: ?Sized + fmt::Debug, A: Allocator> fmt::Debug for Box<T, A> {
473    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474        self.as_ref().fmt(f)
475    }
476}
477
478impl<T: Default, A: AllocatorDefault> Default for Box<T, A> {
479    fn default() -> Self {
480        Self::new(T::default())
481    }
482}
483
484impl<T, A: AllocatorDefault> Default for Box<[T], A> {
485    fn default() -> Self {
486        Self::dangling(A::DEFAULT)
487    }
488}
489
490impl<A: AllocatorDefault> Default for Box<str, A> {
491    fn default() -> Self {
492        // SAFETY: an empty (dangling) Box is valid UTF-8.
493        unsafe { Box::from_utf8_unchecked(Box::dangling(A::DEFAULT)) }
494    }
495}
496
497impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
498    type Target = T;
499
500    fn deref(&self) -> &Self::Target {
501        self.handle.as_ref()
502    }
503}
504
505impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
506    fn deref_mut(&mut self) -> &mut Self::Target {
507        self.handle.as_mut()
508    }
509}
510
511impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
512    fn drop(&mut self) {
513        unsafe {
514            ptr::drop_in_place(self.handle.as_mut());
515        }
516    }
517}
518
519impl<T, A: AllocatorDefault> From<T> for Box<T, A> {
520    #[inline]
521    fn from(value: T) -> Self {
522        Box::write(Self::new_uninit(), value)
523    }
524}
525
526impl<T: Clone, A: AllocatorDefault> From<&[T]> for Box<[T], A> {
527    fn from(data: &[T]) -> Self {
528        Self::from_slice(data)
529    }
530}
531
532impl<T, A: AllocatorDefault, const N: usize> From<[T; N]> for Box<[T], A> {
533    fn from(data: [T; N]) -> Self {
534        Box::into_boxed_slice(Box::new(data))
535    }
536}
537
538impl<A: AllocatorDefault> From<&str> for Box<str, A> {
539    fn from(data: &str) -> Self {
540        let boxed = Box::from_slice(data.as_bytes());
541        // SAFETY: the Box contents are guaranteed to be valid UTF-8 data.
542        unsafe { Self::from_utf8_unchecked(boxed) }
543    }
544}
545
546impl<T, C> From<Vec<T, C>> for Box<[T], C::Alloc>
547where
548    C: VecConfigAlloc<T>,
549{
550    fn from(vec: Vec<T, C>) -> Self {
551        vec.into_boxed_slice()
552    }
553}
554
555impl<T, A: AllocatorDefault> FromIterator<T> for Box<[T], A> {
556    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
557        Vec::<T, A>::from_iter(iter).into_boxed_slice()
558    }
559}
560
561impl<T, A: Allocator, const N: usize> TryFrom<Box<[T], A>> for Box<[T; N], A> {
562    type Error = Box<[T], A>;
563
564    fn try_from(boxed: Box<[T], A>) -> Result<Self, Self::Error> {
565        if boxed.len() == N {
566            Ok(Self {
567                handle: unsafe { boxed.into_handle().cast() },
568            })
569        } else {
570            Err(boxed)
571        }
572    }
573}
574
575impl<T, A: Allocator, const N: usize> TryFrom<Vec<T, A>> for Box<[T; N], A> {
576    type Error = Vec<T, A>;
577
578    fn try_from(vec: Vec<T, A>) -> Result<Self, Self::Error> {
579        if vec.len() == N {
580            let boxed = vec.into_boxed_slice();
581            Ok(Self {
582                handle: unsafe { boxed.into_handle().cast() },
583            })
584        } else {
585            Err(vec)
586        }
587    }
588}
589
590#[cfg(all(feature = "alloc", not(feature = "nightly")))]
591impl<T: ?Sized> ConvertAlloc<Box<T, Global>> for alloc_crate::boxed::Box<T> {
592    fn convert(self) -> Box<T, Global> {
593        let raw = alloc_crate::boxed::Box::into_raw(self);
594        unsafe { Box::from_raw(raw) }
595    }
596}
597
598#[cfg(all(feature = "alloc", feature = "nightly"))]
599impl<T: ?Sized, A: Allocator> ConvertAlloc<Box<T, A>> for alloc_crate::boxed::Box<T, A> {
600    fn convert(self) -> Box<T, A> {
601        let (raw, alloc) = alloc_crate::boxed::Box::into_raw_with_allocator(self);
602        unsafe { Box::from_raw_in(raw, alloc) }
603    }
604}
605
606#[cfg(all(feature = "alloc", not(feature = "nightly")))]
607impl<T: ?Sized> ConvertAlloc<alloc_crate::boxed::Box<T>> for Box<T, Global> {
608    fn convert(self) -> alloc_crate::boxed::Box<T> {
609        let raw = Box::into_raw(self);
610        unsafe { alloc_crate::boxed::Box::from_raw(raw) }
611    }
612}
613
614#[cfg(all(feature = "alloc", feature = "nightly"))]
615impl<T: ?Sized, A: Allocator> ConvertAlloc<alloc_crate::boxed::Box<T, A>> for Box<T, A> {
616    fn convert(self) -> alloc_crate::boxed::Box<T, A> {
617        let (raw, alloc) = Box::into_raw_with_allocator(self);
618        unsafe { alloc_crate::boxed::Box::from_raw_in(raw, alloc) }
619    }
620}
621
622impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for Box<T, A> {
623    #[inline]
624    fn eq(&self, other: &Self) -> bool {
625        PartialEq::eq(self.as_ref(), other.as_ref())
626    }
627}
628
629impl<T: ?Sized + Eq, A: Allocator> Eq for Box<T, A> {}
630
631impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Box<T, A> {
632    #[inline]
633    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
634        PartialOrd::partial_cmp(&**self, &**other)
635    }
636}
637
638impl<T: ?Sized + Ord, A: Allocator> Ord for Box<T, A> {
639    #[inline]
640    fn cmp(&self, other: &Self) -> Ordering {
641        Ord::cmp(&**self, &**other)
642    }
643}
644
645unsafe impl<T: Send + ?Sized, A: Allocator + Send> Send for Box<T, A> {}
646unsafe impl<T: Sync + ?Sized, A: Allocator + Sync> Sync for Box<T, A> {}
647
648impl<T: ?Sized, A: Allocator> Unpin for Box<T, A> {}
649
650#[cfg(feature = "zeroize")]
651impl<T: ?Sized + Zeroize, A: Allocator> Zeroize for Box<T, A> {
652    fn zeroize(&mut self) {
653        self.as_mut().zeroize()
654    }
655}
656
657#[cfg(feature = "zeroize")]
658impl<T: ?Sized, A: crate::alloc::AllocatorZeroizes> ZeroizeOnDrop for Box<T, A> {}
659
660#[cfg(test)]
661mod tests {
662    #[cfg(all(feature = "alloc", feature = "nightly"))]
663    #[test]
664    fn box_unsized() {
665        use core::any::Any;
666
667        use super::Box;
668
669        let _ = Box::new(10usize) as Box<dyn Any>;
670    }
671}