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

Add MaybeUninit support #16

Merged
merged 3 commits into from
Oct 11, 2019
Merged

Add MaybeUninit support #16

merged 3 commits into from
Oct 11, 2019

Conversation

anna-is-cute
Copy link
Contributor

@anna-is-cute anna-is-cute commented Oct 8, 2019

Hello!

This PR adds use of MaybeUninit everywhere that mem::uninitialized was previously used.

The first commit does it in a breaking way, and the second commit only does it on Rust 1.36+, where MaybeUninit is stable, falling back on mem::uninitialized. I'll squash them, but I find it more readable to be able to see them separately for review purposes.

I'm not sure if I've done it 100% correctly, so I'd appreciate a review. It did require a large helping of #[cfg], but I'm not sure how else to handle it.

Tests all pass and benchmarks appear unaffected.

I have a few concerns:

  • I'm not handling the memory from MaybeUninit specially, meaning I'm not dropping it. I'm fairly certain that this is fine because it uses primitive types and doesn't allocate on the heap.
  • Is one byte always written after f.write_to_ryu_buffer? If so, no problem, but if not, this accesses uninitialised memory.

Thanks!

(Edit: Sorry for all the pushes. 1.15.0 won't update the registry on my laptop at home for some reason.)

@anna-is-cute
Copy link
Contributor Author

Okay, all CI builds and tests pass now. :) The 1.15.0 warning about use core::ptr; being unused is fun. It stops being unused in later Rusts (for example, at least by 1.35.0), so I'm not sure what to do about that guy.

Copy link
Owner

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

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

Thanks! Could you explain a bit about the motivation for this? Is there a concern about correctness of our use of mem::uninitialized, or is this more just because mem::uninitialized is deprecated now?

@anna-is-cute
Copy link
Contributor Author

Both!

  1. mem::uninitialized is deprecated and will eventually become a removed lang item, causing ryu to no longer compile, so this change will have to be made eventually, anyway.

  2. The docs for MaybeUninit state the following:

    The compiler, in general, assumes that variables are properly initialized at their respective type. For example, a variable of reference type must be aligned and non-NULL. This is an invariant that must always be upheld, even in unsafe code.

    Moreover, uninitialized memory is special in that the compiler knows that it does not have a fixed value. This makes it undefined behavior to have uninitialized data in a variable even if that variable has an integer type, which otherwise can hold any fixed bit pattern:

    (Notice that the rules around uninitialized integers are not finalized yet, but until they are, it is advisable to avoid them.)

    As I understand it from the above, it is UB to even initialise integer types using mem::uninitialized, which creating an array does.

@dtolnay
Copy link
Owner

dtolnay commented Oct 9, 2019

and will eventually become a removed lang item

Ah I didn't know about this. Could you share a link to where you found this?

@bjorn3
Copy link

bjorn3 commented Oct 9, 2019

Ah I didn't know about this. Could you share a link to where you found this?

It was attempted in rust-lang/rust#62150, and then backed out in rust-lang/rust#63343, as the new mem::uninitialized implementation was causing SIGILL.

@anna-is-cute
Copy link
Contributor Author

It was attempted in rust-lang/rust#62150, and then backed out in rust-lang/rust#63343, as the new mem::uninitialized implementation was causing SIGILL.

Those implement mem::uninitialized in terms of MaybeUninit, but they don't remove the deprecation. I could swear I read explicitly that mem::uninitialized would be removed, but maybe not. The function is deprecated, and that is the idea behind deprecating, though, is it not?

@dtolnay
Copy link
Owner

dtolnay commented Oct 9, 2019

No, in general we don't remove previously stable things from the standard library. Deprecation means there is something else you should probably use instead for new code, but existing code needs to continue to compile. Deprecation does not mean something is scheduled for removal.

@dtolnay dtolnay merged commit e076173 into dtolnay:master Oct 11, 2019
@anna-is-cute anna-is-cute deleted the maybe branch October 11, 2019 21:17
@dtolnay
Copy link
Owner

dtolnay commented Oct 11, 2019

Published in 1.0.1. 🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants