@@ -718,113 +718,81 @@ fn has_allow_dead_code_or_lang_attr(
718
718
}
719
719
}
720
720
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 > (
735
737
tcx : TyCtxt < ' tcx > ,
738
+ owner_id : hir:: OwnerId ,
736
739
worklist : & mut Vec < ( LocalDefId , ComesFromAllowExpect ) > ,
737
740
unsolved_items : & mut Vec < LocalDefId > ,
738
- id : hir:: ItemId ,
739
741
) {
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 ) ;
741
743
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) ) ;
743
745
}
744
746
745
- match tcx. def_kind ( id . owner_id ) {
747
+ match tcx. def_kind ( owner_id) {
746
748
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 ! ( ) ,
753
772
}
754
773
}
755
774
}
756
775
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 ) ;
779
778
}
780
779
}
781
780
DefKind :: GlobalAsm => {
782
781
// global_asm! is always live.
783
- worklist. push ( ( id . owner_id . def_id , ComesFromAllowExpect :: No ) ) ;
782
+ worklist. push ( ( owner_id. def_id , ComesFromAllowExpect :: No ) ) ;
784
783
}
785
784
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 {
790
786
// `const _` is always live, as that syntax only exists for the side effects
791
787
// of type checking and evaluating the constant expression, and marking them
792
788
// 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 ) ) ;
794
790
}
795
791
}
796
792
_ => { }
797
793
}
798
794
}
799
795
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
-
828
796
fn create_and_seed_worklist (
829
797
tcx : TyCtxt < ' _ > ,
830
798
) -> ( Vec < ( LocalDefId , ComesFromAllowExpect ) > , Vec < LocalDefId > ) {
@@ -846,16 +814,8 @@ fn create_and_seed_worklist(
846
814
. collect :: < Vec < _ > > ( ) ;
847
815
848
816
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) ;
859
819
}
860
820
861
821
( worklist, unsolved_impl_item)
0 commit comments