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 } ;
@@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
381382 intravisit:: walk_item ( self , item)
382383 }
383384 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+ }
384401 _ => intravisit:: walk_item ( self , item) ,
385402 } ,
386403 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+ }
387425 intravisit:: walk_trait_item ( self , trait_item) ;
388426 }
389427 Node :: ImplItem ( impl_item) => {
@@ -636,10 +674,6 @@ fn check_item<'tcx>(
636674 }
637675 }
638676 DefKind :: Impl { of_trait } => {
639- if of_trait {
640- worklist. push ( ( id. owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
641- }
642-
643677 // get DefIds from another query
644678 let local_def_ids = tcx
645679 . associated_item_def_ids ( id. owner_id )
@@ -648,7 +682,11 @@ fn check_item<'tcx>(
648682
649683 // And we access the Map here to get HirId from LocalDefId
650684 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+ {
652690 worklist. push ( ( id, ComesFromAllowExpect :: No ) ) ;
653691 } else if let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, id) {
654692 worklist. push ( ( id, comes_from_allow) ) ;
@@ -679,7 +717,7 @@ fn check_trait_item(
679717 use hir:: TraitItemKind :: { Const , Fn } ;
680718 if matches ! ( tcx. def_kind( id. owner_id) , DefKind :: AssocConst | DefKind :: AssocFn ) {
681719 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 ( .. ) )
683721 && let Some ( comes_from_allow) =
684722 has_allow_dead_code_or_lang_attr ( tcx, trait_item. owner_id . def_id )
685723 {
@@ -948,7 +986,8 @@ impl<'tcx> DeadVisitor<'tcx> {
948986 | DefKind :: TyAlias
949987 | DefKind :: Enum
950988 | 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" ) ,
952991 DefKind :: Struct => self . warn_dead_code ( def_id, "constructed" ) ,
953992 DefKind :: Variant | DefKind :: Field => bug ! ( "should be handled specially" ) ,
954993 _ => { }
@@ -973,18 +1012,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9731012 let module_items = tcx. hir_module_items ( module) ;
9741013
9751014 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 ) ;
9831016
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 } ) ;
9851037 }
9861038 }
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 ) ;
9881042 }
9891043
9901044 if !live_symbols. contains ( & item. owner_id . def_id ) {
@@ -997,7 +1051,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9971051 continue ;
9981052 }
9991053
1000- let def_kind = tcx. def_kind ( item. owner_id ) ;
10011054 if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum = def_kind {
10021055 let adt = tcx. adt_def ( item. owner_id ) ;
10031056 let mut dead_variants = Vec :: new ( ) ;
@@ -1044,8 +1097,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
10441097 for foreign_item in module_items. foreign_items ( ) {
10451098 visitor. check_definition ( foreign_item. owner_id . def_id ) ;
10461099 }
1047-
1048- // We do not warn trait items.
10491100}
10501101
10511102pub ( crate ) fn provide ( providers : & mut Providers ) {
0 commit comments