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}