44// is dead.
55
66use hir:: def_id:: { LocalDefIdMap , LocalDefIdSet } ;
7+ use hir:: ItemKind ;
78use rustc_data_structures:: unord:: UnordSet ;
89use rustc_errors:: MultiSpan ;
910use rustc_hir as hir;
@@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
1415use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
1516use rustc_middle:: middle:: privacy:: Level ;
1617use rustc_middle:: query:: Providers ;
17- use rustc_middle:: ty:: { self , TyCtxt } ;
18+ use rustc_middle:: ty:: { self , TyCtxt , Visibility } ;
1819use rustc_session:: lint;
1920use rustc_session:: lint:: builtin:: DEAD_CODE ;
2021use rustc_span:: symbol:: { sym, Symbol } ;
@@ -376,9 +377,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
376377 intravisit:: walk_item ( self , item)
377378 }
378379 hir:: ItemKind :: ForeignMod { .. } => { }
380+ hir:: ItemKind :: Trait ( ..) => {
381+ for impl_def_id in self . tcx . all_impls ( item. owner_id . to_def_id ( ) ) {
382+ if let Some ( local_def_id) = impl_def_id. as_local ( )
383+ && let ItemKind :: Impl ( impl_ref) =
384+ self . tcx . hir ( ) . expect_item ( local_def_id) . kind
385+ {
386+ // skip items
387+ // mark dependent traits live
388+ intravisit:: walk_generics ( self , impl_ref. generics ) ;
389+ // mark dependent parameters live
390+ intravisit:: walk_path ( self , impl_ref. of_trait . unwrap ( ) . path ) ;
391+ }
392+ }
393+
394+ intravisit:: walk_item ( self , item)
395+ }
379396 _ => intravisit:: walk_item ( self , item) ,
380397 } ,
381398 Node :: TraitItem ( trait_item) => {
399+ // mark corresponing ImplTerm live
400+ let trait_item_id = trait_item. owner_id . to_def_id ( ) ;
401+ if let Some ( trait_id) = self . tcx . trait_of_item ( trait_item_id) {
402+ // mark the trait live
403+ self . check_def_id ( trait_id) ;
404+
405+ for impl_id in self . tcx . all_impls ( trait_id) {
406+ if let Some ( local_impl_id) = impl_id. as_local ( )
407+ && let ItemKind :: Impl ( impl_ref) =
408+ self . tcx . hir ( ) . expect_item ( local_impl_id) . kind
409+ {
410+ // mark self_ty live
411+ intravisit:: walk_ty ( self , impl_ref. self_ty ) ;
412+ if let Some ( & impl_item_id) =
413+ self . tcx . impl_item_implementor_ids ( impl_id) . get ( & trait_item_id)
414+ {
415+ self . check_def_id ( impl_item_id) ;
416+ }
417+ }
418+ }
419+ }
382420 intravisit:: walk_trait_item ( self , trait_item) ;
383421 }
384422 Node :: ImplItem ( impl_item) => {
@@ -627,10 +665,6 @@ fn check_item<'tcx>(
627665 }
628666 }
629667 DefKind :: Impl { of_trait } => {
630- if of_trait {
631- worklist. push ( ( id. owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
632- }
633-
634668 // get DefIds from another query
635669 let local_def_ids = tcx
636670 . associated_item_def_ids ( id. owner_id )
@@ -639,7 +673,11 @@ fn check_item<'tcx>(
639673
640674 // And we access the Map here to get HirId from LocalDefId
641675 for id in local_def_ids {
642- if of_trait {
676+ // for impl trait blocks, mark associate functions live if the trait is public
677+ if of_trait
678+ && ( !matches ! ( tcx. def_kind( id) , DefKind :: AssocFn )
679+ || tcx. local_visibility ( id) == Visibility :: Public )
680+ {
643681 worklist. push ( ( id, ComesFromAllowExpect :: No ) ) ;
644682 } else if let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, id) {
645683 worklist. push ( ( id, comes_from_allow) ) ;
@@ -670,7 +708,7 @@ fn check_trait_item(
670708 use hir:: TraitItemKind :: { Const , Fn } ;
671709 if matches ! ( tcx. def_kind( id. owner_id) , DefKind :: AssocConst | DefKind :: AssocFn ) {
672710 let trait_item = tcx. hir ( ) . trait_item ( id) ;
673- if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Fn ( _ , hir :: TraitFn :: Provided ( _ ) ) )
711+ if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Fn ( .. ) )
674712 && let Some ( comes_from_allow) =
675713 has_allow_dead_code_or_lang_attr ( tcx, trait_item. owner_id . def_id )
676714 {
@@ -939,7 +977,8 @@ impl<'tcx> DeadVisitor<'tcx> {
939977 | DefKind :: TyAlias
940978 | DefKind :: Enum
941979 | DefKind :: Union
942- | DefKind :: ForeignTy => self . warn_dead_code ( def_id, "used" ) ,
980+ | DefKind :: ForeignTy
981+ | DefKind :: Trait => self . warn_dead_code ( def_id, "used" ) ,
943982 DefKind :: Struct => self . warn_dead_code ( def_id, "constructed" ) ,
944983 DefKind :: Variant | DefKind :: Field => bug ! ( "should be handled specially" ) ,
945984 _ => { }
@@ -964,18 +1003,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9641003 let module_items = tcx. hir_module_items ( module) ;
9651004
9661005 for item in module_items. items ( ) {
967- if let hir:: ItemKind :: Impl ( impl_item) = tcx. hir ( ) . item ( item) . kind {
968- let mut dead_items = Vec :: new ( ) ;
969- for item in impl_item. items {
970- let def_id = item. id . owner_id . def_id ;
971- if !visitor. is_live_code ( def_id) {
972- let name = tcx. item_name ( def_id. to_def_id ( ) ) ;
973- let level = visitor. def_lint_level ( def_id) ;
1006+ let def_kind = tcx. def_kind ( item. owner_id ) ;
9741007
975- dead_items. push ( DeadItem { def_id, name, level } )
1008+ let mut dead_codes = Vec :: new ( ) ;
1009+ // if we have diagnosed the trait, do not diagnose unused methods
1010+ if matches ! ( def_kind, DefKind :: Impl { .. } )
1011+ || ( def_kind == DefKind :: Trait && live_symbols. contains ( & item. owner_id . def_id ) )
1012+ {
1013+ for & def_id in tcx. associated_item_def_ids ( item. owner_id . def_id ) {
1014+ // We have diagnosed unused methods in traits
1015+ if matches ! ( def_kind, DefKind :: Impl { of_trait: true } )
1016+ && tcx. def_kind ( def_id) == DefKind :: AssocFn
1017+ || def_kind == DefKind :: Trait && tcx. def_kind ( def_id) != DefKind :: AssocFn
1018+ {
1019+ continue ;
1020+ }
1021+
1022+ if let Some ( local_def_id) = def_id. as_local ( )
1023+ && !visitor. is_live_code ( local_def_id)
1024+ {
1025+ let name = tcx. item_name ( def_id) ;
1026+ let level = visitor. def_lint_level ( local_def_id) ;
1027+ dead_codes. push ( DeadItem { def_id : local_def_id, name, level } ) ;
9761028 }
9771029 }
978- visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_items, ReportOn :: NamedField ) ;
1030+ }
1031+ if !dead_codes. is_empty ( ) {
1032+ visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_codes, ReportOn :: NamedField ) ;
9791033 }
9801034
9811035 if !live_symbols. contains ( & item. owner_id . def_id ) {
@@ -988,7 +1042,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9881042 continue ;
9891043 }
9901044
991- let def_kind = tcx. def_kind ( item. owner_id ) ;
9921045 if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum = def_kind {
9931046 let adt = tcx. adt_def ( item. owner_id ) ;
9941047 let mut dead_variants = Vec :: new ( ) ;
@@ -1035,8 +1088,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
10351088 for foreign_item in module_items. foreign_items ( ) {
10361089 visitor. check_definition ( foreign_item. owner_id . def_id ) ;
10371090 }
1038-
1039- // We do not warn trait items.
10401091}
10411092
10421093pub ( crate ) fn provide ( providers : & mut Providers ) {
0 commit comments