add safety sections for three functions in core::mem#154665
add safety sections for three functions in core::mem#154665hxuhack wants to merge 1 commit intorust-lang:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves the API documentation for unsafe/legacy core::mem APIs by adding explicit # Safety sections, helping users understand the invariants required to call these functions soundly.
Changes:
- Added a
# Safetysection tomem::zeroeddescribing the “all-zero must be valid forT” requirement. - Added a
# Safetysection to deprecatedmem::uninitializedto discourage use. - Added a
# Safetysection tomem::transmute_copylisting key caller obligations.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
These safety sections are duplicating what is already said below. They also cause text that was previously not part of any section to be part of the safety section. Also would you mind disabling the option to automatically request copilot reviews in your user settings? These copilot reviews are still shown to people like me who have disabled every copilot related option that github offers. |
|
@bjorn3 I wasn't aware that Copilot had permission to provide automatic reviews for this repository. I have disabled it now. Sorry about that.
|
This comment has been minimized.
This comment has been minimized.
In the first commit, I tried to preserve the original text, although I also noticed the duplication.
I have reorganized the Safety section so that all text before the Example section is now relevant to safety. Does this version work for you? |
|
The case about |
|
As you mentioned on zulip, it seems incorrect to state that
for What would you suggest should be documented here instead as the precondition? |
|
You seem to have misunderstood what I said. "Rust's aliasing rules" refers to two different things, depending on context:
This is the same dichotomy as in my old blog post. It is a fundamental aspect of working with unsafe Rust that your model and PR do not seem to properly capture. |
|
Ok, thanks, Ralf, for the clarification. This operates at the type-system level. |
library/core/src/mem/mod.rs
Outdated
| /// | ||
| /// # Safety | ||
| /// | ||
| /// Do not use; reserved for legacy code only. |
There was a problem hiding this comment.
I don't think this should be in a safety section. The function is already deprecated (signaling it shouldn't be used).
The safety requirement here is ultimately equivalent to MaybeUninit::assume_init's, everything else here is describing that being hard to ensure without the 'initialization' phase MaybeUninit provides.
There was a problem hiding this comment.
They are different.
mem::uninitialized directly produces an invalid value, which leads to language-level UB. For example, if the value implements Drop and the program panics after creating it, the program may end up with a dropping uninitialised value during unwinding, which is UB. That is why this API has been deprecated.
MaybeUninit::assume_init is different. You can create a value of type MaybeUninit<T>, initialize it step by step, and finally call MaybeUninit::assume_init. This approach is safe even if T implements Drop and the program panics at any point during initialization.
There are many issues in the past, e.g., CVE-2019-15552, CVE-2019-15553.
That's why the doc of mem::uninitialized says "The reason for deprecation is that the function basically cannot be used correctly"
There was a problem hiding this comment.
I'm not disputing that it's much harder to use mem::uninitialized correctly. But ultimately the conditions on calling MaybeUninit::assume_init and mem::uninitialized are exactly the same: the returned value must be a valid value at the type. It's just that with mem::uninitialized you don't have an opportunity to do anything before hand, so most usage can't be correct.
There was a problem hiding this comment.
Do you think we should add a Safety section here? If you don’t have a strong preference either way, then perhaps it would be reasonable to add one? One extra benefit is that Clippy already supports checking for missing safety documentation via the missing_safety_doc lint. So adding a Safety section would also align with Clippy’s expectations well.
There was a problem hiding this comment.
I think a Safety section is a good idea. But I don't think a Safety section should say "reserved for legacy code only", that doesn't seem appropriate. If you left this section to cover the actual safety requirement (discussed somewhat below after the newly added line), that seems fine to me.
There was a problem hiding this comment.
To avoid duplication, I moved the last sentence of the original doc to the Safety section.
/// # Safety
///
/// It is immediate undefined behavior to call this function on nearly all types,
/// including integer types and arrays of integer types, and even if the result is unused.
Does this look good to you?
library/core/src/mem/mod.rs
Outdated
| /// * [`size_of::<Src>`][size_of] must be greater than or equal to [`size_of::<Dst>`][size_of]. | ||
| /// It is not a compile-time error if `Src` and `Dst` have different sizes, but it | ||
| /// is highly encouraged to only invoke this function where `Src` and `Dst` have the | ||
| /// same size. |
There was a problem hiding this comment.
This feels confusing to me. Half the point of using transmute_copy is when the two types don't have the same size (or at least not provably so to the compiler) -- otherwise you could just transmute in most cases.
I'm wondering if this should just defer to the Safety documentation of read_unaligned, which is what this boils down to AFAICT.
There was a problem hiding this comment.
This feels confusing to me. Half the point of using transmute_copy is when the two types don't have the same size (or at least not provably so to the compiler) -- otherwise you could just transmute in most cases.
I copied this sentence from the original documentation without modification, although I also find it odd that it highlights “highly encouraged to only invoke this function where Src and Dst have the same size.” I think we should remove this sentence.
There was a problem hiding this comment.
I also considered referring to the safety requirements of the callee, read_unaligned. However, I give up the choice for three reasons:
- The current safety requirements documented for
read_unalignedfocus on pointer validity, which is not a concern for this function.. - This function has an additional requirement regarding the sizes of
SrcandDst. - The current description of the library-level UB that may be introduced by
read_unalignedis misleading. It states that it is unsafe ifTis notCopy, which makes readers falsely think it would be safe if itTisCopy, as discussed in zulip.
There was a problem hiding this comment.
This function has an additional requirement regarding the sizes of Src and Dst.
I don't think this function has any additional safety requirement on those sizes? The requirement seems essentially the same to me: you must be able to read an value of size Dst from &Src.
There was a problem hiding this comment.
Oh, right. There is already an assertion in the implementation, so it will panic instead of causing UB in this case.
rust/library/core/src/mem/mod.rs
Lines 1072 to 1076 in 5f36a7f
There was a problem hiding this comment.
I’ve updated the documentation by removing the size requirement from the Safety section and instead adding a note about the panic behavior right after the API description:
The function will panic if [
size_of::<Src>][size_of] is less than [size_of::<Dst>][size_of].
|
Reminder, once the PR becomes ready for a review, use |
|
@rustbot ready |
View all comments
This pull request adds Safety sections for three library APIs in the
core::memmodule:mem::uninitializedmem::zeroedmem::transmute_copyr? @Mark-Simulacrum