@@ -2189,14 +2189,16 @@ pub unsafe trait FromZeros: TryFromBytes {
2189
2189
#[ cfg( feature = "alloc" ) ]
2190
2190
#[ cfg_attr( doc_cfg, doc( cfg( feature = "alloc" ) ) ) ]
2191
2191
#[ inline]
2192
- fn new_box_slice_zeroed ( len : usize ) -> Box < [ Self ] >
2192
+ fn new_box_zeroed_with_elems ( count : usize ) -> Option < Box < Self > >
2193
2193
where
2194
- Self : Sized ,
2194
+ Self : KnownLayout < PointerMetadata = usize > ,
2195
2195
{
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 ( ) ;
2200
2202
// On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a
2201
2203
// bug in which sufficiently-large allocations (those which, when
2202
2204
// rounded up to the alignment, overflow `isize`) are not rejected,
@@ -2208,29 +2210,28 @@ pub unsafe trait FromZeros: TryFromBytes {
2208
2210
assert ! ( size <= max_alloc) ;
2209
2211
// TODO(https://github.com/rust-lang/rust/issues/55724): Use
2210
2212
// `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 ( ) ?;
2213
2214
2214
2215
let ptr = if layout. size ( ) != 0 {
2215
2216
// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
2216
2217
#[ 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) ,
2220
2222
}
2221
- ptr
2222
2223
} else {
2223
2224
// `Box<[T]>` does not allocate when `T` is zero-sized or when `len`
2224
2225
// is zero, but it does require a non-null dangling pointer for its
2225
2226
// allocation.
2226
- NonNull :: < Self > :: dangling ( ) . as_ptr ( )
2227
+ NonNull :: < u8 > :: dangling ( )
2227
2228
} ;
2228
2229
2230
+ let ptr = Self :: raw_from_ptr_len ( ptr, count) ;
2231
+
2229
2232
// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
2230
2233
#[ 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 ( ) ) } )
2234
2235
}
2235
2236
2236
2237
/// Creates a `Vec<Self>` from zeroed bytes.
@@ -2257,11 +2258,11 @@ pub unsafe trait FromZeros: TryFromBytes {
2257
2258
#[ cfg( feature = "alloc" ) ]
2258
2259
#[ cfg_attr( doc_cfg, doc( cfg( feature = "alloc" ) ) ) ]
2259
2260
#[ inline( always) ]
2260
- fn new_vec_zeroed ( len : usize ) -> Vec < Self >
2261
+ fn new_vec_zeroed ( len : usize ) -> Result < Vec < Self > , AllocError >
2261
2262
where
2262
2263
Self : Sized ,
2263
2264
{
2264
- Self :: new_box_slice_zeroed ( len) . into ( )
2265
+ < [ Self ] > :: new_box_zeroed_with_elems ( len) . map ( Into :: into) . ok_or ( AllocError )
2265
2266
}
2266
2267
}
2267
2268
0 commit comments