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

Kill remaining uses of mem::uninitialized in libcore, liballoc #57045

Merged
merged 10 commits into from
Jan 29, 2019

Conversation

RalfJung
Copy link
Member

Kill remaining uses of mem::uninitialized in libcore and liballoc, and enable a lint that will warn when uses are added again in the future.

To avoid casting raw pointers around (which is always very dangerous because it is not typechecked at all -- it doesn't even get the "same size" sanity check that transmute gets), I also added two new functions to MaybeUninit:

    /// Get a pointer to the first contained values.
    pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
        this as *const [MaybeUninit<T>] as *const T
    }

    /// Get a mutable pointer to the first contained values.
    pub fn first_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
        this as *mut [MaybeUninit<T>] as *mut T
    }

I changed some of the existing code to use array-of-MaybeUninit instead of MaybeUninit-of-array, successfully removing raw pointer casts there as well.

@rust-highfive
Copy link
Collaborator

r? @bluss

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 21, 2018
@nagisa
Copy link
Member

nagisa commented Dec 21, 2018

I was surprised recently to find that MaybeUninit is still unstable. Perhaps it would be a good idea to first let it go stable before migrating the whole standard library to it?

@RalfJung
Copy link
Member Author

I think it makes a lot of sense to migrate more things to it to get some experience with the API before stabilizing.

// Creating a `[MaybeUninit; N]` array by first creating a
// `MaybeUninit<[MaybeUninit; N]>`; the `into_inner` is safe because the inner
// array does not require initialization.
keys: MaybeUninit::uninitialized().into_inner(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do I have a terrible feeling I'm going to be reading MaybeUninit::uninitialized().into_inner() everywhere rather than mem::uninitialized()...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to wrap it into a MaybeUninit::uninitialized_array() -> [MaybeUninit; #] static method that has the pre-copy as a doc-comment so as to remove the 7 times that exact comment is given? or is that (blocked by) what Centril meant by #49147 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mentioned above, this can be made safe once #49147 is stable. Once that happens, you can just write [MaybeUninit::uninitialized(), N] directly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fbstj You could make a fn cap_uninit_array<T>() -> [MaybeUninit<T>; N] function locally here for some specific Ns (e.g. CAPACITY) using the unsafe method but you need const generics to do it for all const N: usize. So waiting for #49147 seems better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do I have a terrible feeling I'm going to be reading MaybeUninit::uninitialized().into_inner() everywhere rather than mem::uninitialized()...

In my defense, that's not the only change here. ;)

The main problem is that we have pretty bad support for working with arrays, and arrays of MaybeUninit are no exceptions. If we had functions generic over array lengths, this all would be much easier.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah-- it's just that working with uninitialized arrays is my only current use of mem::uninitialized, and it used to use ManuallyDrop etc. but that route is now broken. Seeing this working-around of MaybeUninit's semantics makes me sad, but I understand it's a stepping-stone to the eventual goal.

@RalfJung
Copy link
Member Author

I have added a macro to create uninitialized arrays. Unfortunately it requires repeating the array length, but there will be a compile error if you use the wrong one. This removes all the new into_inner. Do you think that is an improvement?

@comex
Copy link
Contributor

comex commented Dec 22, 2018

It's too bad the names as_ptr and as_mut_ptr are already taken, since using them for this would be consistent with the correspondingly named methods on slices.

On the other hand, it's nice to be explicit.

@RalfJung
Copy link
Member Author

It's too bad the names as_ptr and as_mut_ptr are already taken, since using them for this would be consistent with the correspondingly named methods on slices.

I actually feel like the methods on the slice should have been called differently to contain something like first or begin. When writing this patch, it happened several times that existing code that sued to call as_mut_ptr on slices now called the same-named method on MaybeUninit, leading to rather strange type error messages.

But well, too late for any of that. What I'd really like to do is make these functions methods that take self, but I don't think that is possible.

@bors

This comment has been minimized.

@bors

This comment has been minimized.

@RalfJung
Copy link
Member Author

Rebased. However, stdsimd introduced some new uses of mem::zeroed into libcore...

@rust-highfive

This comment has been minimized.

@RalfJung
Copy link
Member Author

Updated stdsimd.

@RalfJung
Copy link
Member Author

RalfJung commented Jan 1, 2019

So, how do we proceed with this?

@bors
Copy link
Contributor

bors commented Jan 5, 2019

☔ The latest upstream changes (presumably #57354) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Jan 27, 2019

☔ The latest upstream changes (presumably #57765) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 28, 2019
@bors
Copy link
Contributor

bors commented Jan 28, 2019

⌛ Testing commit 6a52ca3 with merge acec5ebdc09eed0dc05329bcfea27749b48a4ee0...

@bors

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 28, 2019
@RalfJung
Copy link
Member Author

Fixed debug tests.

@bors r=SimonSapin

@bors
Copy link
Contributor

bors commented Jan 28, 2019

📌 Commit 489a792 has been approved by SimonSapin

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 28, 2019
@bors
Copy link
Contributor

bors commented Jan 28, 2019

⌛ Testing commit 489a792 with merge 8424c01...

bors added a commit that referenced this pull request Jan 28, 2019
Kill remaining uses of mem::uninitialized in libcore, liballoc

Kill remaining uses of mem::uninitialized in libcore and liballoc, and enable a lint that will warn when uses are added again in the future.

To avoid casting raw pointers around (which is always very dangerous because it is not typechecked at all -- it doesn't even get the "same size" sanity check that `transmute` gets), I also added two new functions to `MaybeUninit`:

```rust
    /// Get a pointer to the first contained values.
    pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
        this as *const [MaybeUninit<T>] as *const T
    }

    /// Get a mutable pointer to the first contained values.
    pub fn first_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
        this as *mut [MaybeUninit<T>] as *mut T
    }
```

I changed some of the existing code to use array-of-`MaybeUninit` instead of `MaybeUninit`-of-array, successfully removing raw pointer casts there as well.
@bors
Copy link
Contributor

bors commented Jan 28, 2019

💔 Test failed - checks-travis

@rust-highfive
Copy link
Collaborator

Your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 28, 2019
@Centril
Copy link
Contributor

Centril commented Jan 28, 2019

@bors retry

Seems spurious.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 28, 2019
Centril added a commit to Centril/rust that referenced this pull request Jan 28, 2019
…apin

Kill remaining uses of mem::uninitialized in libcore, liballoc

Kill remaining uses of mem::uninitialized in libcore and liballoc, and enable a lint that will warn when uses are added again in the future.

To avoid casting raw pointers around (which is always very dangerous because it is not typechecked at all -- it doesn't even get the "same size" sanity check that `transmute` gets), I also added two new functions to `MaybeUninit`:

```rust
    /// Get a pointer to the first contained values.
    pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
        this as *const [MaybeUninit<T>] as *const T
    }

    /// Get a mutable pointer to the first contained values.
    pub fn first_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
        this as *mut [MaybeUninit<T>] as *mut T
    }
```

I changed some of the existing code to use array-of-`MaybeUninit` instead of `MaybeUninit`-of-array, successfully removing raw pointer casts there as well.
bors added a commit that referenced this pull request Jan 29, 2019
Rollup of 7 pull requests

Successful merges:

 - #57045 (Kill remaining uses of mem::uninitialized in libcore, liballoc)
 - #57674 (Avoid erase_regions_ty queries if there are no regions to erase)
 - #57833 (Print a slightly clearer message when failing to launch a thread)
 - #57859 (Fix invalid background color)
 - #57904 (add typo suggestion to unknown attribute error)
 - #57915 (Pretty print `$crate` as `crate` or `crate_name` in more cases)
 - #57950 (Extend E0106, E0261)

Failed merges:

r? @ghost
@bors bors merged commit 489a792 into rust-lang:master Jan 29, 2019
@RalfJung RalfJung deleted the kill-more-uninit branch February 17, 2019 11:06
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 22, 2020
…Mark-Simulacrum

Test gdb pretty printing more and fix overzealous type substitution

Adresses a problem concerning printing BTreeMap / BTreeSet data in gdb: when the key or value type name contains substring "LeafNode", and the map has multiple nodes (e.g. more than 11 elements), printing causes an exception. E.g.

```
rustc -g - <<EOF
    use std::collections::BTreeMap;

    struct MyLeafNode(i8);

    fn main() {
        let m: BTreeMap<i8, MyLeafNode> = (0..12).map(|i| (i, MyLeafNode(i))).collect();
        assert!(!m.is_empty());
    }
EOF
```

```
$ rust-gdb rust_out
(gdb) b 7
(gdb) r
(gdb) p m
$1 = BTreeMap<i8, rust_out::MyLeafNode>(len: 12)Python Exception <class 'gdb.error'> No type named alloc::collections::btree::node::InternalNode<i8, rust_out::MyInternalNode>.:
use std::collections::BTreeMap;
```

The code was written in rust-lang#56144 by @tromey (and later touched upon by @RalfJung in rust-lang#57045, but I think that had nothing to do with the issues in this PR).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants