-
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 support for in-place map for Vec
s of types with same size (take 3)
#16853
Conversation
|
||
let start = vec.as_mut_ptr(); | ||
|
||
// This `as int` cast is safe, because the size of the elements of the |
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.
This justification isn't actually required, since this is how offset
is designed to work. :)
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.
How is offset
designed to work?
Actually I'm not even sure what I'm doing is correct, because the docs on ptr::offset
say that the given offset must be inbound, which negative ones technically aren't.
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.
Oh, really? So the following is technically undefined?
let p = some_vec.as_ptr();
let q = p.offset(10);
let r = q.offset(-10);
However, it doesn't particularly matter since offset
is widely used with the output of len()
; this is not an unusual case (e.g. some_slice.iter()
is created with offset
and len
).
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.
@huonw: No, that q.offset(-10)
is perfectly well defined if p.offset(10)
was correct. It's within the bounds of the object it was based on.
I think this is a lot more complicated than it needs to be, even with failure safety in mind. |
@thestinger What specifically? I had the impression that I did pretty much the minimum required to get this running. |
/// | ||
/// Removes the next `T` from the vector and returns it as `Some(T)`, or | ||
/// `None` if there are none left. | ||
fn pop(&mut self) -> Option<T> { |
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.
Is this intentionally private?
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.
No, this should be public.
@tbu- Can you elaborate on the use case you have in mind here? I'm guessing the intent is just to support the |
To elaborate slightly, it seems like the interface here effectively forces you to do something like your If |
/// ]); | ||
/// assert_eq!(u8s.as_slice(), &[[0x11, 0x22], [0x33, 0x44]]); | ||
/// ``` | ||
pub fn map_inplace<U>(self, f: |T| -> U) -> Vec<U> { |
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.
Minor detail, but why not map_in_place
?
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 don't know, it felt more natural to me, maybe because map_in_place
sounds less like a hyphen between "in" and "place". But I have absolutely no problem in renaming this if you want it.
About the public interface: I don't know anymore why the However I am not sure putting less code in |
@tbu- There is some amount of extra assertion checking, API documentation, and extra generality in the As far as interleaving safe and unsafe code, I think most of That said, I wouldn't block the PR on the basis of these preferences; my main concern is to hide I would vote for |
@aturon I renamed it to When you finish reviewing it, please tell me so I can rebase it to master. |
} | ||
} | ||
|
||
impl<T,U> Iterator<T> for PartialVec<T,U> { |
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.
Either the map_in_place
method should use this iterator, or it should be dropped (as dead code).
@tbu- Looks good to me. One minor point: now that the This would expand the use of In any case, I'm happy to r+ as-is, after a rebase; we can always tweak things later. Thanks for doing this work! |
@aturon I rebased it. Will continue to improve it based on your "optional" comments once this one lands. |
@tbu- Okay, headed to bors. Thanks for your persistence on this one! |
@aturon Thanks for reviewing it. Can you issue a retry? It's just a |
This is implemented using a new struct `PartialVec` which implements the proper drop semantics in case the conversion is interrupted by an unwind.
This specifically includes: - Fix of the tests - Remove `transmute` between `Vec`s of different types
This is important because the underlying allocator of the `Vec` passes that information to the deallocator which needs the guarantee that it is the same parameters that were also passed to the allocation function.
This replaces the now obsolete syntax `&[]` with `[].as_slice()`.
I'm sorry for the failed build, I didn't update the tests when I rebased it to the master. Now I fixed the tests, ran |
This is implemented using a new struct PartialVec which implements the proper
drop semantics in case the conversion is interrupted by an unwind.
For the old pull requests, see #15302, #16369.