Skip to content

Commit 29630ce

Browse files
committed
Auto merge of #71992 - Dylan-DPC:rollup-29qjvpe, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #70733 (Add Arc::{incr,decr}_strong_count) - #71598 (improve Drop documentation) - #71783 (Detect errors caused by `async` block in 2015 edition) - #71903 (reword "possible candidate" import suggestion) - #71960 (Fix E0284 to not use incorrect wording) Failed merges: r? @ghost
2 parents 1eefa67 + 14cbbf3 commit 29630ce

File tree

64 files changed

+492
-222
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+492
-222
lines changed

src/liballoc/sync.rs

+73
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,79 @@ impl<T: ?Sized> Arc<T> {
776776
this.inner().strong.load(SeqCst)
777777
}
778778

779+
/// Increments the strong reference count on the `Arc<T>` associated with the
780+
/// provided pointer by one.
781+
///
782+
/// # Safety
783+
///
784+
/// The pointer must have been obtained through `Arc::into_raw`, and the
785+
/// associated `Arc` instance must be valid (i.e. the strong count must be at
786+
/// least 1) for the duration of this method.
787+
///
788+
/// # Examples
789+
///
790+
/// ```
791+
/// #![feature(arc_mutate_strong_count)]
792+
///
793+
/// use std::sync::Arc;
794+
///
795+
/// let five = Arc::new(5);
796+
///
797+
/// unsafe {
798+
/// let ptr = Arc::into_raw(five);
799+
/// Arc::incr_strong_count(ptr);
800+
///
801+
/// // This assertion is deterministic because we haven't shared
802+
/// // the `Arc` between threads.
803+
/// let five = Arc::from_raw(ptr);
804+
/// assert_eq!(2, Arc::strong_count(&five));
805+
/// }
806+
/// ```
807+
#[inline]
808+
#[unstable(feature = "arc_mutate_strong_count", issue = "71983")]
809+
pub unsafe fn incr_strong_count(ptr: *const T) {
810+
// Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
811+
let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr));
812+
// Now increase refcount, but don't drop new refcount either
813+
let _arc_clone: mem::ManuallyDrop<_> = arc.clone();
814+
}
815+
816+
/// Decrements the strong reference count on the `Arc<T>` associated with the
817+
/// provided pointer by one.
818+
///
819+
/// # Safety
820+
///
821+
/// The pointer must have been obtained through `Arc::into_raw`, and the
822+
/// associated `Arc` instance must be valid (i.e. the strong count must be at
823+
/// least 1) when invoking this method. This method can be used to release the final
824+
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
825+
/// released.
826+
///
827+
/// # Examples
828+
///
829+
/// ```
830+
/// #![feature(arc_mutate_strong_count)]
831+
///
832+
/// use std::sync::Arc;
833+
///
834+
/// let five = Arc::new(5);
835+
///
836+
/// unsafe {
837+
/// let ptr = Arc::into_raw(five);
838+
/// Arc::decr_strong_count(ptr);
839+
///
840+
/// // This assertion is deterministic because we haven't shared
841+
/// // the `Arc` between threads.
842+
/// let five = Arc::from_raw(ptr);
843+
/// assert_eq!(0, Arc::strong_count(&five));
844+
/// }
845+
/// ```
846+
#[inline]
847+
#[unstable(feature = "arc_mutate_strong_count", issue = "71983")]
848+
pub unsafe fn decr_strong_count(ptr: *const T) {
849+
mem::drop(Arc::from_raw(ptr));
850+
}
851+
779852
#[inline]
780853
fn inner(&self) -> &ArcInner<T> {
781854
// This unsafety is ok because while this arc is alive we're guaranteed

src/liballoc/task.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![unstable(feature = "wake_trait", issue = "69912")]
22
//! Types and Traits for working with asynchronous tasks.
3-
use core::mem::{self, ManuallyDrop};
3+
use core::mem::ManuallyDrop;
44
use core::task::{RawWaker, RawWakerVTable, Waker};
55

66
use crate::sync::Arc;
@@ -60,9 +60,11 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
6060
fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
6161
// Increment the reference count of the arc to clone it.
6262
unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
63-
let waker: Arc<W> = Arc::from_raw(waker as *const W);
64-
mem::forget(Arc::clone(&waker));
65-
raw_waker(waker)
63+
Arc::incr_strong_count(waker as *const W);
64+
RawWaker::new(
65+
waker as *const (),
66+
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
67+
)
6668
}
6769

