Skip to content

Commit bbdeb5f

Browse files
authored
clarify may_dangle docs
1 parent fc26bba commit bbdeb5f

File tree

1 file changed

+3
-15
lines changed

1 file changed

+3
-15
lines changed

src/libs/maintaining-std.md

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ Changes to collection internals may affect the order their items are dropped in.
189189

190190
A generic `Type<T>` that manually implements `Drop` should consider whether a `#[may_dangle]` attribute is appropriate on `T`. The [Nomicon][dropck] has some details on what `#[may_dangle]` is all about.
191191

192-
If a generic `Type<T>` has a manual drop implementation that may also involve dropping `T` then dropck needs to know about it. If `Type<T>`'s ownership of `T` is expressed indirectly through pointers, such as `*mut T` or `MaybeUninit<T>`, then `Type<T>` also [needs a `PhantomData<T>` field][RFC 0769 PhantomData] to tell dropck that `T` may be dropped. Types in the standard library that use the internal `Unique<T>` pointer type don't need a `PhantomData<T>` marker field. That's taken care of for them by `Unique<T>`.
192+
If a generic `Type<T>` has a manual drop implementation that may also involve dropping `T` then dropck needs to know about it. If `Type<T>`'s ownership of `T` is expressed through types that don't drop `T` themselves such as `ManuallyDrop<T>`, `*mut T`, or `MaybeUninit<T>` then `Type<T>` also [needs a `PhantomData<T>` field][RFC 0769 PhantomData] to tell dropck that `T` may be dropped. Types in the standard library that use the internal `Unique<T>` pointer type don't need a `PhantomData<T>` marker field. That's taken care of for them by `Unique<T>`.
193193

194194
As a real-world example of where this can go wrong, consider an `OptionCell<T>` that looks something like this:
195195

@@ -207,7 +207,7 @@ impl<T> Drop for OptionCell<T> {
207207
}
208208
```
209209

210-
Adding a `#[may_dangle]` attribute to this `OptionCell<T>` that didn't have a `PhantomData<T>` marker field opened up [a soundness hole][rust/issues/76367] for `T`'s that didn't strictly outlive the `OptionCell<T>`, and so could be accessed after being dropped in their own `Drop` implementations. The `OptionCell<T>` first needed a `PhantomData<T>` field:
210+
Adding a `#[may_dangle]` attribute to this `OptionCell<T>` that didn't have a `PhantomData<T>` marker field opened up [a soundness hole][rust/issues/76367] for `T`'s that didn't strictly outlive the `OptionCell<T>`, and so could be accessed after being dropped in their own `Drop` implementations. The correct application of `#[may_dangle]` also required a `PhantomData<T>` field:
211211

212212
```diff
213213
struct OptionCell<T> {
@@ -216,19 +216,7 @@ struct OptionCell<T> {
216216
+ _marker: PhantomData<T>,
217217
}
218218

219-
impl Drop<T> for OptionCell<T> {
220-
```
221-
222-
Then `#[may_dangle]` could be added to the `Drop` implementation:
223-
224-
```diff
225-
struct OptionCell<T> {
226-
is_init: bool,
227-
value: MaybeUninit<T>,
228-
_marker: PhantomData<T>,
229-
}
230-
231-
- impl Drop<T> for OptionCell<T> {
219+
- impl<T> Drop for OptionCell<T> {
232220
+ unsafe impl<#[may_dangle] T> Drop for OptionCell<T> {
233221
```
234222

0 commit comments

Comments
 (0)