3
3
// expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else
4
4
// is dead.
5
5
6
- use hir:: def_id:: { LocalDefIdMap , LocalDefIdSet } ;
6
+ use hir:: def_id:: { DefIdMap , LocalDefIdMap , LocalDefIdSet } ;
7
7
use hir:: ItemKind ;
8
8
use rustc_data_structures:: unord:: UnordSet ;
9
9
use rustc_errors:: MultiSpan ;
@@ -80,6 +80,7 @@ struct MarkSymbolVisitor<'tcx> {
80
80
// and the span of their respective impl (i.e., part of the derive
81
81
// macro)
82
82
ignored_derived_traits : LocalDefIdMap < Vec < ( DefId , DefId ) > > ,
83
+ impl_item_trait_item_ids_cache : DefIdMap < DefIdMap < DefId > > ,
83
84
}
84
85
85
86
impl < ' tcx > MarkSymbolVisitor < ' tcx > {
@@ -490,7 +491,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
490
491
let mut ready;
491
492
( ready, unsolved_impl_items) =
492
493
unsolved_impl_items. into_iter ( ) . partition ( |& ( impl_id, impl_item_id) | {
493
- self . impl_item_with_used_self_and_trait_term ( impl_id, impl_item_id)
494
+ self . impl_item_with_used_self_and_trait_item ( impl_id, impl_item_id)
494
495
} ) ;
495
496
496
497
while !ready. is_empty ( ) {
@@ -500,12 +501,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
500
501
501
502
( ready, unsolved_impl_items) =
502
503
unsolved_impl_items. into_iter ( ) . partition ( |& ( impl_id, impl_item_id) | {
503
- self . impl_item_with_used_self_and_trait_term ( impl_id, impl_item_id)
504
+ self . impl_item_with_used_self_and_trait_item ( impl_id, impl_item_id)
504
505
} ) ;
505
506
}
506
507
}
507
508
508
- fn impl_item_with_used_self_and_trait_term (
509
+ fn impl_item_with_used_self_and_trait_item (
509
510
& mut self ,
510
511
impl_id : hir:: ItemId ,
511
512
impl_item_id : LocalDefId ,
@@ -520,20 +521,32 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
520
521
// for the public method, we don't know the trait item is used or not,
521
522
// so we mark the method live if the self is used
522
523
return self . live_symbols . contains ( & local_def_id) ;
523
- } else if let Some ( trait_item_id) = self
524
- . tcx
525
- . impl_item_trait_item_ids ( impl_id. owner_id . to_def_id ( ) )
526
- . get ( & impl_item_id. to_def_id ( ) )
524
+ }
525
+
526
+ let impl_id = impl_id. owner_id . to_def_id ( ) ;
527
+ let impl_item_trait_item_ids = self
528
+ . impl_item_trait_item_ids_cache
529
+ . entry ( impl_id)
530
+ . or_insert_with ( || Self :: impl_item_trait_item_ids ( self . tcx , impl_id) ) ;
531
+
532
+ if let Some ( trait_item_id) = impl_item_trait_item_ids. get ( & impl_item_id. to_def_id ( ) )
527
533
&& let Some ( local_id) = trait_item_id. as_local ( )
528
534
{
529
- // for the private method, we can know the trait item is ued or not,
535
+ // for the private method, we can know the trait item is used or not,
530
536
// so we mark the method live if the self is used and the trait item is used
531
537
return self . live_symbols . contains ( & local_id)
532
538
&& self . live_symbols . contains ( & local_def_id) ;
533
539
}
534
540
}
535
541
false
536
542
}
543
+
544
+ fn impl_item_trait_item_ids ( tcx : TyCtxt < ' tcx > , impl_id : DefId ) -> DefIdMap < DefId > {
545
+ tcx. associated_items ( impl_id)
546
+ . in_definition_order ( )
547
+ . filter_map ( |item| item. trait_item_def_id . map ( |trait_item| ( item. def_id , trait_item) ) )
548
+ . collect ( )
549
+ }
537
550
}
538
551
539
552
impl < ' tcx > Visitor < ' tcx > for MarkSymbolVisitor < ' tcx > {
@@ -888,6 +901,7 @@ fn live_symbols_and_ignored_derived_traits(
888
901
ignore_variant_stack : vec ! [ ] ,
889
902
struct_constructors,
890
903
ignored_derived_traits : Default :: default ( ) ,
904
+ impl_item_trait_item_ids_cache : Default :: default ( ) ,
891
905
} ;
892
906
symbol_visitor. mark_live_symbols ( ) ;
893
907
symbol_visitor. solve_rest_impl_items ( unsolved_impl_items) ;
0 commit comments