6870
// Wake by value, moving the Arc into the Wake::wake function
@@ -79,7 +81,7 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
7981

8082
// Decrement the reference count of the Arc on drop
8183
unsafe fn drop_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) {
82-
mem::drop(Arc::from_raw(waker as *const W));
84+
Arc::decr_strong_count(waker as *const W);
8385
}
8486

8587
RawWaker::new(

src/libcore/ops/drop.rs

+98-44
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,139 @@
1-
/// Used to run some code when a value goes out of scope.
2-
/// This is sometimes called a 'destructor'.
1+
/// Custom code within the destructor.
32
///
4-
/// When a value goes out of scope, it will have its `drop` method called if
5-
/// its type implements `Drop`. Then, any fields the value contains will also
6-
/// be dropped recursively.
3+
/// When a value is no longer needed, Rust will run a "destructor" on that value.
4+
/// The most common way that a value is no longer needed is when it goes out of
5+
/// scope. Destructors may still run in other circumstances, but we're going to
6+
/// focus on scope for the examples here. To learn about some of those other cases,
7+
/// please see [the reference] section on destructors.
78
///
8-
/// Because of this recursive dropping, you do not need to implement this trait
9-
/// unless your type needs its own destructor logic.
9+
/// [the reference]: https://doc.rust-lang.org/reference/destructors.html
1010
///
11-
/// Refer to [the chapter on `Drop` in *The Rust Programming Language*][book]
12-
/// for some more elaboration.
11+
/// This destructor consists of two components:
12+
/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type.
13+
/// - The automatically generated "drop glue" which recursively calls the destructors
14+
/// of the all fields of this value.
1315
///
14-
/// [book]: ../../book/ch15-03-drop.html
16+
/// As Rust automatically calls the destructors of all contained fields,
17+
/// you don't have to implement `Drop` in most cases. But there are some cases where
18+
/// it is useful, for example for types which directly manage a resource.
19+
/// That resource may be memory, it may be a file descriptor, it may be a network socket.
20+
/// Once a value of that type is no longer going to be used, it should "clean up" its
21+
/// resource by freeing the memory or closing the file or socket. This is
22+
/// the job of a destructor, and therefore the job of `Drop::drop`.
1523
///
16-
/// # Examples
24+
/// ## Examples
1725
///
18-
/// ## Implementing `Drop`
26+
/// To see destructors in action, let's take a look at the following program:
1927
///
20-
/// The `drop` method is called when `_x` goes out of scope, and therefore
21-
/// `main` prints `Dropping!`.
22-
///
23-
/// ```
28+
/// ```rust
2429
/// struct HasDrop;
2530
///
2631
/// impl Drop for HasDrop {
2732
/// fn drop(&mut self) {
28-
/// println!("Dropping!");
33+
/// println!("Dropping HasDrop!");
34+
/// }
35+
/// }
36+
///
37+
/// struct HasTwoDrops {
38+
/// one: HasDrop,
39+
/// two: HasDrop,
40+
/// }
41+
///
42+
/// impl Drop for HasTwoDrops {
43+
/// fn drop(&mut self) {
44+
/// println!("Dropping HasTwoDrops!");
2945
/// }
3046
/// }
3147
///
3248
/// fn main() {
33-
/// let _x = HasDrop;
49+
/// let _x = HasTwoDrops { one: HasDrop, two: HasDrop };
50+
/// println!("Running!");
3451
/// }
3552
/// ```
3653
///
37-
/// ## Dropping is done recursively
54+
/// Rust will first call `Drop::drop` for `_x` and then for both `_x.one` and `_x.two`,
55+
/// meaning that running this will print
3856
///
39-
/// When `outer` goes out of scope, the `drop` method will be called first for
40-
/// `Outer`, then for `Inner`. Therefore, `main` prints `Dropping Outer!` and
41-
/// then `Dropping Inner!`.
57+
/// ```text
58+
/// Running!
59+
/// Dropping HasTwoDrops!
60+
/// Dropping HasDrop!
61+
/// Dropping HasDrop!
62+
/// ```
63+
///
64+
/// Even if we remove the implementation of `Drop` for `HasTwoDrop`, the destructors of its fields are still called.
65+
/// This would result in
4266
///
67+
/// ```test
68+
/// Running!
69+
/// Dropping HasDrop!
70+
/// Dropping HasDrop!
4371
/// ```
44-
/// struct Inner;
45-
/// struct Outer(Inner);
4672
///
47-
/// impl Drop for Inner {
73+
/// ## You cannot call `Drop::drop` yourself
74+
///
75+
/// Because `Drop::drop` is used to clean up a value, it may be dangerous to use this value after
76+
/// the method has been called. As `Drop::drop` does not take ownership of its input,
77+
/// Rust prevents misuse by not allowing you to call `Drop::drop` directly.
78+
///
79+
/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error.
80+
///
81+
/// If you'd like explicitly call the destructor of a value, [`std::mem::drop`] can be used instead.
82+
///
83+
/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
84+
///
85+
/// ## Drop order
86+
///
87+
/// Which of our two `HasDrop` drops first, though? For structs, it's the same
88+
/// order that they're declared: first `one`, then `two`. If you'd like to try
89+
/// this yourself, you can modify `HasDrop` above to contain some data, like an
90+
/// integer, and then use it in the `println!` inside of `Drop`. This behavior is
91+
/// guaranteed by the language.
92+
///
93+
/// Unlike for structs, local variables are dropped in reverse order:
94+
///
95+
/// ```rust
96+
/// struct Foo;
97+
///
98+
/// impl Drop for Foo {
4899
/// fn drop(&mut self) {
49-
/// println!("Dropping Inner!");
100+
/// println!("Dropping Foo!")
50101
/// }
51102
/// }
52103
///
53-
/// impl Drop for Outer {
104+
/// struct Bar;
105+
///
106+
/// impl Drop for Bar {
54107
/// fn drop(&mut self) {
55-
/// println!("Dropping Outer!");
108+
/// println!("Dropping Bar!")
56109
/// }
57110
/// }
58111
///
59112
/// fn main() {
60-
/// let _x = Outer(Inner);
113+
/// let _foo = Foo;
114+
/// let _bar = Bar;
61115
/// }
62116
/// ```
63117
///
64-
/// ## Variables are dropped in reverse order of declaration
65-
///
66-
/// `_first` is declared first and `_second` is declared second, so `main` will
67-
/// print `Declared second!` and then `Declared first!`.
118+
/// This will print
68119
///
120+
/// ```text
121+
/// Dropping Bar!
122+
/// Dropping Foo!
69123
/// ```
70-
/// struct PrintOnDrop(&'static str);
71124
///
72-
/// impl Drop for PrintOnDrop {
73-
/// fn drop(&mut self) {
74-
/// println!("{}", self.0);
75-
/// }
76-
/// }
125+
/// Please see [the reference] for the full rules.
77126
///
78-
/// fn main() {
79-
/// let _first = PrintOnDrop("Declared first!");
80-
/// let _second = PrintOnDrop("Declared second!");
81-
/// }
82-
/// ```
127+
/// [the reference]: https://doc.rust-lang.org/reference/destructors.html
128+
///
129+
/// ## `Copy` and `Drop` are exclusive
130+
///
131+
/// You cannot implement both [`Copy`] and `Drop` on the same type. Types that
132+
/// are `Copy` get implicitly duplicated by the compiler, making it very
133+
/// hard to predict when, and how often destructors will be executed. As such,
134+
/// these types cannot have destructors.
135+
///
136+
/// [`Copy`]: ../../std/marker/trait.Copy.html
83137
#[lang = "drop"]
84138
#[stable(feature = "rust1", since = "1.0.0")]
85139
pub trait Drop {

0 commit comments

Comments
 (0)