diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index ce84f105e5c50..d0be82adb6b16 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1065,161 +1065,46 @@ impl MaybeUninit { this.write_clone_of_slice(src) } - /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now - /// initialized contents of the slice. - /// Any previously initialized elements will not be dropped. - /// - /// This is similar to [`slice::fill`]. - /// - /// # Panics - /// - /// This function will panic if any call to `Clone` panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 10]; - /// let initialized = MaybeUninit::fill(&mut buf, 1); - /// assert_eq!(initialized, &mut [1; 10]); - /// ``` - #[doc(alias = "memset")] + /// Deprecated version of [`slice::write_filled`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill(this: &mut [MaybeUninit], value: T) -> &mut [T] + #[deprecated( + note = "replaced by inherent write_filled method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill<'a>(this: &'a mut [MaybeUninit], value: T) -> &'a mut [T] where T: Clone, { - SpecFill::spec_fill(this, value); - // SAFETY: Valid elements have just been filled into `this` so it is initialized - unsafe { this.assume_init_mut() } + this.write_filled(value) } - /// Fills a slice with elements returned by calling a closure repeatedly. - /// - /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use - /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can - /// pass [`Default::default`] as the argument. - /// - /// # Panics - /// - /// This function will panic if any call to the provided closure panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::::uninit() }; 10]; - /// let initialized = MaybeUninit::fill_with(&mut buf, Default::default); - /// assert_eq!(initialized, &mut [0; 10]); - /// ``` + /// Deprecated version of [`slice::write_with`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_with(this: &mut [MaybeUninit], mut f: F) -> &mut [T] + #[deprecated( + note = "replaced by inherent write_with method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit], mut f: F) -> &'a mut [T] where F: FnMut() -> T, { - let mut guard = Guard { slice: this, initialized: 0 }; - - for element in guard.slice.iter_mut() { - element.write(f()); - guard.initialized += 1; - } - - super::forget(guard); - - // SAFETY: Valid elements have just been written into `this` so it is initialized - unsafe { this.assume_init_mut() } + this.write_with(|_| f()) } - /// Fills a slice with elements yielded by an iterator until either all elements have been - /// initialized or the iterator is empty. - /// - /// Returns two slices. The first slice contains the initialized portion of the original slice. - /// The second slice is the still-uninitialized remainder of the original slice. - /// - /// # Panics - /// - /// This function panics if the iterator's `next` function panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// Completely filling the slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 5]; - /// - /// let iter = [1, 2, 3].into_iter().cycle(); - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); - /// - /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); - /// assert_eq!(remainder.len(), 0); - /// ``` - /// - /// Partially filling the slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 5]; - /// let iter = [1, 2]; - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); - /// - /// assert_eq!(initialized, &mut [1, 2]); - /// assert_eq!(remainder.len(), 3); - /// ``` - /// - /// Checking an iterator after filling a slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 3]; - /// let mut iter = [1, 2, 3, 4, 5].into_iter(); - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter.by_ref()); - /// - /// assert_eq!(initialized, &mut [1, 2, 3]); - /// assert_eq!(remainder.len(), 0); - /// assert_eq!(iter.as_slice(), &[4, 5]); - /// ``` + /// Deprecated version of [`slice::write_iter`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_from(this: &mut [MaybeUninit], it: I) -> (&mut [T], &mut [MaybeUninit]) + #[deprecated( + note = "replaced by inherent write_iter method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill_from<'a, I>( + this: &'a mut [MaybeUninit], + it: I, + ) -> (&'a mut [T], &'a mut [MaybeUninit]) where I: IntoIterator, { - let iter = it.into_iter(); - let mut guard = Guard { slice: this, initialized: 0 }; - - for (element, val) in guard.slice.iter_mut().zip(iter) { - element.write(val); - guard.initialized += 1; - } - - let initialized_len = guard.initialized; - super::forget(guard); - - // SAFETY: guard.initialized <= this.len() - let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) }; - - // SAFETY: Valid elements have just been written into `init`, so that portion - // of `this` is initialized. - (unsafe { initted.assume_init_mut() }, remainder) + this.write_iter(it) } /// Deprecated version of [`slice::as_bytes`]. @@ -1380,6 +1265,163 @@ impl [MaybeUninit] { unsafe { self.assume_init_mut() } } + /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of the slice. + /// Any previously initialized elements will not be dropped. + /// + /// This is similar to [`slice::fill`]. + /// + /// # Panics + /// + /// This function will panic if any call to `Clone` panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 10]; + /// let initialized = buf.write_filled(1); + /// assert_eq!(initialized, &mut [1; 10]); + /// ``` + #[doc(alias = "memset")] + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_filled(&mut self, value: T) -> &mut [T] + where + T: Clone, + { + SpecFill::spec_fill(self, value); + // SAFETY: Valid elements have just been filled into `self` so it is initialized + unsafe { self.assume_init_mut() } + } + + /// Fills a slice with elements returned by calling a closure for each index. + /// + /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use + /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can + /// pass [`|_| Default::default()`][Default::default] as the argument. + /// + /// # Panics + /// + /// This function will panic if any call to the provided closure panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::::uninit() }; 5]; + /// let initialized = buf.write_with(|idx| idx + 1); + /// assert_eq!(initialized, &mut [1, 2, 3, 4, 5]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_with(&mut self, mut f: F) -> &mut [T] + where + F: FnMut(usize) -> T, + { + let mut guard = Guard { slice: self, initialized: 0 }; + + for (idx, element) in guard.slice.iter_mut().enumerate() { + element.write(f(idx)); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { self.assume_init_mut() } + } + + /// Fills a slice with elements yielded by an iterator until either all elements have been + /// initialized or the iterator is empty. + /// + /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// The second slice is the still-uninitialized remainder of the original slice. + /// + /// # Panics + /// + /// This function panics if the iterator's `next` function panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Completely filling the slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; + /// + /// let iter = [1, 2, 3].into_iter().cycle(); + /// let (initialized, remainder) = buf.write_iter(iter); + /// + /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); + /// assert_eq!(remainder.len(), 0); + /// ``` + /// + /// Partially filling the slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; + /// let iter = [1, 2]; + /// let (initialized, remainder) = buf.write_iter(iter); + /// + /// assert_eq!(initialized, &mut [1, 2]); + /// assert_eq!(remainder.len(), 3); + /// ``` + /// + /// Checking an iterator after filling a slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 3]; + /// let mut iter = [1, 2, 3, 4, 5].into_iter(); + /// let (initialized, remainder) = buf.write_iter(iter.by_ref()); + /// + /// assert_eq!(initialized, &mut [1, 2, 3]); + /// assert_eq!(remainder.len(), 0); + /// assert_eq!(iter.as_slice(), &[4, 5]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_iter(&mut self, it: I) -> (&mut [T], &mut [MaybeUninit]) + where + I: IntoIterator, + { + let iter = it.into_iter(); + let mut guard = Guard { slice: self, initialized: 0 }; + + for (element, val) in guard.slice.iter_mut().zip(iter) { + element.write(val); + guard.initialized += 1; + } + + let initialized_len = guard.initialized; + super::forget(guard); + + // SAFETY: guard.initialized <= self.len() + let (initted, remainder) = unsafe { self.split_at_mut_unchecked(initialized_len) }; + + // SAFETY: Valid elements have just been written into `init`, so that portion + // of `this` is initialized. + (unsafe { initted.assume_init_mut() }, remainder) + } + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 9cb94ca3b0ff0..9c15be4a8c4bd 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -1,5 +1,5 @@ use core::mem::*; -use core::ptr; +use core::{array, ptr}; #[cfg(panic = "unwind")] use std::rc::Rc; @@ -327,11 +327,11 @@ fn uninit_write_clone_of_slice_no_drop() { } #[test] -fn uninit_fill() { +fn uninit_write_filled() { let mut dst = [MaybeUninit::new(255); 64]; let expect = [0; 64]; - assert_eq!(MaybeUninit::fill(&mut dst, 0), &expect); + assert_eq!(dst.write_filled(0), &expect); } #[cfg(panic = "unwind")] @@ -352,7 +352,7 @@ impl Clone for CloneUntilPanic { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_clone_panic_drop() { +fn uninit_write_filled_panic_drop() { use std::panic; let rc = Rc::new(()); @@ -361,7 +361,7 @@ fn uninit_fill_clone_panic_drop() { let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill(&mut dst, src); + dst.write_filled(src); })); match err { @@ -378,23 +378,23 @@ fn uninit_fill_clone_panic_drop() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_clone_no_drop_clones() { +fn uninit_write_filled_no_drop_clones() { let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; - MaybeUninit::fill(&mut dst, Bomb); + dst.write_filled(Bomb); } #[test] -fn uninit_fill_with() { - let mut dst = [MaybeUninit::new(255); 64]; - let expect = [0; 64]; +fn uninit_write_with() { + let mut dst = [MaybeUninit::new(255usize); 64]; + let expect = array::from_fn::(|idx| idx); - assert_eq!(MaybeUninit::fill_with(&mut dst, || 0), &expect); + assert_eq!(dst.write_with(|idx| idx), &expect); } #[test] #[cfg(panic = "unwind")] -fn uninit_fill_with_mid_panic() { +fn uninit_write_with_mid_panic() { use std::panic; let rc = Rc::new(()); @@ -403,7 +403,7 @@ fn uninit_fill_with_mid_panic() { let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill_with(&mut dst, || src.clone()); + dst.write_with(|_| src.clone()); })); drop(src); @@ -423,58 +423,58 @@ fn uninit_fill_with_mid_panic() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_with_no_drop() { +fn uninit_write_with_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = Bomb; - MaybeUninit::fill_with(&mut dst, || src.clone()); + dst.write_with(|_| src.clone()); forget(src); } #[test] -fn uninit_fill_from() { +fn uninit_write_iter() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 64]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src); assert_eq!(remainder.len(), 0); } #[test] -fn uninit_fill_from_partial() { +fn uninit_write_iter_partial() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 48]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src); assert_eq!(remainder.len(), 16); } #[test] -fn uninit_over_fill() { +fn uninit_write_iter_overfill() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 72]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src[0..64]); assert_eq!(remainder.len(), 0); } #[test] -fn uninit_empty_fill() { +fn uninit_write_iter_empty() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 0]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src[0..0]); assert_eq!(remainder.len(), 64); } #[test] #[cfg(panic = "unwind")] -fn uninit_fill_from_mid_panic() { +fn uninit_write_iter_mid_panic() { use std::panic; struct IterUntilPanic { @@ -504,7 +504,7 @@ fn uninit_fill_from_mid_panic() { let src = IterUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill_from(&mut dst, src); + dst.write_iter(src); })); match err { @@ -522,11 +522,11 @@ fn uninit_fill_from_mid_panic() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_from_no_drop() { +fn uninit_write_iter_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = [Bomb]; - MaybeUninit::fill_from(&mut dst, src.iter()); + dst.write_iter(src.iter()); forget(src); } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index cb3f864fd4e1e..3b66dbf40b6b5 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -7,7 +7,6 @@ use crate::fmt; use crate::io::{ self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; -use crate::mem::MaybeUninit; /// `Empty` ignores any data written via [`Write`], and will always be empty /// (returning zero bytes) when read via [`Read`]. @@ -196,7 +195,7 @@ impl Read for Repeat { #[inline] fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written. - MaybeUninit::fill(unsafe { buf.as_mut() }, self.byte); + unsafe { buf.as_mut() }.write_filled(self.byte); // SAFETY: the entire unfilled portion of buf has been initialized. unsafe { buf.advance_unchecked(buf.capacity()) }; Ok(())