Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 10 pull requests #122031

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
313eb8f
Implement MaybeUninit::fill{,_with,_from}
ajwock Feb 18, 2024
3908a93
std support for wasm32 panic=unwind
coolreader18 Feb 21, 2024
861c7e7
Fix llvm hang
coolreader18 Feb 22, 2024
658a0a2
Unconditionally pass -wasm-enable-eh
coolreader18 Feb 22, 2024
125b26a
Use Itanium ABI for thrown exceptions
coolreader18 Feb 22, 2024
c7fcf43
Don't codegen wasm.throw unless with -Zbuild-std
coolreader18 Feb 26, 2024
a5245ef
Hint user to update nightly on ICEs produced from outdated nightly
jieyouxu Feb 27, 2024
a0ca9b1
Don't suggest update nightly if using internal features
jieyouxu Feb 27, 2024
9c963fc
Adjust wording
jieyouxu Feb 27, 2024
a9a9798
Removing absolute path in proc-macro
sundeep-kokkonda Mar 4, 2024
6e9f59f
add test for #78894
surechen Mar 4, 2024
4e03c51
hir_analysis: enums return `None` in `find_field`
davidtwco Mar 4, 2024
640e99c
Fix duplicated path in the "not found dylib" error
GuillaumeGomez Mar 4, 2024
5e6e140
Add regression ui test for duplicated path in dylib error
GuillaumeGomez Mar 4, 2024
523ab25
add test for #71450
surechen Mar 4, 2024
960dd38
will_wake tests fail on Miri and that is expected
RalfJung Mar 5, 2024
f391c07
only set noalias on Box with the global allocator
RalfJung Mar 5, 2024
da35734
Merge `impl_trait_in_assoc_types_defined_by` query back into `opaque_…
oli-obk Mar 4, 2024
955a160
Rollup merge of #121280 - ajwock:maybeuninit_fill, r=Amanieu
matthiaskrgr Mar 5, 2024
73ab3c7
Rollup merge of #121438 - coolreader18:wasm32-panic-unwind, r=cuviper
matthiaskrgr Mar 5, 2024
e788f15
Rollup merge of #121658 - jieyouxu:ice-outdated-nightly, r=oli-obk
matthiaskrgr Mar 5, 2024
5b4f049
Rollup merge of #121959 - sundeep-kokkonda:patch-2, r=davidtwco
matthiaskrgr Mar 5, 2024
8676983
Rollup merge of #121961 - surechen:add_test_20240304, r=petrochenkov
matthiaskrgr Mar 5, 2024
b7a60d8
Rollup merge of #121975 - davidtwco:issue-121757, r=petrochenkov
matthiaskrgr Mar 5, 2024
d08dcea
Rollup merge of #121978 - GuillaumeGomez:dylib-duplicated-path, r=bjorn3
matthiaskrgr Mar 5, 2024
9e3f983
Rollup merge of #121991 - oli-obk:merge_opaque_types_defined_by_queri…
matthiaskrgr Mar 5, 2024
62aed06
Rollup merge of #122016 - RalfJung:will_wake, r=dtolnay
matthiaskrgr Mar 5, 2024
8834019
Rollup merge of #122018 - RalfJung:box-custom-alloc, r=oli-obk
matthiaskrgr Mar 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 186 additions & 16 deletions library/core/src/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,22 +1125,6 @@ impl<T> MaybeUninit<T> {
// unlike copy_from_slice this does not call clone_from_slice on the slice
// this is because `MaybeUninit<T: Clone>` does not implement Clone.

struct Guard<'a, T> {
slice: &'a mut [MaybeUninit<T>],
initialized: usize,
}

impl<'a, T> Drop for Guard<'a, T> {
fn drop(&mut self) {
let initialized_part = &mut self.slice[..self.initialized];
// SAFETY: this raw slice will contain only initialized objects
// that's why, it is allowed to drop it.
unsafe {
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part));
}
}
}

assert_eq!(this.len(), src.len(), "destination and source slices have different lengths");
// NOTE: We need to explicitly slice them to the same length
// for bounds checking to be elided, and the optimizer will
Expand All @@ -1162,6 +1146,151 @@ impl<T> MaybeUninit<T> {
unsafe { MaybeUninit::slice_assume_init_mut(this) }
}

/// Fills `this` with elements by cloning `value`, returning a mutable reference to the now
/// initialized contents of `this`.
/// 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
///
/// Fill an uninit vec with 1.
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// let mut buf = vec![MaybeUninit::uninit(); 10];
/// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1);
/// assert_eq!(initialized, &mut [1; 10]);
/// ```
#[doc(alias = "memset")]
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], 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 { MaybeUninit::slice_assume_init_mut(this) }
}

/// Fills `this` 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
///
/// Fill an uninit vec with the default value.
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// let mut buf = vec![MaybeUninit::<i32>::uninit(); 10];
/// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default);
/// assert_eq!(initialized, &mut [0; 10]);
/// ```
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], 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 { MaybeUninit::slice_assume_init_mut(this) }
}

/// Fills `this` 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
///
/// Fill an uninit vec with a cycling iterator.
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// let mut buf = vec![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!(0, remainder.len());
/// ```
///
/// Fill an uninit vec, but not completely.
/// ```
/// #![feature(maybe_uninit_fill)]
/// use std::mem::MaybeUninit;
///
/// let mut buf = vec![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);
/// ```
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
pub fn fill_from<'a, I>(
this: &'a mut [MaybeUninit<T>],
it: I,
) -> (&'a mut [T], &'a mut [MaybeUninit<T>])
where
I: IntoIterator<Item = T>,
{
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 { MaybeUninit::slice_assume_init_mut(initted) }, 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
Expand Down Expand Up @@ -1315,3 +1444,44 @@ impl<T, const N: usize> [MaybeUninit<T>; N] {
unsafe { intrinsics::transmute_unchecked(self) }
}
}

struct Guard<'a, T> {
slice: &'a mut [MaybeUninit<T>],
initialized: usize,
}

impl<'a, T> Drop for Guard<'a, T> {
fn drop(&mut self) {
let initialized_part = &mut self.slice[..self.initialized];
// SAFETY: this raw sub-slice will contain only initialized objects.
unsafe {
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part));
}
}
}

trait SpecFill<T> {
fn spec_fill(&mut self, value: T);
}

impl<T: Clone> SpecFill<T> for [MaybeUninit<T>] {
default fn spec_fill(&mut self, value: T) {
let mut guard = Guard { slice: self, initialized: 0 };

if let Some((last, elems)) = guard.slice.split_last_mut() {
for el in elems {
el.write(value.clone());
guard.initialized += 1;
}

last.write(value);
}
super::forget(guard);
}
}

impl<T: Copy> SpecFill<T> for [MaybeUninit<T>] {
fn spec_fill(&mut self, value: T) {
self.fill(MaybeUninit::new(value));
}
}
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#![feature(slice_from_ptr_range)]
#![feature(slice_split_once)]
#![feature(split_as_slice)]
#![feature(maybe_uninit_fill)]
#![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_write_slice)]
#![feature(maybe_uninit_uninit_array_transpose)]
Expand Down
Loading