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) => {
@@ -632,10 +670,6 @@ fn check_item<'tcx>(
632670 }
633671 }
634672 DefKind :: Impl { of_trait } => {
635- if of_trait {
636- worklist. push ( ( id. owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
637- }
638-
639673 // get DefIds from another query
640674 let local_def_ids = tcx
641675 . associated_item_def_ids ( id. owner_id )
@@ -644,7 +678,11 @@ fn check_item<'tcx>(
644678
645679 // And we access the Map here to get HirId from LocalDefId
646680 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+ {
648686 worklist. push ( ( id, ComesFromAllowExpect :: No ) ) ;
649687 } else if let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, id) {
650688 worklist. push ( ( id, comes_from_allow) ) ;
@@ -675,7 +713,7 @@ fn check_trait_item(
675713 use hir:: TraitItemKind :: { Const , Fn } ;
676714 if matches ! ( tcx. def_kind( id. owner_id) , DefKind :: AssocConst | DefKind :: AssocFn ) {
677715 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 ( .. ) )
679717 && let Some ( comes_from_allow) =
680718 has_allow_dead_code_or_lang_attr ( tcx, trait_item. owner_id . def_id )
681719 {
@@ -944,7 +982,8 @@ impl<'tcx> DeadVisitor<'tcx> {
944982 | DefKind :: TyAlias
945983 | DefKind :: Enum
946984 | 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" ) ,
948987 DefKind :: Struct => self . warn_dead_code ( def_id, "constructed" ) ,
949988 DefKind :: Variant | DefKind :: Field => bug ! ( "should be handled specially" ) ,
950989 _ => { }
@@ -969,18 +1008,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9691008 let module_items = tcx. hir_module_items ( module) ;
9701009
9711010 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 ) ;
9791012
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 } ) ;
9811033 }
9821034 }
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 ) ;
9841038 }
9851039
9861040 if !live_symbols. contains ( & item. owner_id . def_id ) {
@@ -993,7 +1047,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9931047 continue ;
9941048 }
9951049
996- let def_kind = tcx. def_kind ( item. owner_id ) ;
9971050 if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum = def_kind {
9981051 let adt = tcx. adt_def ( item. owner_id ) ;
9991052 let mut dead_variants = Vec :: new ( ) ;
@@ -1040,8 +1093,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
10401093 for foreign_item in module_items. foreign_items ( ) {
10411094 visitor. check_definition ( foreign_item. owner_id . def_id ) ;
10421095 }
1043-
1044- // We do not warn trait items.
10451096}
10461097
10471098pub ( crate ) fn provide ( providers : & mut Providers ) {
0 commit comments