-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 {String,Vec}::into_raw_parts #65705
Conversation
r? @dtolnay (rust_highfive has picked a reviewer for you, use r? to override) |
d9c18de
to
16ff552
Compare
Your PR failed (pretty log, 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 |
16ff552
to
f6d0936
Compare
I believe I've addressed the first round of review comments, thanks! |
LGTM! But let's wait for someone from @rust-lang/libs to also take a look. |
What motivates this? Why is it needed or useful when |
Your PR failed (pretty log, 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 |
It's strikingly easy to get vec transmutation wrong. Just using the methods you listed in the wrong order is UB, for example. So this lets you correctly dismantle a Vec into the parts that you need to use with |
Personally I like this -- I always have the same sort of wonders as the things that Ralf was commenting about when I do this, and getting things back in the same order as |
Could you provide code examples that are UB with an explanation why? This is the same question as in rust-lang/rfcs#2756 (comment) about
I’m not entirely opposed to having this method. But it’s not obvious what problem(s) it solves, so I think it’s important to have those problems documented in details (ideally in the method’s doc-comment), so that that knowledge is not just in the collective mind of people who happen to have participated in a previous discussion. |
I... defer to @RalfJung to answer that one >_> I do not remember the details well enough to be confident in saying at all. |
@SimonSapin See rust-lang/rust-clippy#4484 and #64073 for some context. The only blessed way to "transmute" a The argument "why is this useful when you can already do this right now by calling 5 other functions in a row" would kill the vast majority of recent libstd additions...
|
It’s still not clear to me how exactly things can go wrong or what part would be UB. Again I’m not arguing against adding this method, only for proper documentation (not just in GitHub threads) of all those issues. |
See #62553 (comment) and #65705 (comment). |
The original case started in Deserialize a Vec<Foobar> as Vec directly when Foobar has exactly one field. There, I effectively did: struct FoobarContainer<T> {
values: Vec<T>,
}
#[repr(transparent)]
struct Foobar<T> {
value: T,
}
let input: Vec<Foobar<T>> = unimplemented!();
let output: Vec<T> = mem::transmute(input); Only by a whim of chance did I think to ask if that was safe and learned it was not (as That currently looks like: let mut v: Vec<Foobar<T>> = unimplemented!();
let values = unsafe {
let data = v.as_mut_ptr() as *mut T;
let len = v.len();
let cap = v.capacity();
std::mem::forget(v);
Vec::from_raw_parts(data, len, cap)
}; With this new feature, it can look like let v: Vec<Foobar<T>> = unimplemented!();
let values = unsafe {
let (data, len, cap) = v.into_raw_parts();
Vec::from_raw_parts(data as *mut T, len, cap)
}; That specific example is intended to be expressed in the example for
I agree with @RalfJung's points above
They are certainly motivated by similar concerns (I think the RFC may have even been opened due to the Clippy issue). I believe that there's some amount of benefit to both. If I understand it correctly, unsafe fn transmute<U>(self) -> Vec<U> {
let (ptr, len, cap) = self.into_raw_parts();
let ptr = mem::transmute::<*mut T, *mut U>(ptr);
Vec::from_raw_parts(ptr, len, cap)
} Then the original example would be let mut v: Vec<Foobar<T>> = unimplemented!();
let values: Vec<T> = unsafe { v.transmute() }; Thanks for trying to ensure high-quality for standard library functions! |
Alright. I’d like to accept this PR, with a tracking issue and some docs improvements:
I feel that something about this should maybe be part of the docs, but I’m not sure how to phrase it or if it really belongs there. @RalfJung what do you think? |
|
Is it worth adding an example of using the raw parts of the let ascii_case_difference = b'a' - b'A';
for idx in 0..len {
unsafe {
*ptr.add(idx) -= ascii_case_difference;
}
} But there's |
f6d0936
to
6600cf6
Compare
Should these functions be associated functions like |
Box does that to avoid deref conflicts, I don't think it's necessary here. |
Right, if
|
Looks good, thanks! @bors r+ |
📌 Commit 6600cf6 has been approved by |
Add {String,Vec}::into_raw_parts Aspects to address: - [x] Create a tracking issue - rust-lang#65816
Rollup of 7 pull requests Successful merges: - #63810 (Make <*const/mut T>::offset_from `const fn`) - #65705 (Add {String,Vec}::into_raw_parts) - #65749 (Insurance policy in case `iter.size_hint()` lies.) - #65799 (Fill tracking issue number for `array_value_iter`) - #65800 (self-profiling: Update measureme to 0.4.0 and remove non-RAII methods from profiler.) - #65806 (Add [T]::as_ptr_range() and [T]::as_mut_ptr_range().) - #65810 (SGX: Clear additional flag on enclave entry) Failed merges: r? @ghost
I was mostly asking for consistency between these conceptually similar ideas, not because of an intrinsic need. |
Add {String,Vec}::into_raw_parts Aspects to address: - [x] Create a tracking issue - rust-lang#65816
(That was re: avoiding |
Rollup of 6 pull requests Successful merges: - #65705 (Add {String,Vec}::into_raw_parts) - #65749 (Insurance policy in case `iter.size_hint()` lies.) - #65799 (Fill tracking issue number for `array_value_iter`) - #65800 (self-profiling: Update measureme to 0.4.0 and remove non-RAII methods from profiler.) - #65806 (Add [T]::as_ptr_range() and [T]::as_mut_ptr_range().) - #65810 (SGX: Clear additional flag on enclave entry) Failed merges: r? @ghost
Aspects to address:
vec_into_raw_parts
#65816