Skip to content
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

Manually Drop #1860

Merged
merged 8 commits into from
Mar 20, 2017
Merged

Manually Drop #1860

merged 8 commits into from
Mar 20, 2017

Conversation

nagisa
Copy link
Member

@nagisa nagisa commented Jan 20, 2017

@KalitaAlexey
Copy link

@nagisa,
I like the idea.
I see that you don't propose to make the compiler emit an error if a struct has a manually dropped field but doesn't impl Drop.
I think that the compiler must emit an error.

@KalitaAlexey
Copy link

@nagisa,
You don't describe the situation where a struct has as a manually dropped field as a common one.

/// Inhibits compiler from automatically calling `T`’s destructor.
#[unstable(feature = "manually_drop", reason = "recently added", issue = "0")]
#[allow(missing_debug_implementations, unions_with_drop_fields)]
pub union ManuallyDrop<T>{ value: T }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You write adding following struct, but it is a union.

```rust
/// Inhibits compiler from automatically calling `T`’s destructor.
#[unstable(feature = "manually_drop", reason = "recently added", issue = "0")]
#[allow(missing_debug_implementations, unions_with_drop_fields)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should have impl Debug if T: Debug.

// Other common impls such as `Debug for T: Debug`.
```

Let us apply this structure to the example from the motivation:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace this structure with this union

@nagisa
Copy link
Member Author

nagisa commented Jan 20, 2017

I see that you don't propose to make the compiler emit an error if a struct has a manually dropped field but doesn't impl Drop. I think that the compiler must emit an error.

ManuallyDrop may also be used as a method to suppress the destructors, similar to the functionality provided by the nodrop crate. Automatic mem::forget. In that sense I disagree with compiler having to emit an error.

You don't describe the situation where a struct has as a manually dropped field as a common one.

What do you mean? I’d expect ManuallyDrop to be used quite rarely (for its intended purpose, anyway). I even said this in the “How we teach this” section:

It is expected that the functions and wrapper added as a result of this RFC would be seldom necessary.

That is, I believe that large majority of code does not care about the drop order.

@KalitaAlexey
Copy link

ManuallyDrop may also be used as a method to suppress the destructors, similar to the functionality provided by the nodrop crate. Automatic mem::forget. In that sense I disagree with compiler having to emit an error.

The one who needs to suppress the destructor can add #[allow] to the field.
It is better than people will get annoyed because of leaks.

What do you mean? I’d expect ManuallyDrop to be used quite rarely (for its intended purpose, anyway). I even said this in the “How we teach this” section:

struct FruitBox { 
    peach: ManuallyDrop<Peach>, 
    banana: ManuallyDrop<Banana>,
    other_fruit: OtherFruit,
} 

@aturon aturon added the T-lang Relevant to the language team, which will review and decide on the RFC. label Jan 23, 2017
[design]: #detailed-design

This RFC proposes adding following `struct` to the `core::mem` (and by extension the `std::mem`)
module. `mem` module is a most suitable place for such `struct`, as the module already a place for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems odd to call this a struct. Perhaps "type" instead?

@Ericson2314
Copy link
Contributor

Ericson2314 commented Jan 25, 2017

I feel like &move drop is far more elegant? Could we just do this on an experimental/temporary basis?

@KalitaAlexey
Copy link

@Ericson2314,
What are you talking about?

@Ericson2314
Copy link
Contributor

@KalitaAlexey Sorry, it's in a bunch of old RFCs scattered around.

@Ericson2314
Copy link
Contributor

Ericson2314 commented Jan 25, 2017

At random, here's newer #1646 and older https://internals.rust-lang.org/t/pre-rfc-allow-by-value-drop/1845

