-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Implement Manually Drop #40559
Implement Manually Drop #40559
Conversation
r? @brson (rust_highfive has picked a reviewer for you, use r? to override) |
src/libcore/mem.rs
Outdated
impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> { | ||
fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result { | ||
unsafe { | ||
fmt.debug_tuple("ManuallyDrop").field(&self.value).finish() |
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'd probably recommend just printing ManuallyDrop { .. }
here (but retain the T: Debug
bound) to be maximally conservative.
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.
Why? The data inside ManuallyDrop
is guaranteed to be valid, just like any other wrapper.
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 kind of disagree. Since the value can be logically uninhabited, I think we either need to state up front that this will access the inner value and cannot be called after drop
, or that it will not. While we could leave the door open to going from not printing to printing, that seems like something I would not be comfortable actually doing in practice.
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.
@gereeter Isn't the entire point of this type that that is not the case?
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.
@sfackler No - the point of this type is that it modifies the behavior on drop - instead of dropping the wrapped value, it just doesn't do anything. However, aside from behavior on drop, ManuallyDrop
has no implications on accessing the data.
This is why ManuallyDrop
implements Deref
and DerefMut
.
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.
~Every usage of ManuallyDrop
will involve calling ManuallyDrop::drop
at some point. It's then up to the developer to ensure that the inner value is never accessed past that call. If Debug
does not access that value, and then all of the sudden starts doing so, that seems bad.
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'm not so certain that most uses of ManuallyDrop
will involve calling ManuallyDrop::drop
. The one use I know of currently in the standard library, for example, never drops the contained value. Looking at the three commonly-downloaded users of nodrop
, arrayvec
doesn't drop the inside of the wrapper (since it only wants to drop some elements), quickersort
just replaces the elements instead of dropping them, and generic-array
doesn't drop the array inside NoDrop
because it, like arrayvec
, needs to only drop some of the elements.
That said, I completely agree that changing the behavior of Debug
is not a good idea. I just think there isn't a good reason to not print the contained value.
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.
ManuallyDrop::drop()
is unsafe with a warning that it is the responsibility of the user not to access the field after it is dropped. Is there a reason to look at Debug
as different from the other methods/traits provided by ManuallyDrop
which expect it's contents to be valid?
The user has already been warned about use-after-drop, I'd consider that enough to allow the default Debug impl for ManuallyDrop to remain useful (and print the value).
Cross linking rust-lang/rfcs#1860 |
src/libcore/mem.rs
Outdated
|
||
/// Extract the value from the ManuallyDrop container. | ||
#[unstable(feature = "manually_drop", issue = "0")] | ||
pub fn into_inner(self) -> 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.
This should be a static method.
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 belongs to the RFC.
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.
Yep, commented over there as well.
src/libcore/mem.rs
Outdated
/// } | ||
/// } | ||
/// ``` | ||
pub union ManuallyDrop<T>{ value: 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.
Union fields are private by default, right?
src/libcore/mem.rs
Outdated
impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> { | ||
fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result { | ||
unsafe { | ||
fmt.debug_tuple("ManuallyDrop").field(&self.value).finish() |
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 kind of disagree. Since the value can be logically uninhabited, I think we either need to state up front that this will access the inner value and cannot be called after drop
, or that it will not. While we could leave the door open to going from not printing to printing, that seems like something I would not be comfortable actually doing in practice.
src/libcore/mem.rs
Outdated
@@ -736,3 +736,99 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> { | |||
} | |||
} | |||
|
|||
|
|||
#[unstable(feature = "manually_drop", issue = "0")] |
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.
Nit: can you move these attributes below documentation? The established ordering convention is "docs, attributes, implementation".
Would it make sense to have another union field to "mark" the value as dropped? Something like:
Then a hypothetical "union sanitizer" could flag any future uses of (But of course that depends on future events or uncertainties, so may well not be worth doing now.) |
@rust-lang/libs thoughts on the It was brought up on the RFC that the likelihood of shadowing a legitimate method is very small because deref traits don't allow movement. @sfackler, however, brings up that trying to be clever here may mean it's just more difficult to understand in general. I personally am sympathetic to what @sfackler is saying and would lean a bit towards a static method instead of an inherent method myself at this point. |
src/libcore/mem.rs
Outdated
/// } | ||
/// } | ||
/// ``` | ||
pub union ManuallyDrop<T>{ value: 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.
Missing space before {
, and value
should likely be on its own line (although I don't mind it like this).
@scottmcm I believe that might actually be needed in some interpretations of |
Seems reasonable if this will help some future sanitizer. This is an implementation detail though and can be changed later.
|
☔ The latest upstream changes (presumably #40601) made this pull request unmergeable. Please resolve the merge conflicts. |
Good job getting rid of I see there is one more similar struct left, namely in |
Sure! |
Another random thought:
|
Intrinsic replaced. The PR has been open for a while. I haven’t seen any opinions on |
@nagisa want to switch to a static method instead of an inherent function? I'll r+ w/ that |
87a5096
to
4090a97
Compare
r=me, but I'd recommend squashing the commits as well Looks like travis is also failing? |
@nagisa looks like compile-fail/forget-init-unsafe.rs is using the intrinsic that 4f494c9 removed. |
23b8527
to
99f995b
Compare
☔ The latest upstream changes (presumably #41121) made this pull request unmergeable. Please resolve the merge conflicts. |
@bors: r+ |
📌 Commit c337b99 has been approved by |
⌛ Testing commit c337b99 with merge 5ad9e49... |
💔 Test failed - status-appveyor |
… On Tue, Apr 11, 2017 at 11:45 AM, bors ***@***.***> wrote:
💔 Test failed - status-appveyor
<https://ci.appveyor.com/project/rust-lang/rust/build/1.0.2882>
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#40559 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAD95KbmXsd4yUGPrfK0uvC0Uq7ma_S6ks5ru64SgaJpZM4MemKl>
.
|
Implement Manually Drop As the RFC has been from approx a week in FCP without any major comments, I’m taking the opportunity to submit the PR early.
Implement Manually Drop As the RFC has been from approx a week in FCP without any major comments, I’m taking the opportunity to submit the PR early.
☔ The latest upstream changes (presumably #41237) made this pull request unmergeable. Please resolve the merge conflicts. |
…xcrichton Add mem::forget_unsized() for forgetting unsized values ~~Allows passing values of `T: ?Sized` types to `mem::drop` and `mem::forget`.~~ Adds `mem::forget_unsized()` that accepts `T: ?Sized`. I had to revert the PR that removed the `forget` intrinsic and replaced it with `ManuallyDrop`: rust-lang#40559 We can't use `ManuallyDrop::new()` here because it needs `T: Sized` and we don't have support for unsized return values yet (will we ever?). r? @eddyb
…xcrichton Add mem::forget_unsized() for forgetting unsized values ~~Allows passing values of `T: ?Sized` types to `mem::drop` and `mem::forget`.~~ Adds `mem::forget_unsized()` that accepts `T: ?Sized`. I had to revert the PR that removed the `forget` intrinsic and replaced it with `ManuallyDrop`: rust-lang#40559 We can't use `ManuallyDrop::new()` here because it needs `T: Sized` and we don't have support for unsized return values yet (will we ever?). r? @eddyb
As the RFC has been from approx a week in FCP without any major comments, I’m taking the opportunity to submit the PR early.