Skip to content

Commit 73c7006

Browse files
committed
AsyncDrop trait without sync Drop generates an error
1 parent 7c10378 commit 73c7006

File tree

5 files changed

+59
-1
lines changed

5 files changed

+59
-1
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the {$
4242
4343
hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
4444
45+
hir_analysis_async_drop_without_sync_drop = `AsyncDrop` impl without `Drop` impl
46+
.help = type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds
47+
.note = `AsyncDrop` impl here
48+
4549
hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
4650
.label = deref recursion limit reached
4751
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,17 @@ pub fn provide(providers: &mut Providers) {
113113
}
114114

115115
fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
116-
tcx.calculate_dtor(def_id, always_applicable::check_drop_impl)
116+
let dtor = tcx.calculate_dtor(def_id, always_applicable::check_drop_impl);
117+
if dtor.is_none() && tcx.features().async_drop() {
118+
if let Some(async_dtor) = adt_async_destructor(tcx, def_id) {
119+
// When type has AsyncDrop impl, but doesn't have Drop impl, generate error
120+
let span = tcx.def_span(def_id.to_def_id());
121+
let impl_span = tcx.def_span(async_dtor.impl_did);
122+
let err = errors::AsyncDropWithoutSyncDrop { span, impl_span };
123+
tcx.dcx().emit_err(err);
124+
}
125+
}
126+
dtor
117127
}
118128

119129
fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,3 +1698,13 @@ pub(crate) struct SelfInTypeAlias {
16981698
#[label]
16991699
pub span: Span,
17001700
}
1701+
1702+
#[derive(Diagnostic)]
1703+
#[diag(hir_analysis_async_drop_without_sync_drop)]
1704+
#[help]
1705+
pub(crate) struct AsyncDropWithoutSyncDrop {
1706+
#[primary_span]
1707+
pub span: Span,
1708+
#[note]
1709+
pub impl_span: Span,
1710+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ edition: 2024
2+
#![feature(async_drop)]
3+
#![allow(incomplete_features)]
4+
#![crate_type = "lib"]
5+
6+
use std::future::AsyncDrop;
7+
use std::pin::Pin;
8+
9+
async fn foo() {
10+
let _st = St;
11+
}
12+
13+
struct St; //~ ERROR: `AsyncDrop` impl without `Drop` impl
14+
15+
impl AsyncDrop for St {
16+
async fn drop(self: Pin<&mut Self>) {
17+
println!("123");
18+
}
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: `AsyncDrop` impl without `Drop` impl
2+
--> $DIR/async-without-sync.rs:13:1
3+
|
4+
LL | struct St;
5+
| ^^^^^^^^^
6+
|
7+
= help: type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds
8+
note: `AsyncDrop` impl here
9+
--> $DIR/async-without-sync.rs:15:1
10+
|
11+
LL | impl AsyncDrop for St {
12+
| ^^^^^^^^^^^^^^^^^^^^^
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)