Summary

Include the ManuallyDrop wrapper in core::mem.

Motivation

Currently Rust does not specify

特定する、指定する、規定する
the order
順序
in which the destructors are run. Furthermore, this order
順序
differs depending on context.
文脈、背景
RFC issue #744 exposed the fact that the current, but unspecified
特定されていない
behaviour is relied onto for code validity and that there’s at least a few instances
実例
of such code in the wild.

While a move to stabilise and document

文書
the order
順序
of destructor evaluation
評価
would technically fix the problem described
記述する
above, there’s another important aspect to consider
考える、みなす
here implicitness. Consider
考える、みなす
such code:

#![allow(unused)] fn main() { struct FruitBox { peach: Peach, banana: Banana, } }

Does this structure depend on Peach’s destructor being run before Banana for correctness? Perhaps its the other way around and it is Banana’s destructor that has to run first? In the common case structures do not have any such dependencies

依存、依存関係
between fields, and therefore it is easy to overlook such a dependency
依存、依存関係
while changing the code above to the snippet
断片
below (e.g. so the fields are sorted by name).

#![allow(unused)] fn main() { struct FruitBox { banana: Banana, peach: Peach, } }

For structures with dependencies

依存、依存関係
between fields it is worthwhile to have ability to explicitly
明示的に
annotate the dependencies
依存、依存関係
somehow.

Detailed design
設計(する)

This RFC proposes adding

たす
the following struct as a new lang item to the core::mem (and by extension the std::mem) module. mem module is a most suitable place for such type, as the module already a place for functions very similar
似ている、同様の
in purpose: drop and forget.

#![allow(unused)] fn main() { /// Inhibits compiler from automatically calling `T`’s destructor. #[lang = "manually_drop"] #[unstable(feature = "manually_drop", reason = "recently added", issue = "0")] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ManuallyDrop<T> { value: T, } impl<T> ManuallyDrop<T> { /// Wraps a value to be manually dropped. #[unstable(feature = "manually_drop", reason = "recently added", issue = "0")] pub fn new(value: T) -> ManuallyDrop<T> { ManuallyDrop { value } } /// Extracts the value from the ManuallyDrop container. #[unstable(feature = "manually_drop", reason = "recently added", issue = "0")] pub fn into_inner(slot: ManuallyDrop<T>) -> T { slot.value } /// Manually drops the contained value. /// /// # Unsafety /// /// This function runs the destructor of the contained value and thus makes any further action /// with the value within invalid. The fact that this function does not consume the wrapper /// does not statically prevent further reuse. #[unstable(feature = "manually_drop", reason = "recently added", issue = "0")] pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { ptr::drop_in_place(&mut slot.value) } } impl<T> Deref for ManuallyDrop<T> { type Target = T; // ... } impl<T> DerefMut for ManuallyDrop<T> { // ... } }

The lang item will be treated

取り扱う
specially by the compiler to not emit any drop glue for this type.

Let us apply

適用する
ManuallyDrop to a somewhat expanded example from the motivation:

#![allow(unused)] fn main() { struct FruitBox { // Immediately clear there’s something non-trivial going on with these fields. peach: ManuallyDrop<Peach>, melon: Melon, // Field that’s independent of the other two. banana: ManuallyDrop<Banana>, } impl Drop for FruitBox { fn drop(&mut self) { unsafe { // Explicit ordering in which field destructors are run specified in the intuitive // location – the destructor of the structure containing the fields. // Moreover, one can now reorder fields within the struct however much they want. ManuallyDrop::drop(&mut self.peach); ManuallyDrop::drop(&mut self.banana); } // After destructor for `FruitBox` runs (this function), the destructor for Melon gets // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`. } } }

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

順序

How We Teach This

It is expected that the functions and wrapper added

たす
as a result
結果、戻り値
of this RFC would be seldom necessary.

In addition

追加
to the usual API documentation,
文書
ManuallyDrop should be mentioned in reference/nomicon/elsewhere as the solution to the desire of explicit
明示的な
control
制御する
of the order
順序
in which the structure fields gets dropped.

Alternatives
代わりのもの、選択肢

  • Stabilise some sort of drop order
    順序
    and make people to write code that’s hard to figure out at a glance;
  • Bikeshed colour;
  • Stabilise union and let people implement
    実装する
    this themselves:
    • Precludes (or makes it much harder) from recommending this pattern as the idiomatic way to implement
      実装する
      destructors with dependencies.
      依存、依存関係

Unresolved questions

None known.