Conversation
src/libsyntax/ptr.rs
Outdated
There was a problem hiding this comment.
cc @RalfJung this is a clever trick I didn't consider!
There was a problem hiding this comment.
Yeah I think this should work. I don't like the raw ptr cast though, it's so easy to get those wrong -- but I also don't know another way here.
|
r=me if @RalfJung can confirm it's a correct approach |
|
Do you suggestions on alternatives to raw pointer cast? If not, I guess the code should be merged as-is. |
|
This might be a shot in the dark but would something like the following work (and deal with the FIXME): pub fn filter_map<F>(self, f: F) -> Option<P<T>> where
F: FnOnce(T) -> Option<T>,
{
unsafe {
// Transmute to `Box<MaybeUninit<T>>` so if `f` `panic`s or returns
// `None` the `Box` will be freed but not the inner T.
let mut maybe_box: Box<MaybeUninit<T>> = mem::transmute(self.ptr);
let x = f(ptr::read(maybe_box.as_ptr()))?;
maybe_box.set(x);
Some(P { ptr: mem::transmute(maybe_box) })
}
} |
|
I think @ollie27's suggestion is pretty good, any opinions/alternatives regarding the use of transmute? |
|
It seems to me that using |
|
@RalfJung the snippet above uses MaybeUninit::set. |
|
I guess this would work: pub fn filter_map<F>(self, f: F) -> Option<P<T>> where
F: FnOnce(T) -> Option<T>,
{
unsafe {
// Transmute to `Box<ManuallyDrop<T>>` so if `f` `panic`s or returns
// `None` the `Box` will be freed but not the inner T.
let mut manaully_drop_box: Box<ManuallyDrop<T>> = mem::transmute(self.ptr);
let x = f(ManuallyDrop::take(&mut manaully_drop_box))?;
*manaully_drop_box = ManuallyDrop::new(x);
Some(P { ptr: mem::transmute(manaully_drop_box) })
}
} |
|
Yeah, something like that. Either way though I think it'd be good to avoid "open" |
|
ping from triage @ishitatsuyuki @eddyb what's the update on this? |
|
r? @RalfJung |
|
@ishitatsuyuki could you update this to one of the proposed panic-safe schemes? If not I can r+ this, because it is an improvement, but the other version is even better. |
|
Actually I invented one that is drastically simpler, based on ManuallyDrop. The pains are with the |
|
Not sure if I like changing But it seems like some local private conversion functions between |
|
I spent some effort and wrote things again. Hopefully this is what you wanted. |
src/liballoc/boxed.rs
Outdated
There was a problem hiding this comment.
I meant local helper functions in the P module... this also works but now you have to create a tracking issue and add it here.
src/libsyntax/ptr.rs
Outdated
There was a problem hiding this comment.
Can you use into_inner instead of take?
There was a problem hiding this comment.
I don't think so, that would reallocate (or at least consume) the Box which defeats the point of P.
There was a problem hiding this comment.
It would move out of the box and then later move back into it, why would it reallocate? This code does not reallocate either.
There was a problem hiding this comment.
Oh wow. Box turns out to be even more magical than I realized. In this playground example shows that not only we can move a value out of Box without a DerefMove trait, but the compiler tracks such moves like for local variables and plain struct fields. Attempting to use the box before its contents are reassigned (if *x = … is removed) results in a compile time error[E0382]: use of moved value: `x` . But the box is still there and can be used again after its contents are reassigned.
And this is panic-safe too. In the assembly for https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=d4907435865f18159268fc36a8546016 we see that foo calls box_free but not drop_t.
So I think @RalfJung’s suggestion is the way to go.
There was a problem hiding this comment.
Bonus possibly-unexpected detail:
Lines 290 to 295 in f22dca0
There was a problem hiding this comment.
Wow, I was aware of Box special-casing, but I do not recall being able to reinitialize the Box and reuse it!
@nikomatsakis @pnkfelix Do you happen to know when that might've happened?
There was a problem hiding this comment.
I believe this probably happened as part of the NLL transition. We decided to stop hobbling the treatment of Box during that discussion.
|
I will do the tracking issue thing tomorrow. |
|
@rust-lang/libs any advise on how to proceed here -- should we add two new unstable methods with a tracking issue, or instead add two local private helper functions in |
|
Per #58021 (comment) it looks like the one use case for those methods can be solved with plain |
|
I hadn't even thought so far, but you are right... this proper move tracking for boxes entirely sidesteps the need for |
|
(Short on time this week, will update this weekend) |
|
☀️ Test successful - checks-travis, status-appveyor |
|
Discussed in this week's T-compiler meeting. Approved for beta-backport. (In parallel, @pnkfelix wants to make a regression test. But than need not hold up the backport.) |
I was careless and misread the patch, thinking that this was some |
[beta] Rollup backports Cherry-picked: * #58021: Fix fallout from #57667 * #59599: Updated RELEASES.md for 1.34.0 * #59587: Remove #[doc(hidden)] from Error::type_id * #58994: Hide deprecation warnings inside derive expansions * #58015: Expand docs for `TryFrom` and `TryInto`. * #59770: ci: pin android emulator to 28.0.23 * #59704: ci: Update FreeBSD tarball downloads * #59257: Update CI configuration for building Redox libraries * #59724: Function arguments should never get promoted r? @ghost
[beta] Rollup backports Cherry-picked: * #58021: Fix fallout from #57667 * #59599: Updated RELEASES.md for 1.34.0 * #59587: Remove #[doc(hidden)] from Error::type_id * #58994: Hide deprecation warnings inside derive expansions * #58015: Expand docs for `TryFrom` and `TryInto`. * #59770: ci: pin android emulator to 28.0.23 * #59704: ci: Update FreeBSD tarball downloads * #59257: Update CI configuration for building Redox libraries * #59724: Function arguments should never get promoted * #59499: Fix broken download link in the armhf-gnu image * #58330: Add rustdoc JS non-std tests * #58848: Prevent cache issues on version updates r? @ghost
PR #57667 fixed a memory leak in
P::filter_map(wherePis the special pointer type used in the compiler's AST).but @eddyb pointed out a bug in it: #57667 (comment)