(
mut initializer: F,
)
| 191 | |
| 192 | #[inline] |
| 193 | fn try_array_init_impl<Err, F, T, const N: usize, const D: i8>( |
| 194 | mut initializer: F, |
| 195 | ) -> Result<[T; N], Err> |
| 196 | where |
| 197 | F: FnMut(usize) -> Result<T, Err>, |
| 198 | { |
| 199 | // The implementation differentiates two cases: |
| 200 | // A) `T` does not need to be dropped. Even if the initializer panics |
| 201 | // or returns `Err` we will not leak memory. |
| 202 | // B) `T` needs to be dropped. We must keep track of which elements have |
| 203 | // been initialized so far, and drop them if we encounter a panic or `Err` midway. |
| 204 | if !mem::needs_drop::<T>() { |
| 205 | let mut array: MaybeUninit<[T; N]> = MaybeUninit::uninit(); |
| 206 | // pointer to array = *mut [T; N] <-> *mut T = pointer to first element |
| 207 | let mut ptr_i = array.as_mut_ptr() as *mut T; |
| 208 | |
| 209 | // # Safety |
| 210 | // |
| 211 | // - for D > 0, we are within the array since we start from the |
| 212 | // beginning of the array, and we have `0 <= i < N`. |
| 213 | // - for D < 0, we start at the end of the array and go back one |
| 214 | // place before writing, going back N times in total, finishing |
| 215 | // at the start of the array. |
| 216 | unsafe { |
| 217 | if D < 0 { |
| 218 | ptr_i = ptr_i.add(N); |
| 219 | } |
| 220 | for i in 0..N { |
| 221 | let value_i = initializer(i)?; |
| 222 | // We overwrite *ptr_i previously undefined value without reading or dropping it. |
| 223 | if D < 0 { |
| 224 | ptr_i = ptr_i.sub(1); |
| 225 | } |
| 226 | ptr_i.write(value_i); |
| 227 | if D > 0 { |
| 228 | ptr_i = ptr_i.add(1); |
| 229 | } |
| 230 | } |
| 231 | Ok(array.assume_init()) |
| 232 | } |
| 233 | } else { |
| 234 | // else: `mem::needs_drop::<T>()` |
| 235 | |
| 236 | /// # Safety |
| 237 | /// |
| 238 | /// - `base_ptr[.. initialized_count]` must be a slice of init elements... |
| 239 | /// |
| 240 | /// - ... that must be sound to `ptr::drop_in_place` if/when |
| 241 | /// `UnsafeDropSliceGuard` is dropped: "symbolic ownership" |
| 242 | struct UnsafeDropSliceGuard<Item> { |
| 243 | base_ptr: *mut Item, |
| 244 | initialized_count: usize, |
| 245 | } |
| 246 | |
| 247 | impl<Item> Drop for UnsafeDropSliceGuard<Item> { |
| 248 | fn drop(self: &'_ mut Self) { |
| 249 | unsafe { |
| 250 | // # Safety |
nothing calls this directly
no outgoing calls
no test coverage detected