@@ -192,7 +192,7 @@ use core::fmt;
192192use core:: future:: Future ;
193193use core:: hash:: { Hash , Hasher } ;
194194use core:: marker:: { Tuple , Unsize } ;
195- use core:: mem:: { self , SizedTypeProperties } ;
195+ use core:: mem:: { self , MaybeUninit , SizedTypeProperties } ;
196196use core:: ops:: {
197197 AsyncFn , AsyncFnMut , AsyncFnOnce , CoerceUnsized , Coroutine , CoroutineState , Deref , DerefMut ,
198198 DerefPure , DispatchFromDyn , LegacyReceiver ,
@@ -203,7 +203,7 @@ use core::task::{Context, Poll};
203203
204204#[ cfg( not( no_global_oom_handling) ) ]
205205use crate :: alloc:: handle_alloc_error;
206- use crate :: alloc:: { AllocError , Allocator , Global , Layout , exchange_malloc } ;
206+ use crate :: alloc:: { AllocError , Allocator , Global , Layout } ;
207207use crate :: raw_vec:: RawVec ;
208208#[ cfg( not( no_global_oom_handling) ) ]
209209use crate :: str:: from_boxed_utf8_unchecked;
@@ -233,15 +233,49 @@ pub struct Box<
233233 #[ unstable( feature = "allocator_api" , issue = "32838" ) ] A : Allocator = Global ,
234234> ( Unique < T > , A ) ;
235235
236+ /// Monomorphic function for allocating an uninit `Box`.
237+ ///
238+ /// # Safety
239+ ///
240+ /// size and align need to be safe for `Layout::from_size_align_unchecked`.
241+ #[ inline]
242+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
243+ #[ lang = "exchange_malloc" ]
244+ unsafe fn box_new_uninit ( size : usize , align : usize ) -> * mut u8 {
245+ let layout = unsafe { Layout :: from_size_align_unchecked ( size, align) } ;
246+ match Global . allocate ( layout) {
247+ Ok ( ptr) => ptr. as_mut_ptr ( ) ,
248+ Err ( _) => handle_alloc_error ( layout) ,
249+ }
250+ }
251+
236252/// Constructs a `Box<T>` by calling the `exchange_malloc` lang item and moving the argument into
237253/// the newly allocated memory. This is an intrinsic to avoid unnecessary copies.
238254///
239255/// This is the surface syntax for `box <expr>` expressions.
240- #[ doc( hidden) ]
241256#[ rustc_intrinsic]
242257#[ unstable( feature = "liballoc_internals" , issue = "none" ) ]
243258pub fn box_new < T > ( x : T ) -> Box < T > ;
244259
260+ /// Writes `x` into `b`, then returns `b` at its new type`.
261+ ///
262+ /// This is needed for `vec!`, which can't afford any extra copies of the argument (or else debug
263+ /// builds regress), has to be written fully as a call chain without `let` (or else the temporary
264+ /// lifetimes of the arguments change), and can't use an `unsafe` block as that would then also
265+ /// include the user-provided `$x`.
266+ #[ rustc_intrinsic]
267+ #[ unstable( feature = "liballoc_internals" , issue = "none" ) ]
268+ pub fn init_box_via_move < T > ( b : Box < MaybeUninit < T > > , x : T ) -> Box < T > ;
269+
270+ /// Helper for `vec!` to ensure type inferences work correctly (which it wouldn't if we
271+ /// inlined the `as` cast).
272+ #[ doc( hidden) ]
273+ #[ unstable( feature = "liballoc_internals" , issue = "none" ) ]
274+ #[ inline( always) ]
275+ pub fn box_array_into_vec < T , const N : usize > ( b : Box < [ T ; N ] > ) -> crate :: vec:: Vec < T > {
276+ ( b as Box < [ T ] > ) . into_vec ( )
277+ }
278+
245279impl < T > Box < T > {
246280 /// Allocates memory on the heap and then places `x` into it.
247281 ///
@@ -259,15 +293,18 @@ impl<T> Box<T> {
259293 #[ rustc_diagnostic_item = "box_new" ]
260294 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
261295 pub fn new ( x : T ) -> Self {
262- // SAFETY: the size and align of a valid type `T` are always valid for `Layout`.
263- let ptr = unsafe {
264- exchange_malloc ( <T as SizedTypeProperties >:: SIZE , <T as SizedTypeProperties >:: ALIGN )
265- } as * mut T ;
266- // Nothing below can panic so we do not have to worry about deallocating `ptr`.
267- // SAFETY: we just allocated the box to store `x`.
268- unsafe { core:: intrinsics:: write_via_move ( ptr, x) } ;
269- // SAFETY: we just initialized `b`.
270- unsafe { mem:: transmute ( ptr) }
296+ // This is `Box::new_uninit` but inlined to avoid build time regressions.
297+ // SAFETY:
298+ // - The size and align of a valid type `T` are always valid for `Layout`.
299+ // - If `allocate` succeeds, the returned pointer exactly matches what `Box` needs.
300+ let b = unsafe {
301+ mem:: transmute ( box_new_uninit (
302+ <T as SizedTypeProperties >:: SIZE ,
303+ <T as SizedTypeProperties >:: ALIGN ,
304+ ) )
305+ } ;
306+ // We could do this with `write_via_move`, but may as well use `init_box_via_move`.
307+ init_box_via_move ( b, x)
271308 }
272309
273310 /// Constructs a new box with uninitialized contents.
@@ -285,9 +322,21 @@ impl<T> Box<T> {
285322 #[ cfg( not( no_global_oom_handling) ) ]
286323 #[ stable( feature = "new_uninit" , since = "1.82.0" ) ]
287324 #[ must_use]
288- #[ inline]
325+ #[ inline( always) ]
326+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
289327 pub fn new_uninit ( ) -> Box < mem:: MaybeUninit < T > > {
290- Self :: new_uninit_in ( Global )
328+ // This is the same as `Self::new_uninit_in(Global)`, but manually inlined (just like
329+ // `Box::new`).
330+
331+ // SAFETY:
332+ // - The size and align of a valid type `T` are always valid for `Layout`.
333+ // - If `allocate` succeeds, the returned pointer exactly matches what `Box` needs.
334+ unsafe {
335+ mem:: transmute ( box_new_uninit (
336+ <T as SizedTypeProperties >:: SIZE ,
337+ <T as SizedTypeProperties >:: ALIGN ,
338+ ) )
339+ }
291340 }
292341
293342 /// Constructs a new `Box` with uninitialized contents, with the memory
0 commit comments