@@ -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,14 +233,39 @@ pub struct Box<
233233 #[ unstable( feature = "allocator_api" , issue = "32838" ) ] A : Allocator = Global ,
234234> ( Unique < T > , A ) ;
235235
236- /// Constructs a `Box<T>` by calling the `exchange_malloc` lang item and moving the argument into
237- /// the newly allocated memory. This is an intrinsic to avoid unnecessary copies.
236+ /// Monomorphic function for allocating an uninit `Box`.
238237///
239- /// This is the surface syntax for `box <expr>` expressions.
240- #[ doc( hidden) ]
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+ unsafe fn box_new_uninit ( size : usize , align : usize ) -> * mut u8 {
244+ let layout = unsafe { Layout :: from_size_align_unchecked ( size, align) } ;
245+ match Global . allocate ( layout) {
246+ Ok ( ptr) => ptr. as_mut_ptr ( ) ,
247+ Err ( _) => handle_alloc_error ( layout) ,
248+ }
249+ }
250+
251+ /// Writes `x` into `b`, then returns `b` at its new type`.
252+ ///
253+ /// This is needed for `vec!`, which can't afford any extra copies of the argument (or else debug
254+ /// builds regress), has to be written fully as a call chain without `let` (or else the temporary
255+ /// lifetimes of the arguments change), and can't use an `unsafe` block as that would then also
256+ /// include the user-provided `$x`.
241257#[ rustc_intrinsic]
242258#[ unstable( feature = "liballoc_internals" , issue = "none" ) ]
243- pub fn box_new < T > ( x : T ) -> Box < T > ;
259+ pub fn init_box_via_move < T > ( b : Box < MaybeUninit < T > > , x : T ) -> Box < T > ;
260+
261+ /// Helper for `vec!` to ensure type inferences work correctly (which it wouldn't if we
262+ /// inlined the `as` cast).
263+ #[ doc( hidden) ]
264+ #[ unstable( feature = "liballoc_internals" , issue = "none" ) ]
265+ #[ inline( always) ]
266+ pub fn box_array_into_vec < T , const N : usize > ( b : Box < [ T ; N ] > ) -> crate :: vec:: Vec < T > {
267+ ( b as Box < [ T ] > ) . into_vec ( )
268+ }
244269
245270impl < T > Box < T > {
246271 /// Allocates memory on the heap and then places `x` into it.
@@ -259,15 +284,18 @@ impl<T> Box<T> {
259284 #[ rustc_diagnostic_item = "box_new" ]
260285 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
261286 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) }
287+ // This is `Box::new_uninit` but inlined to avoid build time regressions.
288+ // SAFETY:
289+ // - The size and align of a valid type `T` are always valid for `Layout`.
290+ // - If `allocate` succeeds, the returned pointer exactly matches what `Box` needs.
291+ let b = unsafe {
292+ mem:: transmute ( box_new_uninit (
293+ <T as SizedTypeProperties >:: SIZE ,
294+ <T as SizedTypeProperties >:: ALIGN ,
295+ ) )
296+ } ;
297+ // We could do this with `write_via_move`, but may as well use `init_box_via_move`.
298+ init_box_via_move ( b, x)
271299 }
272300
273301 /// Constructs a new box with uninitialized contents.
@@ -285,9 +313,21 @@ impl<T> Box<T> {
285313 #[ cfg( not( no_global_oom_handling) ) ]
286314 #[ stable( feature = "new_uninit" , since = "1.82.0" ) ]
287315 #[ must_use]
288- #[ inline]
316+ #[ inline( always) ]
317+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
289318 pub fn new_uninit ( ) -> Box < mem:: MaybeUninit < T > > {
290- Self :: new_uninit_in ( Global )
319+ // This is the same as `Self::new_uninit_in(Global)`, but manually inlined (just like
320+ // `Box::new`).
321+
322+ // SAFETY:
323+ // - The size and align of a valid type `T` are always valid for `Layout`.
324+ // - If `allocate` succeeds, the returned pointer exactly matches what `Box` needs.
325+ unsafe {
326+ mem:: transmute ( box_new_uninit (
327+ <T as SizedTypeProperties >:: SIZE ,
328+ <T as SizedTypeProperties >:: ALIGN ,
329+ ) )
330+ }
291331 }
292332
293333 /// Constructs a new `Box` with uninitialized contents, with the memory
0 commit comments