Change:
There was some confusion in #rust over when values are dropped. It was pointed out that the documentation only says drop is called if "a value goes out of scope", which is inaccurate: Scopes apply to variables, not values Values can be dropped for other reasons than scopes ending. For example, if a variable is re-assigned, the old value is dropped. There are also temporaries. I don't know how to best phrase it, but focusing only on scopes is evidently a good way to confuse people.
I feel like scopes are still the best way to model the intuition about drops, but it is important to understand that scopes used for drop generation aren’t exactly the lexical scopes which you have in the source file. Most notably drop scopes may overlap in various ways in which the lexical scopes cannot. Similarly, each let binding introduces a scope, which is distinct from any lexical scope you have. (Re-)assignments are best considered as a sugar for which does not exactly invalidate the scope-based intuition either.
What exactly is a "scope", then? An arbitrary execution path in the CFG? I can't see them being anything less, since all the various operations that cause early drops may be conditional or in loops. And I find it very strange to "desugar" a primitive language construct such as assignment to a combination of various API calls. I understand it's meant for "intuitive" understanding, but even so it sounds strange and possibly counter-productive for people confused about drop placement.
I adjusted the title to make it more clear this is talking about documentation, rather than the operation of destructors in general.
doc team triage: p-medium
Triage: no changes, though with NLL, referring to it as a scope will become even more confusing, making this a higher priority.

Discussion:
<del> /// Used to run some code when a value goes out of scope. /// This is sometimes called a 'destructor'. </del> <ins> /// Custom code within the destructor. </ins> /// <del> /// When a value goes out of scope, it will have its `drop` method called if /// its type implements `Drop`. Then, any fields the value contains will also /// be dropped recursively. </del> <ins> /// When a value is no longer needed, Rust will run a "destructor" on that value. /// The most common way that a value is no longer needed is when it goes out of /// scope. Destructors may still run in other circumstances, but we're going to /// focus on scope for the examples here. To learn about some of those other cases, /// please see [the reference] section on destructors. </ins> /// <del> /// Because of this recursive dropping, you do not need to implement this trait /// unless your type needs its own destructor logic. </del> <ins> /// [the reference]: https://doc.rust-lang.org/reference/destructors.html </ins> /// <del> /// Refer to [the chapter on `Drop` in *The Rust Programming Language*][book] /// for some more elaboration. </del> <ins> /// This destructor consists of two components: /// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type. /// - The automatically generated "drop glue" which recursively calls the destructors ///     of the all fields of this value. </ins> /// <del> /// [book]: ../../book/ch15-03-drop.html </del> <ins> /// As Rust automatically calls the destructors of all contained fields, /// you don't have to implement `Drop` in most cases. But there are some cases where /// it is useful, for example for types which directly manage a resource. /// That resource may be memory, it may be a file descriptor, it may be a network socket. /// Once a value of that type is no longer going to be used, it should "clean up" its /// resource by freeing the memory or closing the file or socket. This is /// the job of a destructor, and therefore the job of `Drop::drop`. </ins> /// <del> /// # Examples </del> <ins> /// ## Examples </ins> /// <del> /// ## Implementing `Drop` </del> <ins> /// To see destructors in action, let's take a look at the following program: </ins> /// <del> /// The `drop` method is called when `_x` goes out of scope, and therefore /// `main` prints `Dropping!`. /// /// ``` </del> <ins> /// ```rust </ins> /// struct HasDrop; /// /// impl Drop for HasDrop { ///     fn drop(&mut self) { <del> ///         println!("Dropping!"); </del> <ins> ///         println!("Dropping HasDrop!"); ///     } /// } /// /// struct HasTwoDrops { ///     one: HasDrop, ///     two: HasDrop, /// } /// /// impl Drop for HasTwoDrops { ///     fn drop(&mut self) { ///         println!("Dropping HasTwoDrops!"); </ins> ///     } /// } /// /// fn main() { <del> ///     let _x = HasDrop; </del> <ins> ///     let _x = HasTwoDrops { one: HasDrop, two: HasDrop }; ///     println!("Running!"); </ins> /// } /// ``` /// <del> /// ## Dropping is done recursively </del> <ins> /// Rust will first call `Drop::drop` for `_x` and then for both `_x.one` and `_x.two`, /// meaning that running this will print </ins> /// <del> /// When `outer` goes out of scope, the `drop` method will be called first for /// `Outer`, then for `Inner`. Therefore, `main` prints `Dropping Outer!` and /// then `Dropping Inner!`. </del> <ins> /// ```text /// Running! /// Dropping HasTwoDrops! /// Dropping HasDrop! /// Dropping HasDrop! /// ``` /// /// Even if we remove the implementation of `Drop` for `HasTwoDrop`, the destructors of its fields are still called. /// This would result in </ins> /// <ins> /// ```test /// Running! /// Dropping HasDrop! /// Dropping HasDrop! </ins> /// ``` <del> /// struct Inner; /// struct Outer(Inner); </del> /// <del> /// impl Drop for Inner { </del> <ins> /// ## You cannot call `Drop::drop` yourself /// /// Because `Drop::drop` is used to clean up a value, it may be dangerous to use this value after /// the method has been called. As `Drop::drop` does not take ownership of its input, /// Rust prevents misuse by not allowing you to call `Drop::drop` directly. /// /// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error. /// /// If you'd like explicitly call the destructor of a value, [`std::mem::drop`] can be used instead. /// /// [`std::mem::drop`]: ../../std/mem/fn.drop.html /// /// ## Drop order /// /// Which of our two `HasDrop` drops first, though? For structs, it's the same /// order that they're declared: first `one`, then `two`. If you'd like to try /// this yourself, you can modify `HasDrop` above to contain some data, like an /// integer, and then use it in the `println!` inside of `Drop`. This behavior is /// guaranteed by the language. /// /// Unlike for structs, local variables are dropped in reverse order: /// /// ```rust /// struct Foo; /// /// impl Drop for Foo { </ins> ///     fn drop(&mut self) { <del> ///         println!("Dropping Inner!"); </del> <ins> ///         println!("Dropping Foo!") </ins> ///     } /// } /// <del> /// impl Drop for Outer { </del> <ins> /// struct Bar; /// /// impl Drop for Bar { </ins> ///     fn drop(&mut self) { <del> ///         println!("Dropping Outer!"); </del> <ins> ///         println!("Dropping Bar!") </ins> ///     } /// } /// /// fn main() { <del> ///     let _x = Outer(Inner); </del> <ins> ///     let _foo = Foo; ///     let _bar = Bar; </ins> /// } /// ``` /// <del> /// ## Variables are dropped in reverse order of declaration /// /// `_first` is declared first and `_second` is declared second, so `main` will /// print `Declared second!` and then `Declared first!`. </del> <ins> /// This will print </ins> /// <ins> /// ```text /// Dropping Bar! /// Dropping Foo! </ins> /// ``` <del> /// struct PrintOnDrop(&'static str); </del> /// <del> /// impl Drop for PrintOnDrop { ///     fn drop(&mut self) { ///         println!("{}", self.0); ///     } /// } </del> <ins> /// Please see [the reference] for the full rules. </ins> /// <del> /// fn main() { ///     let _first = PrintOnDrop("Declared first!"); ///     let _second = PrintOnDrop("Declared second!"); /// } /// ``` </del> <ins> /// [the reference]: https://doc.rust-lang.org/reference/destructors.html /// /// ## `Copy` and `Drop` are exclusive /// /// You cannot implement both [`Copy`] and `Drop` on the same type. Types that /// 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. /// /// [`Copy`]: ../../std/marker/trait.Copy.html </ins> #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Drop {