@@ -422,11 +422,8 @@ where
422422
423423 fn build_drop ( & mut self , bb : BasicBlock ) {
424424 let drop_ty = self . place_ty ( self . place ) ;
425- if self . tcx ( ) . features ( ) . async_drop ( )
426- && self . elaborator . body ( ) . coroutine . is_some ( )
427- && self . elaborator . allow_async_drops ( )
428- && !self . elaborator . patch_ref ( ) . block ( self . elaborator . body ( ) , bb) . is_cleanup
429- && drop_ty. needs_async_drop ( self . tcx ( ) , self . elaborator . typing_env ( ) )
425+ if !self . elaborator . patch_ref ( ) . block ( self . elaborator . body ( ) , bb) . is_cleanup
426+ && self . check_if_can_async_drop ( drop_ty, false )
430427 {
431428 self . build_async_drop (
432429 self . place ,
@@ -452,6 +449,46 @@ where
452449 }
453450 }
454451
452+ /// Function to check if we can generate an async drop here
453+ fn check_if_can_async_drop ( & mut self , drop_ty : Ty < ' tcx > , call_destructor_only : bool ) -> bool {
454+ let is_async_drop_feature_enabled = if self . tcx ( ) . features ( ) . async_drop ( ) {
455+ true
456+ } else {
457+ // Check if the type needing async drop comes from a dependency crate.
458+ if let ty:: Adt ( adt_def, _) = drop_ty. kind ( ) {
459+ !adt_def. did ( ) . is_local ( ) && adt_def. async_destructor ( self . tcx ( ) ) . is_some ( )
460+ } else {
461+ false
462+ }
463+ } ;
464+
465+ // Short-circuit before calling needs_async_drop/is_async_drop, as those
466+ // require the `async_drop` lang item to exist (which may not be present
467+ // in minimal/custom core environments like cranelift's mini_core).
468+ if !is_async_drop_feature_enabled
469+ || !self . elaborator . body ( ) . coroutine . is_some ( )
470+ || !self . elaborator . allow_async_drops ( )
471+ {
472+ return false ;
473+ }
474+
475+ let needs_async_drop = if call_destructor_only {
476+ drop_ty. is_async_drop ( self . tcx ( ) , self . elaborator . typing_env ( ) )
477+ } else {
478+ drop_ty. needs_async_drop ( self . tcx ( ) , self . elaborator . typing_env ( ) )
479+ } ;
480+
481+ // Async drop in libstd/libcore would become insta-stable — catch that mistake.
482+ if needs_async_drop && self . tcx ( ) . features ( ) . staged_api ( ) {
483+ span_bug ! (
484+ self . source_info. span,
485+ "don't use async drop in libstd, it becomes insta-stable"
486+ ) ;
487+ }
488+
489+ needs_async_drop
490+ }
491+
455492 /// This elaborates a single drop instruction, located at `bb`, and
456493 /// patches over it.
457494 ///
@@ -1003,12 +1040,7 @@ where
10031040 ) -> BasicBlock {
10041041 debug ! ( "destructor_call_block({:?}, {:?})" , self , succ) ;
10051042 let ty = self . place_ty ( self . place ) ;
1006- if self . tcx ( ) . features ( ) . async_drop ( )
1007- && self . elaborator . body ( ) . coroutine . is_some ( )
1008- && self . elaborator . allow_async_drops ( )
1009- && !unwind. is_cleanup ( )
1010- && ty. is_async_drop ( self . tcx ( ) , self . elaborator . typing_env ( ) )
1011- {
1043+ if !unwind. is_cleanup ( ) && self . check_if_can_async_drop ( ty, true ) {
10121044 self . build_async_drop ( self . place , ty, None , succ, unwind, dropline, true )
10131045 } else {
10141046 self . destructor_call_block_sync ( ( succ, unwind) )
@@ -1078,12 +1110,7 @@ where
10781110 let loop_block = self . elaborator . patch ( ) . new_block ( loop_block) ;
10791111
10801112 let place = tcx. mk_place_deref ( ptr) ;
1081- if self . tcx ( ) . features ( ) . async_drop ( )
1082- && self . elaborator . body ( ) . coroutine . is_some ( )
1083- && self . elaborator . allow_async_drops ( )
1084- && !unwind. is_cleanup ( )
1085- && ety. needs_async_drop ( self . tcx ( ) , self . elaborator . typing_env ( ) )
1086- {
1113+ if !unwind. is_cleanup ( ) && self . check_if_can_async_drop ( ety, false ) {
10871114 self . build_async_drop (
10881115 place,
10891116 ety,
@@ -1368,12 +1395,7 @@ where
13681395
13691396 fn drop_block ( & mut self , target : BasicBlock , unwind : Unwind ) -> BasicBlock {
13701397 let drop_ty = self . place_ty ( self . place ) ;
1371- if self . tcx ( ) . features ( ) . async_drop ( )
1372- && self . elaborator . body ( ) . coroutine . is_some ( )
1373- && self . elaborator . allow_async_drops ( )
1374- && !unwind. is_cleanup ( )
1375- && drop_ty. needs_async_drop ( self . tcx ( ) , self . elaborator . typing_env ( ) )
1376- {
1398+ if !unwind. is_cleanup ( ) && self . check_if_can_async_drop ( drop_ty, false ) {
13771399 self . build_async_drop (
13781400 self . place ,
13791401 drop_ty,
0 commit comments