@@ -3,7 +3,7 @@ use std::collections::hash_map;
33use std:: rc:: Rc ;
44
55use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
6- use rustc_data_structures:: unord:: UnordSet ;
6+ use rustc_data_structures:: unord:: { UnordMap , UnordSet } ;
77use rustc_errors:: Subdiagnostic ;
88use rustc_hir:: CRATE_HIR_ID ;
99use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -20,7 +20,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
2020use rustc_mir_dataflow:: move_paths:: { LookupResult , MoveData , MovePathIndex } ;
2121use rustc_mir_dataflow:: { Analysis , MaybeReachable , ResultsCursor } ;
2222use rustc_session:: lint;
23- use rustc_span:: { Span , Symbol } ;
23+ use rustc_span:: { DUMMY_SP , Span , Symbol } ;
2424use rustc_type_ir:: data_structures:: IndexMap ;
2525use smallvec:: { SmallVec , smallvec} ;
2626use tracing:: { debug, instrument} ;
@@ -170,7 +170,9 @@ fn true_significant_drop_ty<'tcx>(
170170 debug ! ( ?name_str) ;
171171 match name_str[ ..] {
172172 // These are the types from Rust core ecosystem
173- [ "sym" | "proc_macro2" , ..] | [ "core" | "std" , "task" , "RawWaker" ] => Some ( smallvec ! [ ] ) ,
173+ [ "sym" | "proc_macro2" , ..]
174+ | [ "core" | "std" , "task" , "LocalWaker" | "Waker" ]
175+ | [ "core" | "std" , "task" , "wake" , "LocalWaker" | "Waker" ] => Some ( smallvec ! [ ] ) ,
174176 // These are important types from Rust ecosystem
175177 [ "tracing" , "instrument" , "Instrumented" ] | [ "bytes" , "Bytes" ] => Some ( smallvec ! [ ] ) ,
176178 [ "hashbrown" , "raw" , "RawTable" | "RawIntoIter" ] => {
@@ -328,9 +330,19 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
328330 // because they tend to be scheduled in the same drop ladder block.
329331 let mut bid_per_block = IndexMap :: default ( ) ;
330332 let mut bid_places = UnordSet :: new ( ) ;
333+ let param_env = tcx. param_env ( def_id) . with_reveal_all_normalized ( tcx) ;
334+ let mut ty_dropped_components = UnordMap :: default ( ) ;
331335 for ( block, data) in body. basic_blocks . iter_enumerated ( ) {
332336 for ( statement_index, stmt) in data. statements . iter ( ) . enumerate ( ) {
333337 if let StatementKind :: BackwardIncompatibleDropHint { place, reason : _ } = & stmt. kind {
338+ let ty = place. ty ( body, tcx) . ty ;
339+ if ty_dropped_components
340+ . entry ( ty)
341+ . or_insert_with ( || extract_component_with_significant_dtor ( tcx, param_env, ty) )
342+ . is_empty ( )
343+ {
344+ continue ;
345+ }
334346 bid_per_block
335347 . entry ( block)
336348 . or_insert ( vec ! [ ] )
@@ -345,7 +357,6 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
345357
346358 dump_mir ( tcx, false , "lint_tail_expr_drop_order" , & 0 as _ , body, |_, _| Ok ( ( ) ) ) ;
347359 let locals_with_user_names = collect_user_names ( body) ;
348- let param_env = tcx. param_env ( def_id) . with_reveal_all_normalized ( tcx) ;
349360 let is_closure_like = tcx. is_closure_like ( def_id. to_def_id ( ) ) ;
350361 let move_data = MoveData :: gather_moves ( body, tcx, |_| true ) ;
351362 let maybe_init = MaybeInitializedPlaces :: new ( tcx, body, & move_data) ;
@@ -401,7 +412,13 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
401412 }
402413 let observer_ty = move_path. place . ty ( body, tcx) . ty ;
403414 // d) The collect local has no custom destructor.
404- if !observer_ty. has_significant_drop ( tcx, param_env) {
415+ if ty_dropped_components
416+ . entry ( observer_ty)
417+ . or_insert_with ( || {
418+ extract_component_with_significant_dtor ( tcx, param_env, observer_ty)
419+ } )
420+ . is_empty ( )
421+ {
405422 debug ! ( ?dropped_local, "skip non-droppy types" ) ;
406423 to_exclude. insert ( path_idx) ;
407424 continue ;
@@ -449,12 +466,26 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
449466 }
450467
451468 // Collect spans of the custom destructors.
452- let destructors =
453- extract_component_with_significant_dtor ( tcx, param_env, linted_local_decl. ty )
454- . into_iter ( )
455- . filter_map ( |ty| ty_dtor_span ( tcx, ty) )
456- . map ( |span| DestructorLabel { span, name } )
457- . collect ( ) ;
469+ let mut seen_dyn = false ;
470+ let destructors = ty_dropped_components
471+ . get ( & linted_local_decl. ty )
472+ . unwrap ( )
473+ . iter ( )
474+ . filter_map ( |& ty| {
475+ if let Some ( span) = ty_dtor_span ( tcx, ty) {
476+ Some ( DestructorLabel { span, name, dtor_kind : "concrete" } )
477+ } else if matches ! ( ty. kind( ) , ty:: Dynamic ( ..) ) {
478+ if seen_dyn {
479+ None
480+ } else {
481+ seen_dyn = true ;
482+ Some ( DestructorLabel { span : DUMMY_SP , name, dtor_kind : "dyn" } )
483+ }
484+ } else {
485+ None
486+ }
487+ } )
488+ . collect ( ) ;
458489 local_labels. push ( LocalLabel {
459490 span : linted_local_decl. source_info . span ,
460491 destructors,
@@ -476,10 +507,23 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
476507 } ;
477508 let name = name. as_str ( ) ;
478509
510+ let mut seen_dyn = false ;
479511 let destructors = extract_component_with_significant_dtor ( tcx, param_env, observer_ty)
480512 . into_iter ( )
481- . filter_map ( |ty| ty_dtor_span ( tcx, ty) )
482- . map ( |span| DestructorLabel { span, name } )
513+ . filter_map ( |ty| {
514+ if let Some ( span) = ty_dtor_span ( tcx, ty) {
515+ Some ( DestructorLabel { span, name, dtor_kind : "concrete" } )
516+ } else if matches ! ( ty. kind( ) , ty:: Dynamic ( ..) ) {
517+ if seen_dyn {
518+ None
519+ } else {
520+ seen_dyn = true ;
521+ Some ( DestructorLabel { span : DUMMY_SP , name, dtor_kind : "dyn" } )
522+ }
523+ } else {
524+ None
525+ }
526+ } )
483527 . collect ( ) ;
484528 local_labels. push ( LocalLabel {
485529 span : observer_local_decl. source_info . span ,
@@ -582,5 +626,6 @@ impl Subdiagnostic for LocalLabel<'_> {
582626struct DestructorLabel < ' a > {
583627 #[ primary_span]
584628 span : Span ,
629+ dtor_kind : & ' static str ,
585630 name : & ' a str ,
586631}
0 commit comments