-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Deprecate Read::initializer in favor of ptr::freeze #58363
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
Changes from 3 commits
5e0fb23
c21e79e
e4d316e
73133ee
1671e90
0529921
695feb1
9d4f07e
055bcb6
78e2233
ec682d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -946,6 +946,58 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { | |||||
intrinsics::volatile_store(dst, src); | ||||||
} | ||||||
|
||||||
/// Freezes `count * size_of::<T>()` bytes of memory, converting undefined data into | ||||||
/// arbitrary but fixed data. | ||||||
sfackler marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
/// | ||||||
/// Uninitialized memory has undefined contents, and interation with that data | ||||||
/// can easily cause undefined behavior. This function "freezes" memory | ||||||
/// contents, converting uninitialized memory to initialized memory with | ||||||
/// arbitrary contents so that use of it is well defined. | ||||||
/// | ||||||
/// This function has no runtime effect; it is purely an instruction to the | ||||||
/// compiler. In particular, it does not actually write anything to the memory. | ||||||
|
||||||
/// | ||||||
/// # Safety | ||||||
/// | ||||||
/// Behavior is undefined if any of the following conditions are violated: | ||||||
/// | ||||||
/// * `dst` must be [valid] for writes. | ||||||
/// | ||||||
/// * Every bit representation of `T` must be a valid value. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is that a precondition to
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought that what you meant in this comment: #58363 (comment). If the validity requirements are less strict I can move this to be a more general warning about use of the function rather than a hard UB constraint. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The phrasing here seems congruent with the behavior of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The validity requirements come in once you actually operate on or a make a copy of a value at some type. So the following is UB: let x = MaybeUninit::<bool>::uninitialized();
ptr::freeze(x.as_mut_ptr());
let x = x.into_initialized(); // UB But it's not the freeze that is UB, it's the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RalfJung Oh... you're talking about |
||||||
/// | ||||||
/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this formulation is used consistently throughout this file, so I'd prefer that if it gets changed that happens in a separate PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah; that's a good idea; I'll see if I can remember to make such a PR... :) |
||||||
/// | ||||||
/// [valid]: ../ptr/index.html#safety | ||||||
/// | ||||||
/// # Examples | ||||||
/// | ||||||
/// ```ignore (io-is-in-std) | ||||||
/// use std::io::{self, Read}; | ||||||
/// use std::mem; | ||||||
/// use std::ptr; | ||||||
/// | ||||||
/// pub fn read_le_u32<R>(reader: &mut R) -> io::Result<u32> | ||||||
/// where | ||||||
/// R: Read, | ||||||
/// { | ||||||
/// unsafe { | ||||||
/// // We're passing this buffer to an arbitrary reader and aren't | ||||||
/// // guaranteed they won't read from it, so freeze to avoid UB. | ||||||
/// let mut buf: [u8; 4] = mem::uninitialized(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a FIXME somewhere about porting this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (This is still open, from what I can see) |
||||||
/// ptr::freeze(&mut buf, 1); | ||||||
|
||||||
/// reader.read_exact(&mut buf)?; | ||||||
/// | ||||||
/// Ok(u32::from_le_bytes(buf)) | ||||||
/// } | ||||||
/// } | ||||||
/// ``` | ||||||
#[inline] | ||||||
#[unstable(feature = "ptr_freeze", issue = "0")] | ||||||
pub unsafe fn freeze<T>(dst: *mut T, count: usize) { | ||||||
|
||||||
let _ = count; | ||||||
asm!("" : "=*m"(dst) : ); | ||||||
|
||||||
} | ||||||
|
||||||
#[lang = "const_ptr"] | ||||||
impl<T: ?Sized> *const T { | ||||||
/// Returns `true` if the pointer is null. | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the first time we talk about this kind of data in the docs. I usually call it "uninitialized data" as I feel that is easier to understand. It also is further away from LLVM's
undef
, which is good -- Rust's "uninitialized data" is much more likepoision
thanundef
.