Skip to content

Tracking issue for #![feature(maybe_uninit_slice)] #63569

Closed

Description

@Centril

View all comments

This is a tracking issue for the RFC "Deprecate uninitialized in favor of a new MaybeUninit type" (rust-lang/rfcs#1892).

Most of this has been stabilized, this issue now only tracks the below unstable methods.

Public API

impl<T> [MaybeUninit<T>] {
    pub unsafe fn assume_init_drop(&mut self);
    pub const unsafe fn assume_init_ref(&self) -> &[T];
    pub const unsafe fn assume_init_mut(&mut self) -> &mut [T];

    pub const fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T;
    pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T;
}

Steps / History

Unresolved Questions

Activity

  1. added
    T-libs-api[DEPRECATED; DO NOT USE]
    B-unstableBlocker: Implemented in the nightly compiler and unstable.
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    on Aug 14, 2019
  2. RalfJung commented on Aug 14, 2019

    @RalfJung
    Member

    Note: #63291 contains some APIs for creating uninitialized slices, but still does not have a good story for working with them, AFAIK.

    Cc @SimonSapin

  3. added 2 commits that reference this issue on Aug 14, 2019
  4. asomers commented on Sep 1, 2019

    @asomers
    Contributor

    I think another missing function is a way to create a slice of uninitialized data from a Vec. Like this:

    impl<'a, T> Vec<T> {
        pub fn as_uninit(&'a mut self) -> &'a mut [MaybeUninit<T>] {...}
    }

    Which would be used like this:

    let v = Vec::<u8>::with_capacity(100);
    let mut sl = v.as_uninit();
    if 0 != some_ffi_func(sl.first_ptr_mut(), sl.len()) {
        return Err<()>;
    } else {
        v.set_len(sl.len());
        return Ok(v);
    }

    There's no need for Vec::uninit() or Vec::assume_init(), because Vec::with_capacity and Vec::set_len already do pretty much the same thing. And for simple cases like this one Vec::as_mut_ptr() would suffice without the formality of creating a slice of MaybeUninits. However, the slice has the advantage that it knows its own length and it knows the lifetime of its data. The latter is especially useful when working with FFI functions that initialize the data asynchronously, such as aio_read.

  5. RalfJung commented on Sep 1, 2019

    @RalfJung
    Member

    Cc @Shnatsel see above -- seems related to rust-lang/rust-clippy#4483

  6. SimonSapin commented on Sep 2, 2019

    @SimonSapin
    Contributor

    @asomers I agree that something like this would be good to have. However your proposal seems ambiguous: does the returned slice include the entire allocation (indices 0..capacity) or only the range that is not known to be initialized (indices len..capacity)?

    Would an API that returns two disjoint (&mut [T], &mut [MaybeUninit<T>]) slices for indices 0..len and len..capacity also be useful?

  7. SimonSapin commented on Sep 2, 2019

    @SimonSapin
    Contributor

    Back to the APIs tracked in this issue, could they be methods of [MaybeUninit<T>] that take &self instead of associated functions of MaybeUninit<T>? (Though it’s not obvious what they should be called in that case.)

    We have precedent for a lang item for impl [u8] {…}

  8. asomers commented on Sep 3, 2019

    @asomers
    Contributor

    Good questions @SimonSapin. I think that the returned slice should include the entire allocation (after all, elements that are already initialized can still be represented as MaybeUninit. Also, I realized that the method I proposed isn't even good enough for my particular use case. I need a way to create an owned, maybe-uninitialized slice in a known memory location, and then transform that into an initialized vec. This is important for Tokio, whose asynchronous nature can thwart the borrow-checker.

    impl<T> Vec<MaybeUninit<T>> {
        /// Transmute this `Vec` of possibly uninitialized data into a normal `Vec`, assuming that the
        /// first `len` elements are properly initialized.
        pub unsafe fn assume_init(self, len: usize) -> Vec<T> {...}
    }
    /// I'm not 100% sure it's necessary, but define this for symmetry's sake:
    impl<T> Vec<T> {
        /// Transmute this `Vec` into a `Vec` of possibly uninitialized data whose length is equal to
        /// the original `Vec`'s capacity.
        pub fn into_uninit(self) -> Vec<MaybeUninit<T>> {...}
    }

    And it would be used like this:

    let v_uninit = Vec::<MaybeUninit<u8>>::with_capacity(1024);
    let result = some_ffi_func(v_uninit.as_mut_ptr(), v_uninit.capacity());
    match result {
        Ok(len) => Ok(v_uninit.assume_init(len)),
        Err(e) => Err(e)
    }

    Also, regarding the original methods, should the return type be Option<NonNull<T>>? That way they could return None for 0-length slices.

  9. SimonSapin commented on Sep 3, 2019

    @SimonSapin
    Contributor

    I need a way to create an owned, maybe-uninitialized slice in a known memory location

    That’s Box::new_uninit #63291

  10. Shnatsel commented on Sep 3, 2019

    @Shnatsel
    Member

    Why would you use Vec<MaybeUninit<T>>? Vec already encapsulates work with uninitialized memory - you can write to its capacity and then .set_len() to update the length. Or just use one of the myriad of methods that append to it safely.

  11. asomers commented on Sep 3, 2019

    @asomers
    Contributor

    @Shnatsel because I need something that owns uninitialized memory, unlike a *mut u8. I'm using aio_read, which asynchronously initializes the memory. There's no way for me to supply a &mut Vec reference to aio_read and persuade the borrow checker that the Vec will still be around by the time that the operation is complete (with notification delivered via kqueue). Making matters more complicated is the fact that my stack is 5 crates deep.

    Another option might be if [T] implemented BorrowMut<[MaybeUninit<T>]>. Then I think I could make things work.

  12. 52 remaining items

  13. rust-rfcbot commented on Nov 2, 2025

    @rust-rfcbot
    Collaborator

    The final comment period, with a disposition to merge, as per the review above, is now complete.

    As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

    This will be merged soon.

  14. added a commit that references this issue on Dec 1, 2025
  15. added a commit that references this issue on Dec 1, 2025
  16. added a commit that references this issue on Dec 1, 2025
  17. added this to the 1.93.0 milestone on Jan 8, 2026
  18. added a commit that references this issue on Jan 20, 2026
  19. added a commit that references this issue on Feb 2, 2026
  20. added
    I-libs-radarLibs issues that are tracked on the team's radar.
    and removed
    I-libs-radarLibs issues that are tracked on the team's radar.
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-raw-pointersArea: raw pointers, MaybeUninit, NonNullA-sliceArea: `[T]`B-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.T-libs-api[DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions