@@ -45,56 +45,6 @@ register_bitfields![u16,
4545 ] ,
4646] ;
4747
48- // This is an unsafe workaround of an unsafe workaround.
49- //
50- // Unfortunately, the Rust core library defines defaults on arrays not in a
51- // generic way, but only for arrays up to 32 elements. Hence, for arrays using a
52- // const-generic argument for their length, `Default::<[$SOMETHING_NON_DEFAULT;
53- // CONST_GENERIC_USIZE]>::default()` does not work in Rust (as of
54- // 2022-11-26). Instead, we need to use this horrible and unsafe hack as
55- // documented here, which initializes an array of `MaybeUninit`s and transmutes:
56- // (https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element)
57- //
58- // However, Rust is also unable to transmute from a `MaybeUninit<T>` to a
59- // generic `T`, even though the former is explicitly layout-compatible with the
60- // latter. Hence, we have to use another hack described in the following
61- // comment:
62- // https://github.com/rust-lang/rust/issues/62875#issuecomment-513834029
63- //
64- // This function encapsulates all of this unsafe code and should be safe to use
65- // until Rust adds support for constructing arrays over a const-generic length
66- // from the contained types' default values.
67- //
68- // In large parts, this function is a verbatim copy of Rust's example for
69- // element-wise array initialization using `MaybeUninit`:
70- // https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
71- fn init_constgeneric_default_array < const N : usize , T : Default > ( ) -> [ T ; N ] {
72- // Create an uninitialized array of `MaybeUninit`. The `assume_init` is safe
73- // because the type we are claiming to have initialized here is a bunch of
74- // `MaybeUninit`s, which do not require initialization.
75- let mut uninit_arr: [ core:: mem:: MaybeUninit < T > ; N ] =
76- unsafe { core:: mem:: MaybeUninit :: uninit ( ) . assume_init ( ) } ;
77-
78- // Dropping a `MaybeUninit` does nothing, so if there is a panic during this
79- // loop, we have a memory leak, but there is no memory safety issue.
80- for elem in & mut uninit_arr[ ..] {
81- elem. write ( T :: default ( ) ) ;
82- }
83-
84- // Everything is initialized. We'd like to transmute the `[MaybeUnit<T>; N]`
85- // array into a `[T; N]`, but transmuting `MaybeUninit<T>` to `T` (where T
86- // is generic) is not (yet) supported. Hence we need to take a pointer to
87- // this array, cast it to the correct type, read the pointer back and forget
88- // the original `[MaybeUnit<T>; N]` array, as described here:
89- // https://github.com/rust-lang/rust/issues/62875#issuecomment-513834029
90- let uninit_arr_ptr: * mut [ core:: mem:: MaybeUninit < T > ; N ] = & mut uninit_arr as * mut _ ;
91- let transmuted: [ T ; N ] = unsafe { core:: ptr:: read ( uninit_arr_ptr. cast :: < [ T ; N ] > ( ) ) } ;
92-
93- // With the original value forgotten and new value recreated from its
94- // pointer, return it:
95- transmuted
96- }
97-
9848/// A single Virtqueue descriptor.
9949///
10050/// Implements the memory layout of a single Virtqueue descriptor of a
@@ -142,7 +92,7 @@ pub struct VirtqueueDescriptors<const MAX_QUEUE_SIZE: usize>([VirtqueueDescripto
14292
14393impl < const MAX_QUEUE_SIZE : usize > Default for VirtqueueDescriptors < MAX_QUEUE_SIZE > {
14494 fn default ( ) -> Self {
145- VirtqueueDescriptors ( init_constgeneric_default_array ( ) )
95+ VirtqueueDescriptors ( core :: array :: from_fn ( |_| VirtqueueDescriptor :: default ( ) ) )
14696 }
14797}
14898
@@ -201,7 +151,7 @@ impl<const MAX_QUEUE_SIZE: usize> Default for VirtqueueAvailableRing<MAX_QUEUE_S
201151 VirtqueueAvailableRing {
202152 flags : InMemoryRegister :: new ( 0 ) ,
203153 idx : InMemoryRegister :: new ( 0 ) ,
204- ring : init_constgeneric_default_array ( ) ,
154+ ring : core :: array :: from_fn ( |_| VirtqueueAvailableElement :: default ( ) ) ,
205155 used_event : InMemoryRegister :: new ( 0 ) ,
206156 }
207157 }
@@ -244,7 +194,7 @@ impl<const MAX_QUEUE_SIZE: usize> Default for VirtqueueUsedRing<MAX_QUEUE_SIZE>
244194 VirtqueueUsedRing {
245195 flags : InMemoryRegister :: new ( 0 ) ,
246196 idx : InMemoryRegister :: new ( 0 ) ,
247- ring : init_constgeneric_default_array ( ) ,
197+ ring : core :: array :: from_fn ( |_| VirtqueueUsedElement :: default ( ) ) ,
248198 avail_event : InMemoryRegister :: new ( 0 ) ,
249199 }
250200 }
@@ -493,7 +443,7 @@ impl<'a, 'b, const MAX_QUEUE_SIZE: usize> SplitVirtqueue<'a, 'b, MAX_QUEUE_SIZE>
493443 queue_number : Cell :: new ( 0 ) ,
494444 max_elements : Cell :: new ( MAX_QUEUE_SIZE ) ,
495445
496- descriptor_buffers : init_constgeneric_default_array ( ) ,
446+ descriptor_buffers : core :: array :: from_fn ( |_| OptionalCell :: empty ( ) ) ,
497447
498448 client : OptionalCell :: empty ( ) ,
499449 used_callbacks_enabled : Cell :: new ( false ) ,
@@ -731,8 +681,7 @@ impl<'a, 'b, const MAX_QUEUE_SIZE: usize> SplitVirtqueue<'a, 'b, MAX_QUEUE_SIZE>
731681 ) -> [ Option < VirtqueueBuffer < ' b > > ; MAX_QUEUE_SIZE ] {
732682 assert ! ( self . initialized. get( ) ) ;
733683
734- let mut res: [ Option < VirtqueueBuffer < ' b > > ; MAX_QUEUE_SIZE ] =
735- init_constgeneric_default_array ( ) ;
684+ let mut res: [ Option < VirtqueueBuffer < ' b > > ; MAX_QUEUE_SIZE ] = [ const { None } ; _] ;
736685
737686 let mut i = 0 ;
738687 let mut next_index: Option < usize > = Some ( top_descriptor_index) ;
0 commit comments