-
Notifications
You must be signed in to change notification settings - Fork 13.4k
PhantomData: fix documentation wrt interaction with dropck #103413
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
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -132,6 +132,74 @@ | |||||||||
/// are `Copy` get implicitly duplicated by the compiler, making it very | ||||||||||
/// hard to predict when, and how often destructors will be executed. As such, | ||||||||||
/// these types cannot have destructors. | ||||||||||
/// | ||||||||||
/// ## Drop check | ||||||||||
/// | ||||||||||
/// Dropping interacts with the borrow checker in subtle ways: when a type `T` is being implicitly | ||||||||||
/// dropped as some variable of this type goes out of scope, the borrow checker needs to ensure that | ||||||||||
/// calling `T`'s destructor at this moment is safe. In particular, it also needs to be safe to | ||||||||||
/// recursively drop all the fields of `T`. For example, it is crucial that code like the following | ||||||||||
/// is being rejected: | ||||||||||
/// | ||||||||||
/// ```compile_fail,E0597 | ||||||||||
/// use std::cell::Cell; | ||||||||||
/// | ||||||||||
/// struct S<'a>(Cell<Option<&'a S<'a>>>, Box<i32>); | ||||||||||
/// impl Drop for S<'_> { | ||||||||||
/// fn drop(&mut self) { | ||||||||||
/// if let Some(r) = self.0.get() { | ||||||||||
/// // Print the contents of the `Box` in `r`. | ||||||||||
/// println!("{}", r.1); | ||||||||||
/// } | ||||||||||
/// } | ||||||||||
/// } | ||||||||||
/// | ||||||||||
/// fn main() { | ||||||||||
/// // Set up two `S` that point to each other. | ||||||||||
/// let s1 = S(Cell::new(None), Box::new(42)); | ||||||||||
/// let s2 = S(Cell::new(Some(&s1)), Box::new(42)); | ||||||||||
/// s1.0.set(Some(&s2)); | ||||||||||
/// // Now they both get dropped. But whichever is the 2nd one | ||||||||||
/// // to be dropped will access the `Box` in the first one, | ||||||||||
/// // which is a use-after-free! | ||||||||||
/// } | ||||||||||
/// ``` | ||||||||||
/// | ||||||||||
/// The Nomicon discusses the need for [drop check in more detail][drop check]. | ||||||||||
/// | ||||||||||
/// To reject such code, the "drop check" analysis determines which types and lifetimes need to | ||||||||||
/// still be live when `T` gets dropped. The exact details of this analysis are not yet | ||||||||||
/// stably guaranteed and **subject to change**. Currently, the analysis works as follows: | ||||||||||
/// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if | ||||||||||
/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`] | ||||||||||
/// and [`ManuallyDrop`] are considered to never have a destructor, no matter their field type. | ||||||||||
/// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`, | ||||||||||
/// recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of | ||||||||||
/// owned types is determined by recursively traversing `T`: | ||||||||||
/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (including arrays of | ||||||||||
/// length 0). | ||||||||||
/// - Stop at reference and raw pointer types as well as function pointers and function items; | ||||||||||
/// they do not own anything. | ||||||||||
/// - Stop at non-composite types (type parameters that remain generic in the current context and | ||||||||||
/// base types such as integers and `bool`); these types are owned. | ||||||||||
/// - When hitting an ADT with `impl Drop`, stop there; this type is owned. | ||||||||||
/// - When hitting an ADT without `impl Drop`, recursively descend to its fields. (For an `enum`, | ||||||||||
/// consider all fields of all variants.) | ||||||||||
Comment on lines
+186
to
+187
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
or sth like that |
||||||||||
/// - Furthermore, if `T` implements `Drop`, then all generic (lifetime and type) parameters of `T` | ||||||||||
/// must be live. | ||||||||||
/// | ||||||||||
/// In the above example, the last clause implies that `'a` must be live when `S<'a>` is dropped, | ||||||||||
/// and hence the example is rejected. If we remove the `impl Drop`, the liveness requirement | ||||||||||
/// disappears and the example is accepted. | ||||||||||
/// | ||||||||||
/// There exists an unstable way for a type to opt-out of the last clause; this is called "drop | ||||||||||
/// check eyepatch" or `may_dangle`. For more details on this nightly-only feature, see the | ||||||||||
/// [discussion in the Nomicon][nomicon]. | ||||||||||
/// | ||||||||||
/// [`ManuallyDrop`]: crate::mem::ManuallyDrop | ||||||||||
/// [`PhantomData`]: crate::marker::PhantomData | ||||||||||
/// [drop check]: ../../nomicon/dropck.html | ||||||||||
/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle | ||||||||||
#[lang = "drop"] | ||||||||||
#[stable(feature = "rust1", since = "1.0.0")] | ||||||||||
#[const_trait] | ||||||||||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// check-pass | ||
//! This test checks that dropck knows that ManuallyDrop does not drop its field. | ||
#![feature(dropck_eyepatch)] | ||
|
||
use std::mem::ManuallyDrop; | ||
|
||
struct S<T>(ManuallyDrop<T>); | ||
|
||
unsafe impl<#[may_dangle] T> Drop for S<T> { | ||
fn drop(&mut self) {} | ||
} | ||
|
||
struct NonTrivialDrop<'a>(&'a str); | ||
impl<'a> Drop for NonTrivialDrop<'a> { | ||
fn drop(&mut self) {} | ||
} | ||
|
||
fn main() { | ||
let s = String::from("string"); | ||
let _t = S(ManuallyDrop::new(NonTrivialDrop(&s))); | ||
drop(s); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.