4
4
// is dead.
5
5
6
6
use hir:: def_id:: { LocalDefIdMap , LocalDefIdSet } ;
7
+ use hir:: ItemKind ;
7
8
use rustc_data_structures:: unord:: UnordSet ;
8
9
use rustc_errors:: MultiSpan ;
9
10
use rustc_hir as hir;
@@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
14
15
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
15
16
use rustc_middle:: middle:: privacy:: Level ;
16
17
use rustc_middle:: query:: Providers ;
17
- use rustc_middle:: ty:: { self , TyCtxt } ;
18
+ use rustc_middle:: ty:: { self , TyCtxt , Visibility } ;
18
19
use rustc_session:: lint;
19
20
use rustc_session:: lint:: builtin:: DEAD_CODE ;
20
21
use rustc_span:: symbol:: { sym, Symbol } ;
@@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
381
382
intravisit:: walk_item ( self , item)
382
383
}
383
384
hir:: ItemKind :: ForeignMod { .. } => { }
385
+ hir:: ItemKind :: Trait ( ..) => {
386
+ for impl_def_id in self . tcx . all_impls ( item. owner_id . to_def_id ( ) ) {
387
+ if let Some ( local_def_id) = impl_def_id. as_local ( )
388
+ && let ItemKind :: Impl ( impl_ref) =
389
+ self . tcx . hir ( ) . expect_item ( local_def_id) . kind
390
+ {
391
+ // skip items
392
+ // mark dependent traits live
393
+ intravisit:: walk_generics ( self , impl_ref. generics ) ;
394
+ // mark dependent parameters live
395
+ intravisit:: walk_path ( self , impl_ref. of_trait . unwrap ( ) . path ) ;
396
+ }
397
+ }
398
+
399
+ intravisit:: walk_item ( self , item)
400
+ }
384
401
_ => intravisit:: walk_item ( self , item) ,
385
402
} ,
386
403
Node :: TraitItem ( trait_item) => {
404
+ // mark corresponing ImplTerm live
405
+ let trait_item_id = trait_item. owner_id . to_def_id ( ) ;
406
+ if let Some ( trait_id) = self . tcx . trait_of_item ( trait_item_id) {
407
+ // mark the trait live
408
+ self . check_def_id ( trait_id) ;
409
+
410
+ for impl_id in self . tcx . all_impls ( trait_id) {
411
+ if let Some ( local_impl_id) = impl_id. as_local ( )
412
+ && let ItemKind :: Impl ( impl_ref) =
413
+ self . tcx . hir ( ) . expect_item ( local_impl_id) . kind
414
+ {
415
+ // mark self_ty live
416
+ intravisit:: walk_ty ( self , impl_ref. self_ty ) ;
417
+ if let Some ( & impl_item_id) =
418
+ self . tcx . impl_item_implementor_ids ( impl_id) . get ( & trait_item_id)
419
+ {
420
+ self . check_def_id ( impl_item_id) ;
421
+ }
422
+ }
423
+ }
424
+ }
387
425
intravisit:: walk_trait_item ( self , trait_item) ;
388
426
}
389
427
Node :: ImplItem ( impl_item) => {
@@ -636,10 +674,6 @@ fn check_item<'tcx>(
636
674
}
637
675
}
638
676
DefKind :: Impl { of_trait } => {
639
- if of_trait {
640
- worklist. push ( ( id. owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
641
- }
642
-
643
677
// get DefIds from another query
644
678
let local_def_ids = tcx
645
679
. associated_item_def_ids ( id. owner_id )
@@ -648,7 +682,11 @@ fn check_item<'tcx>(
648
682
649
683
// And we access the Map here to get HirId from LocalDefId
650
684
for id in local_def_ids {
651
- if of_trait {
685
+ // for impl trait blocks, mark associate functions live if the trait is public
686
+ if of_trait
687
+ && ( !matches ! ( tcx. def_kind( id) , DefKind :: AssocFn )
688
+ || tcx. local_visibility ( id) == Visibility :: Public )
689
+ {
652
690
worklist. push ( ( id, ComesFromAllowExpect :: No ) ) ;
653
691
} else if let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, id) {
654
692
worklist. push ( ( id, comes_from_allow) ) ;
@@ -679,7 +717,7 @@ fn check_trait_item(
679
717
use hir:: TraitItemKind :: { Const , Fn } ;
680
718
if matches ! ( tcx. def_kind( id. owner_id) , DefKind :: AssocConst | DefKind :: AssocFn ) {
681
719
let trait_item = tcx. hir ( ) . trait_item ( id) ;
682
- if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Fn ( _ , hir :: TraitFn :: Provided ( _ ) ) )
720
+ if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Fn ( .. ) )
683
721
&& let Some ( comes_from_allow) =
684
722
has_allow_dead_code_or_lang_attr ( tcx, trait_item. owner_id . def_id )
685
723
{
@@ -948,7 +986,8 @@ impl<'tcx> DeadVisitor<'tcx> {
948
986
| DefKind :: TyAlias
949
987
| DefKind :: Enum
950
988
| DefKind :: Union
951
- | DefKind :: ForeignTy => self . warn_dead_code ( def_id, "used" ) ,
989
+ | DefKind :: ForeignTy
990
+ | DefKind :: Trait => self . warn_dead_code ( def_id, "used" ) ,
952
991
DefKind :: Struct => self . warn_dead_code ( def_id, "constructed" ) ,
953
992
DefKind :: Variant | DefKind :: Field => bug ! ( "should be handled specially" ) ,
954
993
_ => { }
@@ -973,18 +1012,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
973
1012
let module_items = tcx. hir_module_items ( module) ;
974
1013
975
1014
for item in module_items. items ( ) {
976
- if let hir:: ItemKind :: Impl ( impl_item) = tcx. hir ( ) . item ( item) . kind {
977
- let mut dead_items = Vec :: new ( ) ;
978
- for item in impl_item. items {
979
- let def_id = item. id . owner_id . def_id ;
980
- if !visitor. is_live_code ( def_id) {
981
- let name = tcx. item_name ( def_id. to_def_id ( ) ) ;
982
- let level = visitor. def_lint_level ( def_id) ;
1015
+ let def_kind = tcx. def_kind ( item. owner_id ) ;
983
1016
984
- dead_items. push ( DeadItem { def_id, name, level } )
1017
+ let mut dead_codes = Vec :: new ( ) ;
1018
+ // if we have diagnosed the trait, do not diagnose unused methods
1019
+ if matches ! ( def_kind, DefKind :: Impl { .. } )
1020
+ || ( def_kind == DefKind :: Trait && live_symbols. contains ( & item. owner_id . def_id ) )
1021
+ {
1022
+ for & def_id in tcx. associated_item_def_ids ( item. owner_id . def_id ) {
1023
+ // We have diagnosed unused methods in traits
1024
+ if matches ! ( def_kind, DefKind :: Impl { of_trait: true } )
1025
+ && tcx. def_kind ( def_id) == DefKind :: AssocFn
1026
+ || def_kind == DefKind :: Trait && tcx. def_kind ( def_id) != DefKind :: AssocFn
1027
+ {
1028
+ continue ;
1029
+ }
1030
+
1031
+ if let Some ( local_def_id) = def_id. as_local ( )
1032
+ && !visitor. is_live_code ( local_def_id)
1033
+ {
1034
+ let name = tcx. item_name ( def_id) ;
1035
+ let level = visitor. def_lint_level ( local_def_id) ;
1036
+ dead_codes. push ( DeadItem { def_id : local_def_id, name, level } ) ;
985
1037
}
986
1038
}
987
- visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_items, ReportOn :: NamedField ) ;
1039
+ }
1040
+ if !dead_codes. is_empty ( ) {
1041
+ visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_codes, ReportOn :: NamedField ) ;
988
1042
}
989
1043
990
1044
if !live_symbols. contains ( & item. owner_id . def_id ) {
@@ -997,7 +1051,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
997
1051
continue ;
998
1052
}
999
1053
1000
- let def_kind = tcx. def_kind ( item. owner_id ) ;
1001
1054
if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum = def_kind {
1002
1055
let adt = tcx. adt_def ( item. owner_id ) ;
1003
1056
let mut dead_variants = Vec :: new ( ) ;
@@ -1044,8 +1097,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
1044
1097
for foreign_item in module_items. foreign_items ( ) {
1045
1098
visitor. check_definition ( foreign_item. owner_id . def_id ) ;
1046
1099
}
1047
-
1048
- // We do not warn trait items.
1049
1100
}
1050
1101
1051
1102
pub ( crate ) fn provide ( providers : & mut Providers ) {
0 commit comments