@@ -718,113 +718,81 @@ fn has_allow_dead_code_or_lang_attr(
718718 }
719719}
720720
721- // These check_* functions seeds items that
722- // 1) We want to explicitly consider as live:
723- // * Item annotated with #[allow(dead_code)]
724- // - This is done so that if we want to suppress warnings for a
725- // group of dead functions, we only have to annotate the "root".
726- // For example, if both `f` and `g` are dead and `f` calls `g`,
727- // then annotating `f` with `#[allow(dead_code)]` will suppress
728- // warning for both `f` and `g`.
729- // * Item annotated with #[lang=".."]
730- // - This is because lang items are always callable from elsewhere.
731- // or
732- // 2) We are not sure to be live or not
733- // * Implementations of traits and trait methods
734- fn check_item < ' tcx > (
721+ /// Examine the given definition and record it in the worklist if it should be considered live.
722+ ///
723+ /// We want to explicitly consider as live:
724+ /// * Item annotated with #[allow(dead_code)]
725+ /// This is done so that if we want to suppress warnings for a
726+ /// group of dead functions, we only have to annotate the "root".
727+ /// For example, if both `f` and `g` are dead and `f` calls `g`,
728+ /// then annotating `f` with `#[allow(dead_code)]` will suppress
729+ /// warning for both `f` and `g`.
730+ ///
731+ /// * Item annotated with #[lang=".."]
732+ /// Lang items are always callable from elsewhere.
733+ ///
734+ /// For trait methods and implementations of traits, we are not certain that the definitions are
735+ /// live at this stage. We record them in `unsolved_items` for later examination.
736+ fn maybe_record_as_seed < ' tcx > (
735737 tcx : TyCtxt < ' tcx > ,
738+ owner_id : hir:: OwnerId ,
736739 worklist : & mut Vec < ( LocalDefId , ComesFromAllowExpect ) > ,
737740 unsolved_items : & mut Vec < LocalDefId > ,
738- id : hir:: ItemId ,
739741) {
740- let allow_dead_code = has_allow_dead_code_or_lang_attr ( tcx, id . owner_id . def_id ) ;
742+ let allow_dead_code = has_allow_dead_code_or_lang_attr ( tcx, owner_id. def_id ) ;
741743 if let Some ( comes_from_allow) = allow_dead_code {
742- worklist. push ( ( id . owner_id . def_id , comes_from_allow) ) ;
744+ worklist. push ( ( owner_id. def_id , comes_from_allow) ) ;
743745 }
744746
745- match tcx. def_kind ( id . owner_id ) {
747+ match tcx. def_kind ( owner_id) {
746748 DefKind :: Enum => {
747- let item = tcx. hir_item ( id) ;
748- if let hir:: ItemKind :: Enum ( _, _, ref enum_def) = item. kind {
749- if let Some ( comes_from_allow) = allow_dead_code {
750- worklist. extend (
751- enum_def. variants . iter ( ) . map ( |variant| ( variant. def_id , comes_from_allow) ) ,
752- ) ;
749+ let adt = tcx. adt_def ( owner_id) ;
750+ if let Some ( comes_from_allow) = allow_dead_code {
751+ worklist. extend (
752+ adt. variants ( )
753+ . iter ( )
754+ . map ( |variant| ( variant. def_id . expect_local ( ) , comes_from_allow) ) ,
755+ ) ;
756+ }
757+ }
758+ DefKind :: AssocFn | DefKind :: AssocConst | DefKind :: AssocTy => {
759+ if allow_dead_code. is_none ( ) {
760+ let parent = tcx. local_parent ( owner_id. def_id ) ;
761+ match tcx. def_kind ( parent) {
762+ DefKind :: Impl { of_trait : false } | DefKind :: Trait => { }
763+ DefKind :: Impl { of_trait : true } => {
764+ // We only care about associated items of traits,
765+ // because they cannot be visited directly,
766+ // so we later mark them as live if their corresponding traits
767+ // or trait items and self types are both live,
768+ // but inherent associated items can be visited and marked directly.
769+ unsolved_items. push ( owner_id. def_id ) ;
770+ }
771+ _ => bug ! ( ) ,
753772 }
754773 }
755774 }
756775 DefKind :: Impl { of_trait } => {
757- if let Some ( comes_from_allow) =
758- has_allow_dead_code_or_lang_attr ( tcx, id. owner_id . def_id )
759- {
760- worklist. push ( ( id. owner_id . def_id , comes_from_allow) ) ;
761- } else if of_trait {
762- unsolved_items. push ( id. owner_id . def_id ) ;
763- }
764-
765- for def_id in tcx. associated_item_def_ids ( id. owner_id ) {
766- let local_def_id = def_id. expect_local ( ) ;
767-
768- if let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, local_def_id)
769- {
770- worklist. push ( ( local_def_id, comes_from_allow) ) ;
771- } else if of_trait {
772- // We only care about associated items of traits,
773- // because they cannot be visited directly,
774- // so we later mark them as live if their corresponding traits
775- // or trait items and self types are both live,
776- // but inherent associated items can be visited and marked directly.
777- unsolved_items. push ( local_def_id) ;
778- }
776+ if allow_dead_code. is_none ( ) && of_trait {
777+ unsolved_items. push ( owner_id. def_id ) ;
779778 }
780779 }
781780 DefKind :: GlobalAsm => {
782781 // global_asm! is always live.
783- worklist. push ( ( id . owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
782+ worklist. push ( ( owner_id. def_id , ComesFromAllowExpect :: No ) ) ;
784783 }
785784 DefKind :: Const => {
786- let item = tcx. hir_item ( id) ;
787- if let hir:: ItemKind :: Const ( ident, ..) = item. kind
788- && ident. name == kw:: Underscore
789- {
785+ if tcx. item_name ( owner_id. def_id ) == kw:: Underscore {
790786 // `const _` is always live, as that syntax only exists for the side effects
791787 // of type checking and evaluating the constant expression, and marking them
792788 // as dead code would defeat that purpose.
793- worklist. push ( ( id . owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
789+ worklist. push ( ( owner_id. def_id , ComesFromAllowExpect :: No ) ) ;
794790 }
795791 }
796792 _ => { }
797793 }
798794}
799795
800- fn check_trait_item (
801- tcx : TyCtxt < ' _ > ,
802- worklist : & mut Vec < ( LocalDefId , ComesFromAllowExpect ) > ,
803- id : hir:: TraitItemId ,
804- ) {
805- use hir:: TraitItemKind :: { Const , Fn , Type } ;
806-
807- let trait_item = tcx. hir_trait_item ( id) ;
808- if matches ! ( trait_item. kind, Const ( _, Some ( _) ) | Type ( _, Some ( _) ) | Fn ( ..) )
809- && let Some ( comes_from_allow) =
810- has_allow_dead_code_or_lang_attr ( tcx, trait_item. owner_id . def_id )
811- {
812- worklist. push ( ( trait_item. owner_id . def_id , comes_from_allow) ) ;
813- }
814- }
815-
816- fn check_foreign_item (
817- tcx : TyCtxt < ' _ > ,
818- worklist : & mut Vec < ( LocalDefId , ComesFromAllowExpect ) > ,
819- id : hir:: ForeignItemId ,
820- ) {
821- if matches ! ( tcx. def_kind( id. owner_id) , DefKind :: Static { .. } | DefKind :: Fn )
822- && let Some ( comes_from_allow) = has_allow_dead_code_or_lang_attr ( tcx, id. owner_id . def_id )
823- {
824- worklist. push ( ( id. owner_id . def_id , comes_from_allow) ) ;
825- }
826- }
827-
828796fn create_and_seed_worklist (
829797 tcx : TyCtxt < ' _ > ,
830798) -> ( Vec < ( LocalDefId , ComesFromAllowExpect ) > , Vec < LocalDefId > ) {
@@ -846,16 +814,8 @@ fn create_and_seed_worklist(
846814 . collect :: < Vec < _ > > ( ) ;
847815
848816 let crate_items = tcx. hir_crate_items ( ( ) ) ;
849- for id in crate_items. free_items ( ) {
850- check_item ( tcx, & mut worklist, & mut unsolved_impl_item, id) ;
851- }
852-
853- for id in crate_items. trait_items ( ) {
854- check_trait_item ( tcx, & mut worklist, id) ;
855- }
856-
857- for id in crate_items. foreign_items ( ) {
858- check_foreign_item ( tcx, & mut worklist, id) ;
817+ for id in crate_items. owners ( ) {
818+ maybe_record_as_seed ( tcx, id, & mut worklist, & mut unsolved_impl_item) ;
859819 }
860820
861821 ( worklist, unsolved_impl_item)
0 commit comments