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) => {
@@ -632,10 +670,6 @@ fn check_item<'tcx>(
632
670
}
633
671
}
634
672
DefKind :: Impl { of_trait } => {
635
- if of_trait {
636
- worklist. push ( ( id. owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
637
- }
638
-
639
673
// get DefIds from another query
640
674
let local_def_ids = tcx
641
675
. associated_item_def_ids ( id. owner_id )
@@ -644,7 +678,11 @@ fn check_item<'tcx>(
644
678
645
679
// And we access the Map here to get HirId from LocalDefId
646
680
for id in local_def_ids {
647
- if of_trait {
681
+ // for impl trait blocks, mark associate functions live if the trait is public
682
+ if of_trait
683
+ && ( !matches ! ( tcx. def_kind( id) , DefKind :: AssocFn )
684
+ || tcx. local_visibility ( id) == Visibility :: Public )
685
+ {
648
686
worklist. push ( ( id, ComesFromAllowExpect :: No ) ) ;
649
687
} else if let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, id) {
650
688
worklist. push ( ( id, comes_from_allow) ) ;
@@ -675,7 +713,7 @@ fn check_trait_item(
675
713
use hir:: TraitItemKind :: { Const , Fn } ;
676
714
if matches ! ( tcx. def_kind( id. owner_id) , DefKind :: AssocConst | DefKind :: AssocFn ) {
677
715
let trait_item = tcx. hir ( ) . trait_item ( id) ;
678
- if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Fn ( _ , hir :: TraitFn :: Provided ( _ ) ) )
716
+ if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Fn ( .. ) )
679
717
&& let Some ( comes_from_allow) =
680
718
has_allow_dead_code_or_lang_attr ( tcx, trait_item. owner_id . def_id )
681
719
{
@@ -944,7 +982,8 @@ impl<'tcx> DeadVisitor<'tcx> {
944
982
| DefKind :: TyAlias
945
983
| DefKind :: Enum
946
984
| DefKind :: Union
947
- | DefKind :: ForeignTy => self . warn_dead_code ( def_id, "used" ) ,
985
+ | DefKind :: ForeignTy
986
+ | DefKind :: Trait => self . warn_dead_code ( def_id, "used" ) ,
948
987
DefKind :: Struct => self . warn_dead_code ( def_id, "constructed" ) ,
949
988
DefKind :: Variant | DefKind :: Field => bug ! ( "should be handled specially" ) ,
950
989
_ => { }
@@ -969,18 +1008,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
969
1008
let module_items = tcx. hir_module_items ( module) ;
970
1009
971
1010
for item in module_items. items ( ) {
972
- if let hir:: ItemKind :: Impl ( impl_item) = tcx. hir ( ) . item ( item) . kind {
973
- let mut dead_items = Vec :: new ( ) ;
974
- for item in impl_item. items {
975
- let def_id = item. id . owner_id . def_id ;
976
- if !visitor. is_live_code ( def_id) {
977
- let name = tcx. item_name ( def_id. to_def_id ( ) ) ;
978
- let level = visitor. def_lint_level ( def_id) ;
1011
+ let def_kind = tcx. def_kind ( item. owner_id ) ;
979
1012
980
- dead_items. push ( DeadItem { def_id, name, level } )
1013
+ let mut dead_codes = Vec :: new ( ) ;
1014
+ // if we have diagnosed the trait, do not diagnose unused methods
1015
+ if matches ! ( def_kind, DefKind :: Impl { .. } )
1016
+ || ( def_kind == DefKind :: Trait && live_symbols. contains ( & item. owner_id . def_id ) )
1017
+ {
1018
+ for & def_id in tcx. associated_item_def_ids ( item. owner_id . def_id ) {
1019
+ // We have diagnosed unused methods in traits
1020
+ if matches ! ( def_kind, DefKind :: Impl { of_trait: true } )
1021
+ && tcx. def_kind ( def_id) == DefKind :: AssocFn
1022
+ || def_kind == DefKind :: Trait && tcx. def_kind ( def_id) != DefKind :: AssocFn
1023
+ {
1024
+ continue ;
1025
+ }
1026
+
1027
+ if let Some ( local_def_id) = def_id. as_local ( )
1028
+ && !visitor. is_live_code ( local_def_id)
1029
+ {
1030
+ let name = tcx. item_name ( def_id) ;
1031
+ let level = visitor. def_lint_level ( local_def_id) ;
1032
+ dead_codes. push ( DeadItem { def_id : local_def_id, name, level } ) ;
981
1033
}
982
1034
}
983
- visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_items, ReportOn :: NamedField ) ;
1035
+ }
1036
+ if !dead_codes. is_empty ( ) {
1037
+ visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_codes, ReportOn :: NamedField ) ;
984
1038
}
985
1039
986
1040
if !live_symbols. contains ( & item. owner_id . def_id ) {
@@ -993,7 +1047,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
993
1047
continue ;
994
1048
}
995
1049
996
- let def_kind = tcx. def_kind ( item. owner_id ) ;
997
1050
if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum = def_kind {
998
1051
let adt = tcx. adt_def ( item. owner_id ) ;
999
1052
let mut dead_variants = Vec :: new ( ) ;
@@ -1040,8 +1093,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
1040
1093
for foreign_item in module_items. foreign_items ( ) {
1041
1094
visitor. check_definition ( foreign_item. owner_id . def_id ) ;
1042
1095
}
1043
-
1044
- // We do not warn trait items.
1045
1096
}
1046
1097
1047
1098
pub ( crate ) fn provide ( providers : & mut Providers ) {
0 commit comments