@@ -127,18 +127,18 @@ impl Drop for FruitBox {
}
```

It is proposed that such code would become idiomatic for structures where fields must be dropped in
a particular order.
It is proposed that such pattern would become idiomatic for structures where fields must be dropped
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps: "this pattern" instead of "such pattern"? Alternates would be "such patterns" and "such a pattern", but "this" seems more natural here.

@nagisa
Copy link
Member Author

nagisa commented Jan 25, 2017

I feel like &move drop is far more elegant? Could we just do this on an experimental/temporary basis?

&move is not possible to produce from a &mut, and we cannot change the signature of Drop::drop. If we had &move already, I’d be interested in discussing a MoveDrop::move_drop(&move self), but it does not exist yet. Stabilising unions and having something like this proposal as a crate also sounds okay to me, although it is awkward to recommend people to use a crate for what I propose to make the idiomatic (while we haven’t &move, at least) solution to the problem.

@aturon aturon added T-libs-api Relevant to the library API team, which will review and decide on the RFC. and removed T-lang Relevant to the language team, which will review and decide on the RFC. labels Jan 26, 2017
@joshtriplett joshtriplett added T-lang Relevant to the language team, which will review and decide on the RFC. and removed T-lang Relevant to the language team, which will review and decide on the RFC. labels Jan 26, 2017
@joshtriplett
Copy link
Member

Based on discussion in the lang team meeting: this is a libs RFC, not a lang RFC. Labeling accordingly.

@nagisa
Copy link
Member Author

nagisa commented Jan 27, 2017

I feel that its at least to some extent related to T-lang, even if the only relation is about the intent to consider ManuallyDrop the idiomatic approach.

@alexcrichton
Copy link
Member

I wonder, was perhaps a Deref and DerefMut implementation considered for this type? This seems like a swell type to have in libstd, and with deref we'd trim the API down to:

impl<T> ManuallyDrop<T> {
    pub fn new(T) -> Self;
    pub fn into_inner(self) -> T;
    pub unsafe fn manually_drop(slot: &mut ManuallyDrop<T>); // not inherent to avoid conflicts
}

impl<T> Deref for ManuallyDrop<T> {
    type Target = T;
}

impl<T> DerefMut for ManuallyDrop<T> {}

@SimonSapin
Copy link
Contributor

    pub fn into_inner(self) -> T;
    pub unsafe fn manually_drop(slot: &mut ManuallyDrop<T>); // not inherent to avoid conflicts

pub fn into_inner(ManuallyDrop<T>) -> T for the same reason?

@alexcrichton
Copy link
Member

@SimonSapin yeah I was initially going to recommend that, but I hesitated because almost all into_* methods consume self, so if you're reaching them through Deref you're by definition unable to call them. In that sense the reason we avoid inherent methods on Deref types, to avoid method conflicts, may not actually apply to the into_* terminology.

Although with that in mind it may be too clever, we have Box::into_raw, so it may be not worth it. Either way I'm fine.

@Ericson2314
Copy link
Contributor

Ericson2314 commented Feb 16, 2017

&move is not possible to produce from a &mut, and we cannot change the signature of Drop::drop.

These were never problems. It's easy to write a blanket impl from Old Drop to new Drop. Because new Drop grants the implementation a more powerful reference, plain old drop (the function) can be used---that solution is giving the callee more power, not requiring less of the caller as this does.

If we had &move already, I’d be interested in discussing a MoveDrop::move_drop(&move self), but it does not exist yet.

I think the reason we don't have &move is because people were insufficiently peeved with the problem this RFC duct-tapes. &move-Drop is, I'll wager, the only safe solution to the drop-from-drop instance problem. I was completely OK with the reasoning in #1646 (comment), but if this RFC is going to be accepted perhaps we should revisit some of the conclusions of insufficient motivation there.

Taking a step back, I'm fine with this as a stop-gap, especially if it remains unstable until further thinking about &move. I hope it increases the pressure for the more elegant and safe solution, but I fear it will decrease it instead.

@sfackler sfackler mentioned this pull request Feb 21, 2017
@alexcrichton
Copy link
Member

ping @BurntSushi (checkbox)

@alexcrichton
Copy link
Member

also ping @aturon

@rfcbot
Copy link
Collaborator

rfcbot commented Mar 9, 2017

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot added the final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. label Mar 9, 2017
// location – the destructor of the structure containing the fields.
// Moreover, one can now reorder fields within the struct however much they want.
peach.manually_drop();
banana.manually_drop();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be updated to ManuallyDrop::drop(...).

@oli-obk
Copy link
Contributor

oli-obk commented Mar 15, 2017

Is it valid to ptr::read from the deref of a ManualDrop to obtain an owned value in a Drop impl?

@nagisa
Copy link
Member Author

nagisa commented Mar 16, 2017 via email

@oli-obk
Copy link
Contributor

oli-obk commented Mar 16, 2017

OK. This is a use case I'd like to see mentioned in the docs and tests. Or even explicitly added as an unsafe take method?

@est31
Copy link
Member

est31 commented Mar 16, 2017

Cross linking rust-lang/rust#40559


/// Extracts the value from the ManuallyDrop container.
#[unstable(feature = "manually_drop", reason = "recently added", issue = "0")]
pub fn into_inner(self) -> T {
Copy link
Member

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 like drop.

@alexcrichton
Copy link
Member

@sfackler there's some discussion above about whether it's a free function or method, and the method was chosen because conventionally all into_* methods require self-by-value which is typically unusable through Deref and DerefMut

@sfackler
Copy link
Member

I was unfortunately not tuned in to the conversation at that point, oops :(

I feel somewhat strongly that it should be static - since we have an otherwise universal convention that smart pointer methods are static, if I see a foo.bar(), I can assume the bar is calling into the inner type. In addition, if/when we support DerefMove, an inner into_inner call could be made!

@alexcrichton
Copy link
Member

That's true yeah, I'd personally be fine either way

@rfcbot
Copy link
Collaborator

rfcbot commented Mar 19, 2017

The final comment period is now complete.

@alexcrichton
Copy link
Member

Looks like the main issue to arise during FCP is whether into_inner is an inherent method or not, but overall nothing much major arised so I'm going to merge! We can always tweak the implementation during stabilization and come back to tweak the RFC if necessary.

Thanks for the RFC @nagisa!

@alexcrichton alexcrichton merged commit 66e9f74 into rust-lang:master Mar 20, 2017
aturon added a commit that referenced this pull request Feb 14, 2018
@Centril Centril added A-drop Proposals relating to the Drop trait or drop semantics A-data-types RFCs about data-types A-machine Proposals relating to Rust's abstract machine. labels Nov 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-data-types RFCs about data-types A-drop Proposals relating to the Drop trait or drop semantics A-machine Proposals relating to Rust's abstract machine. final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.