@@ -2189,14 +2189,16 @@ pub unsafe trait FromZeros: TryFromBytes {
21892189 #[ cfg( feature = "alloc" ) ]
21902190 #[ cfg_attr( doc_cfg, doc( cfg( feature = "alloc" ) ) ) ]
21912191 #[ inline]
2192- fn new_box_slice_zeroed ( len : usize ) -> Box < [ Self ] >
2192+ fn new_box_zeroed_with_elems ( count : usize ) -> Option < Box < Self > >
21932193 where
2194- Self : Sized ,
2194+ Self : KnownLayout < PointerMetadata = usize > ,
21952195 {
2196- let size = mem:: size_of :: < Self > ( )
2197- . checked_mul ( len)
2198- . expect ( "mem::size_of::<Self>() * len overflows `usize`" ) ;
2199- let align = mem:: align_of :: < Self > ( ) ;
2196+ let size = match count. size_for_metadata ( Self :: LAYOUT ) {
2197+ Some ( size) => size,
2198+ None => return None ,
2199+ } ;
2200+
2201+ let align = Self :: LAYOUT . align . get ( ) ;
22002202 // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a
22012203 // bug in which sufficiently-large allocations (those which, when
22022204 // rounded up to the alignment, overflow `isize`) are not rejected,
@@ -2208,29 +2210,28 @@ pub unsafe trait FromZeros: TryFromBytes {
22082210 assert ! ( size <= max_alloc) ;
22092211 // TODO(https://github.com/rust-lang/rust/issues/55724): Use
22102212 // `Layout::repeat` once it's stabilized.
2211- let layout =
2212- Layout :: from_size_align ( size, align) . expect ( "total allocation size overflows `isize`" ) ;
2213+ let layout = Layout :: from_size_align ( size, align) . ok ( ) ?;
22132214
22142215 let ptr = if layout. size ( ) != 0 {
22152216 // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
22162217 #[ allow( clippy:: undocumented_unsafe_blocks) ]
2217- let ptr = unsafe { alloc:: alloc:: alloc_zeroed ( layout) . cast :: < Self > ( ) } ;
2218- if ptr. is_null ( ) {
2219- alloc:: alloc:: handle_alloc_error ( layout) ;
2218+ let ptr = unsafe { alloc:: alloc:: alloc_zeroed ( layout) } ;
2219+ match NonNull :: new ( ptr) {
2220+ Some ( ptr) => ptr,
2221+ None => alloc:: alloc:: handle_alloc_error ( layout) ,
22202222 }
2221- ptr
22222223 } else {
22232224 // `Box<[T]>` does not allocate when `T` is zero-sized or when `len`
22242225 // is zero, but it does require a non-null dangling pointer for its
22252226 // allocation.
2226- NonNull :: < Self > :: dangling ( ) . as_ptr ( )
2227+ NonNull :: < u8 > :: dangling ( )
22272228 } ;
22282229
2230+ let ptr = Self :: raw_from_ptr_len ( ptr, count) ;
2231+
22292232 // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
22302233 #[ allow( clippy:: undocumented_unsafe_blocks) ]
2231- unsafe {
2232- Box :: from_raw ( slice:: from_raw_parts_mut ( ptr, len) )
2233- }
2234+ Some ( unsafe { Box :: from_raw ( ptr. as_ptr ( ) ) } )
22342235 }
22352236
22362237 /// Creates a `Vec<Self>` from zeroed bytes.
@@ -2257,11 +2258,11 @@ pub unsafe trait FromZeros: TryFromBytes {
22572258 #[ cfg( feature = "alloc" ) ]
22582259 #[ cfg_attr( doc_cfg, doc( cfg( feature = "alloc" ) ) ) ]
22592260 #[ inline( always) ]
2260- fn new_vec_zeroed ( len : usize ) -> Vec < Self >
2261+ fn new_vec_zeroed ( len : usize ) -> Result < Vec < Self > , AllocError >
22612262 where
22622263 Self : Sized ,
22632264 {
2264- Self :: new_box_slice_zeroed ( len) . into ( )
2265+ < [ Self ] > :: new_box_zeroed_with_elems ( len) . map ( Into :: into) . ok_or ( AllocError )
22652266 }
22662267}
22672268
0 commit comments