diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index f768bd157abc8..bd2252c1bf8fd 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -46,6 +46,9 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the {$ hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes +hir_analysis_async_drop_without_sync_drop = `AsyncDrop` impl without `Drop` impl + .help = type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds + hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index c5c7e6b2aa722..de8cbc3a57ff2 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -113,7 +113,15 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_dtor(def_id, always_applicable::check_drop_impl) + let dtor = tcx.calculate_dtor(def_id, always_applicable::check_drop_impl); + if dtor.is_none() && tcx.features().async_drop() { + if let Some(async_dtor) = adt_async_destructor(tcx, def_id) { + // When type has AsyncDrop impl, but doesn't have Drop impl, generate error + let span = tcx.def_span(async_dtor.impl_did); + tcx.dcx().emit_err(errors::AsyncDropWithoutSyncDrop { span }); + } + } + dtor } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 8de2aec95a7b2..318aaab50f4d4 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1712,3 +1712,11 @@ pub(crate) struct AbiCustomClothedFunction { )] pub naked_span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_async_drop_without_sync_drop)] +#[help] +pub(crate) struct AsyncDropWithoutSyncDrop { + #[primary_span] + pub span: Span, +} diff --git a/tests/ui/async-await/async-drop/async-without-sync.rs b/tests/ui/async-await/async-drop/async-without-sync.rs new file mode 100644 index 0000000000000..8a748636cc783 --- /dev/null +++ b/tests/ui/async-await/async-drop/async-without-sync.rs @@ -0,0 +1,19 @@ +//@ edition: 2024 +#![feature(async_drop)] +#![allow(incomplete_features)] +#![crate_type = "lib"] + +use std::future::AsyncDrop; +use std::pin::Pin; + +async fn foo() { + let _st = St; +} + +struct St; + +impl AsyncDrop for St { //~ ERROR: `AsyncDrop` impl without `Drop` impl + async fn drop(self: Pin<&mut Self>) { + println!("123"); + } +} diff --git a/tests/ui/async-await/async-drop/async-without-sync.stderr b/tests/ui/async-await/async-drop/async-without-sync.stderr new file mode 100644 index 0000000000000..0eaca322dc034 --- /dev/null +++ b/tests/ui/async-await/async-drop/async-without-sync.stderr @@ -0,0 +1,10 @@ +error: `AsyncDrop` impl without `Drop` impl + --> $DIR/async-without-sync.rs:15:1 + | +LL | impl AsyncDrop for St { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds + +error: aborting due to 1 previous error +