11use  crate :: ops:: { Deref ,  DerefMut ,  DerefPure } ; 
22use  crate :: ptr; 
33
4- /// A wrapper to inhibit the compiler from automatically calling `T`’s destructor.  
5- /// This wrapper is 0-cost. 
4+ /// A wrapper to inhibit the compiler from automatically calling `T`’s 
5+ /// destructor.  This wrapper is 0-cost. 
66/// 
77/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as 
8- /// `T`, and is subject to the same layout optimizations as `T`. As a consequence,  
9- /// it has *no effect* on the assumptions that the compiler makes about its  
10- /// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`]  
11- /// is undefined behavior. If you need to handle uninitialized data, use  
12- /// [`MaybeUninit<T>`] instead. 
8+ /// `T`, and is subject to the same layout optimizations as `T`. As a 
9+ /// consequence,  it has *no effect* on the assumptions that the compiler makes 
10+ /// about its  contents. For example, initializing a `ManuallyDrop<&mut T>` with 
11+ /// [`mem::zeroed`]  is undefined behavior. If you need to handle uninitialized 
12+ /// data, use  [`MaybeUninit<T>`] instead. 
1313/// 
14- /// Note that accessing the value inside a `ManuallyDrop<T>` is safe. 
15- /// This means that a `ManuallyDrop<T>` whose content has been dropped must not 
16- /// be exposed through a public safe API. 
17- /// Correspondingly, `ManuallyDrop::drop` is unsafe. 
14+ /// Note that accessing the value inside a `ManuallyDrop<T>` is safe. This means 
15+ /// that a `ManuallyDrop<T>` whose content has been dropped must not be exposed 
16+ /// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe. 
1817/// 
19- /// # `ManuallyDrop` and drop order.  
18+ /// # `ManuallyDrop` and drop order 
2019/// 
2120/// Rust has a well-defined [drop order] of values. To make sure that fields or 
2221/// locals are dropped in a specific order, reorder the declarations such that 
@@ -40,9 +39,116 @@ use crate::ptr;
4039/// } 
4140/// ``` 
4241/// 
42+ /// # Interaction with `Box` 
43+ /// 
44+ /// Currently, if you have a `ManuallyDrop<T>`, where the type `T` is a `Box` or 
45+ /// contains a `Box` inside, then dropping the `T` followed by moving the 
46+ /// `ManuallyDrop<T>` is [considered to be undefined 
47+ /// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245). 
48+ /// That is, the following code causes undefined behavior: 
49+ /// 
50+ /// ```no_run 
51+ /// use std::mem::ManuallyDrop; 
52+ /// 
53+ /// let mut x = ManuallyDrop::new(Box::new(42)); 
54+ /// unsafe { 
55+ ///     ManuallyDrop::drop(&mut x); 
56+ /// } 
57+ /// let y = x; // Undefined behavior! 
58+ /// ``` 
59+ /// 
60+ /// This is [likely to change in the 
61+ /// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the 
62+ /// meantime, consider using [`MaybeUninit`] instead. 
63+ /// 
64+ /// # Safety hazards when storing `ManuallyDrop` in a struct or an enum. 
65+ /// 
66+ /// Special care is needed when all of the conditions below are met: 
67+ /// * A struct or enum contains a `ManuallyDrop`. 
68+ /// * The `ManuallyDrop` is not inside a `union`. 
69+ /// * The struct or enum is part of public API, or is stored in a struct or an 
70+ ///   enum that is part of public API. 
71+ /// * There is code that drops the contents of the `ManuallyDrop` field, and 
72+ ///   this code is outside the struct or enum's `Drop` implementation. 
73+ /// 
74+ /// In particular, the following hazards may occur: 
75+ /// 
76+ /// #### Storing generic types 
77+ /// 
78+ /// If the `ManuallyDrop` contains a client-supplied generic type, the client 
79+ /// might provide a `Box` as that type. This would cause undefined behavior when 
80+ /// the struct or enum is later moved, as mentioned in the previous section. For 
81+ /// example, the following code causes undefined behavior: 
82+ /// 
83+ /// ```no_run 
84+ /// use std::mem::ManuallyDrop; 
85+ /// 
86+ /// pub struct BadOption<T> { 
87+ ///     // Invariant: Has been dropped iff `is_some` is false. 
88+ ///     value: ManuallyDrop<T>, 
89+ ///     is_some: bool, 
90+ /// } 
91+ /// impl<T> BadOption<T> { 
92+ ///     pub fn new(value: T) -> Self { 
93+ ///         Self { value: ManuallyDrop::new(value), is_some: true } 
94+ ///     } 
95+ ///     pub fn change_to_none(&mut self) { 
96+ ///         if self.is_some { 
97+ ///             self.is_some = false; 
98+ ///             unsafe { 
99+ ///                 // SAFETY: `value` hasn't been dropped yet, as per the invariant 
100+ ///                 // (This is actually unsound!) 
101+ ///                 ManuallyDrop::drop(&mut self.value); 
102+ ///             } 
103+ ///         } 
104+ ///     } 
105+ /// } 
106+ /// 
107+ /// // In another crate: 
108+ /// 
109+ /// let mut option = BadOption::new(Box::new(42)); 
110+ /// option.change_to_none(); 
111+ /// let option2 = option; // Undefined behavior! 
112+ /// ``` 
113+ /// 
114+ /// #### Deriving traits 
115+ /// 
116+ /// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on 
117+ /// the struct or enum could be unsound, since the derived implementations of 
118+ /// these traits would access the `ManuallyDrop` field. For example, the 
119+ /// following code causes undefined behavior: 
120+ /// 
121+ /// ```no_run 
122+ /// use std::mem::ManuallyDrop; 
123+ /// 
124+ /// // This derive is unsound in combination with the `ManuallyDrop::drop` call. 
125+ /// #[derive(Debug)] 
126+ /// pub struct Foo { 
127+ ///     value: ManuallyDrop<String>, 
128+ /// } 
129+ /// impl Foo { 
130+ ///     pub fn new() -> Self { 
131+ ///         let mut temp = Self { 
132+ ///             value: ManuallyDrop::new(String::from("Unsafe rust is hard.")) 
133+ ///         }; 
134+ ///         unsafe { 
135+ ///             // SAFETY: `value` hasn't been dropped yet. 
136+ ///             ManuallyDrop::drop(&mut temp.value); 
137+ ///         } 
138+ ///         temp 
139+ ///     } 
140+ /// } 
141+ /// 
142+ /// // In another crate: 
143+ /// 
144+ /// let foo = Foo::new(); 
145+ /// println!("{:?}", foo); // Undefined behavior! 
146+ /// ``` 
147+ /// 
43148/// [drop order]: https://doc.rust-lang.org/reference/destructors.html 
44149/// [`mem::zeroed`]: crate::mem::zeroed 
45150/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit 
151+ /// [`MaybeUninit`]: crate::mem::MaybeUninit 
46152#[ stable( feature = "manually_drop" ,  since = "1.20.0" ) ]  
47153#[ lang = "manually_drop" ]  
48154#[ derive( Copy ,  Clone ,  Debug ,  Default ,  PartialEq ,  Eq ,  PartialOrd ,  Ord ,  Hash ) ]  
0 commit comments