diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 14e353f13ca49..bbde0f3e7114e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -360,6 +360,8 @@ declare_features! ( (unstable, associated_type_defaults, "1.2.0", Some(29661)), /// Allows `async || body` closures. (unstable, async_closure, "1.37.0", Some(62290)), + /// Allows implementing `AsyncDrop`. + (incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)), /// Allows `#[track_caller]` on async functions. (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs new file mode 100644 index 0000000000000..fc4f95a98b42d --- /dev/null +++ b/library/core/src/future/async_drop.rs @@ -0,0 +1,51 @@ +#![unstable(feature = "async_drop", issue = "126482")] + +#[allow(unused_imports)] +use core::future::Future; + +#[allow(unused_imports)] +use crate::pin::Pin; +#[allow(unused_imports)] +use crate::task::{Context, Poll}; + +/// Async version of Drop trait. +/// +/// 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. +/// +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html +/// +/// ## `Copy` and ([`Drop`]|`AsyncDrop`) are exclusive +/// +/// You cannot implement both [`Copy`] and ([`Drop`]|`AsyncDrop`) 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. +#[cfg(not(bootstrap))] +#[unstable(feature = "async_drop", issue = "126482")] +#[lang = "async_drop"] +pub trait AsyncDrop { + /// Executes the async destructor for this type. + /// + /// This method is called implicitly when the value goes out of scope, + /// and cannot be called explicitly. + /// + /// When this method has been called, `self` has not yet been deallocated. + /// That only happens after the method is over. + /// + /// # Panics + #[allow(async_fn_in_trait)] + async fn drop(self: Pin<&mut Self>); +} + +/// Async drop. +#[cfg(not(bootstrap))] +#[unstable(feature = "async_drop", issue = "126482")] +#[lang = "async_drop_in_place"] +pub async unsafe fn async_drop_in_place(_to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real implementation by the compiler. +} diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 3a1ed307787ee..4137101583fad 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -12,6 +12,7 @@ use crate::ptr::NonNull; use crate::task::Context; +mod async_drop; mod future; mod into_future; mod join; @@ -19,6 +20,9 @@ mod pending; mod poll_fn; mod ready; +#[cfg(not(bootstrap))] +#[unstable(feature = "async_drop", issue = "126482")] +pub use async_drop::{async_drop_in_place, AsyncDrop}; #[stable(feature = "into_future", since = "1.64.0")] pub use into_future::IntoFuture; #[stable(feature = "future_readiness_fns", since = "1.48.0")] diff --git a/tests/ui/feature-gates/feature-gate-async-drop.rs b/tests/ui/feature-gates/feature-gate-async-drop.rs new file mode 100644 index 0000000000000..6da5008846d77 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-drop.rs @@ -0,0 +1,16 @@ +//@ edition: 2021 + +use std::future::AsyncDrop; //~ ERROR use of unstable library feature 'async_drop' +use std::pin::Pin; + +struct Foo {} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +impl AsyncDrop for Foo { //~ ERROR use of unstable library feature 'async_drop' + async fn drop(self: Pin<&mut Self>) {} //~ ERROR use of unstable library feature 'async_drop' +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-async-drop.stderr b/tests/ui/feature-gates/feature-gate-async-drop.stderr new file mode 100644 index 0000000000000..6f0edb183a412 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-drop.stderr @@ -0,0 +1,33 @@ +error[E0658]: use of unstable library feature 'async_drop' + --> $DIR/feature-gate-async-drop.rs:3:5 + | +LL | use std::future::AsyncDrop; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #126482 for more information + = help: add `#![feature(async_drop)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'async_drop' + --> $DIR/feature-gate-async-drop.rs:13:5 + | +LL | async fn drop(self: Pin<&mut Self>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #126482 for more information + = help: add `#![feature(async_drop)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'async_drop' + --> $DIR/feature-gate-async-drop.rs:12:6 + | +LL | impl AsyncDrop for Foo { + | ^^^^^^^^^ + | + = note: see issue #126482 for more information + = help: add `#![feature(async_drop)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`.