@@ -10,14 +10,12 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
10
10
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
11
11
use rustc_hir:: intravisit:: { self , Visitor } ;
12
12
use rustc_hir:: { Node , PatKind , TyKind } ;
13
- use rustc_middle:: hir:: nested_filter;
14
13
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
15
14
use rustc_middle:: middle:: privacy;
16
15
use rustc_middle:: ty:: query:: Providers ;
17
16
use rustc_middle:: ty:: { self , DefIdTree , TyCtxt } ;
18
17
use rustc_session:: lint;
19
18
use rustc_span:: symbol:: { sym, Symbol } ;
20
- use rustc_span:: Span ;
21
19
use std:: mem;
22
20
23
21
// Any local node that may call something in its body block should be
@@ -647,41 +645,16 @@ struct DeadVisitor<'tcx> {
647
645
}
648
646
649
647
impl < ' tcx > DeadVisitor < ' tcx > {
650
- fn should_warn_about_item ( & mut self , item : & hir:: Item < ' _ > ) -> bool {
651
- let should_warn = matches ! (
652
- item. kind,
653
- hir:: ItemKind :: Static ( ..)
654
- | hir:: ItemKind :: Const ( ..)
655
- | hir:: ItemKind :: Fn ( ..)
656
- | hir:: ItemKind :: TyAlias ( ..)
657
- | hir:: ItemKind :: Enum ( ..)
658
- | hir:: ItemKind :: Struct ( ..)
659
- | hir:: ItemKind :: Union ( ..)
660
- ) ;
661
- should_warn && !self . symbol_is_live ( item. def_id )
662
- }
663
-
664
- fn should_warn_about_field ( & mut self , field : & hir:: FieldDef < ' _ > ) -> bool {
665
- let def_id = self . tcx . hir ( ) . local_def_id ( field. hir_id ) ;
666
- let field_type = self . tcx . type_of ( def_id) ;
667
- !field. is_positional ( )
668
- && !self . symbol_is_live ( def_id)
669
- && !field_type. is_phantom_data ( )
670
- && !has_allow_dead_code_or_lang_attr ( self . tcx , field. hir_id )
671
- }
672
-
673
- fn should_warn_about_variant ( & mut self , variant : & hir:: Variant < ' _ > ) -> bool {
674
- let def_id = self . tcx . hir ( ) . local_def_id ( variant. id ) ;
675
- !self . symbol_is_live ( def_id) && !has_allow_dead_code_or_lang_attr ( self . tcx , variant. id )
676
- }
677
-
678
- fn should_warn_about_foreign_item ( & mut self , fi : & hir:: ForeignItem < ' _ > ) -> bool {
679
- !self . symbol_is_live ( fi. def_id ) && !has_allow_dead_code_or_lang_attr ( self . tcx , fi. hir_id ( ) )
680
- }
681
-
682
- // id := HIR id of an item's definition.
683
- fn symbol_is_live ( & mut self , def_id : LocalDefId ) -> bool {
684
- self . live_symbols . contains ( & def_id)
648
+ fn should_warn_about_field ( & mut self , field : & ty:: FieldDef ) -> bool {
649
+ if self . live_symbols . contains ( & field. did . expect_local ( ) ) {
650
+ return false ;
651
+ }
652
+ let is_positional = field. name . as_str ( ) . starts_with ( |c : char | c. is_ascii_digit ( ) ) ;
653
+ if is_positional {
654
+ return false ;
655
+ }
656
+ let field_type = self . tcx . type_of ( field. did ) ;
657
+ !field_type. is_phantom_data ( )
685
658
}
686
659
687
660
fn warn_multiple_dead_codes (
@@ -790,154 +763,102 @@ impl<'tcx> DeadVisitor<'tcx> {
790
763
}
791
764
792
765
fn warn_dead_code ( & mut self , id : LocalDefId , participle : & str ) {
793
- if self . tcx . item_name ( id. to_def_id ( ) ) . as_str ( ) . starts_with ( '_' ) {
794
- return ;
795
- }
796
766
self . warn_multiple_dead_codes ( & [ id] , participle, None ) ;
797
767
}
798
- }
799
768
800
- impl < ' tcx > Visitor < ' tcx > for DeadVisitor < ' tcx > {
801
- type NestedFilter = nested_filter:: All ;
802
-
803
- /// Walk nested items in place so that we don't report dead-code
804
- /// on inner functions when the outer function is already getting
805
- /// an error. We could do this also by checking the parents, but
806
- /// this is how the code is setup and it seems harmless enough.
807
- fn nested_visit_map ( & mut self ) -> Self :: Map {
808
- self . tcx . hir ( )
809
- }
810
-
811
- fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
812
- if self . should_warn_about_item ( item) {
813
- // For most items, we want to highlight its identifier
814
- let participle = match item. kind {
815
- hir:: ItemKind :: Struct ( ..) => "constructed" , // Issue #52325
816
- _ => "used" ,
817
- } ;
818
- self . warn_dead_code ( item. def_id , participle) ;
819
- } else {
820
- // Only continue if we didn't warn
821
- intravisit:: walk_item ( self , item) ;
769
+ fn check_definition ( & mut self , def_id : LocalDefId ) {
770
+ if self . live_symbols . contains ( & def_id) {
771
+ return ;
822
772
}
823
- }
824
-
825
- // This visitor should only visit a single module at a time.
826
- fn visit_mod ( & mut self , _: & ' tcx hir:: Mod < ' tcx > , _: Span , _: hir:: HirId ) { }
827
-
828
- fn visit_enum_def (
829
- & mut self ,
830
- enum_definition : & ' tcx hir:: EnumDef < ' tcx > ,
831
- generics : & ' tcx hir:: Generics < ' tcx > ,
832
- item_id : hir:: HirId ,
833
- _: Span ,
834
- ) {
835
- intravisit:: walk_enum_def ( self , enum_definition, generics, item_id) ;
836
- let dead_variants = enum_definition
837
- . variants
838
- . iter ( )
839
- . filter_map ( |variant| {
840
- if self . should_warn_about_variant ( & variant) {
841
- Some ( DeadVariant {
842
- def_id : self . tcx . hir ( ) . local_def_id ( variant. id ) ,
843
- name : variant. ident . name ,
844
- level : self . tcx . lint_level_at_node ( lint:: builtin:: DEAD_CODE , variant. id ) . 0 ,
845
- } )
846
- } else {
847
- None
848
- }
849
- } )
850
- . collect ( ) ;
851
- self . warn_dead_fields_and_variants ( item_id. expect_owner ( ) , "constructed" , dead_variants)
852
- }
853
-
854
- fn visit_variant (
855
- & mut self ,
856
- variant : & ' tcx hir:: Variant < ' tcx > ,
857
- g : & ' tcx hir:: Generics < ' tcx > ,
858
- id : hir:: HirId ,
859
- ) {
860
- if !self . should_warn_about_variant ( & variant) {
861
- intravisit:: walk_variant ( self , variant, g, id) ;
773
+ let hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( def_id) ;
774
+ if has_allow_dead_code_or_lang_attr ( self . tcx , hir_id) {
775
+ return ;
862
776
}
863
- }
864
-
865
- fn visit_foreign_item ( & mut self , fi : & ' tcx hir:: ForeignItem < ' tcx > ) {
866
- if self . should_warn_about_foreign_item ( fi) {
867
- self . warn_dead_code ( fi. def_id , "used" ) ;
777
+ let Some ( name) = self . tcx . opt_item_name ( def_id. to_def_id ( ) ) else {
778
+ return
779
+ } ;
780
+ if name. as_str ( ) . starts_with ( '_' ) {
781
+ return ;
782
+ }
783
+ match self . tcx . def_kind ( def_id) {
784
+ DefKind :: AssocConst
785
+ | DefKind :: AssocFn
786
+ | DefKind :: Fn
787
+ | DefKind :: Static ( _)
788
+ | DefKind :: Const
789
+ | DefKind :: TyAlias
790
+ | DefKind :: Enum
791
+ | DefKind :: Union
792
+ | DefKind :: ForeignTy => self . warn_dead_code ( def_id, "used" ) ,
793
+ DefKind :: Struct => self . warn_dead_code ( def_id, "constructed" ) ,
794
+ DefKind :: Variant | DefKind :: Field => bug ! ( "should be handled specially" ) ,
795
+ _ => { }
868
796
}
869
- intravisit:: walk_foreign_item ( self , fi) ;
870
797
}
798
+ }
871
799
872
- fn visit_variant_data (
873
- & mut self ,
874
- def : & ' tcx hir:: VariantData < ' tcx > ,
875
- _: Symbol ,
876
- _: & hir:: Generics < ' _ > ,
877
- id : hir:: HirId ,
878
- _: rustc_span:: Span ,
879
- ) {
880
- intravisit:: walk_struct_def ( self , def) ;
881
- let dead_fields = def
882
- . fields ( )
883
- . iter ( )
884
- . filter_map ( |field| {
885
- if self . should_warn_about_field ( & field) {
886
- Some ( DeadVariant {
887
- def_id : self . tcx . hir ( ) . local_def_id ( field. hir_id ) ,
888
- name : field. ident . name ,
889
- level : self
890
- . tcx
891
- . lint_level_at_node ( lint:: builtin:: DEAD_CODE , field. hir_id )
892
- . 0 ,
893
- } )
894
- } else {
895
- None
896
- }
897
- } )
898
- . collect ( ) ;
899
- self . warn_dead_fields_and_variants ( self . tcx . hir ( ) . local_def_id ( id) , "read" , dead_fields)
900
- }
800
+ fn check_mod_deathness ( tcx : TyCtxt < ' _ > , module : LocalDefId ) {
801
+ let ( live_symbols, ignored_derived_traits) = tcx. live_symbols_and_ignored_derived_traits ( ( ) ) ;
802
+ let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits } ;
901
803
902
- fn visit_impl_item ( & mut self , impl_item : & ' tcx hir:: ImplItem < ' tcx > ) {
903
- match impl_item. kind {
904
- hir:: ImplItemKind :: Const ( _, body_id) => {
905
- if !self . symbol_is_live ( impl_item. def_id ) {
906
- self . warn_dead_code ( impl_item. def_id , "used" ) ;
907
- }
908
- self . visit_nested_body ( body_id)
804
+ let module_items = tcx. hir_module_items ( module) ;
805
+
806
+ for item in module_items. items ( ) {
807
+ if !live_symbols. contains ( & item. def_id ) {
808
+ let parent = tcx. local_parent ( item. def_id ) ;
809
+ if parent != module && !live_symbols. contains ( & parent) {
810
+ // We already have diagnosed something.
811
+ continue ;
909
812
}
910
- hir:: ImplItemKind :: Fn ( _, body_id) => {
911
- if !self . symbol_is_live ( impl_item. def_id ) {
912
- self . warn_dead_code ( impl_item. def_id , "used" ) ;
813
+ visitor. check_definition ( item. def_id ) ;
814
+ continue ;
815
+ }
816
+
817
+ let def_kind = tcx. def_kind ( item. def_id ) ;
818
+ if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum = def_kind {
819
+ let adt = tcx. adt_def ( item. def_id ) ;
820
+ let mut dead_variants = Vec :: new ( ) ;
821
+
822
+ for variant in adt. variants ( ) {
823
+ let def_id = variant. def_id . expect_local ( ) ;
824
+ if !live_symbols. contains ( & def_id) {
825
+ // Record to group diagnostics.
826
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
827
+ let level = tcx. lint_level_at_node ( lint:: builtin:: DEAD_CODE , hir_id) . 0 ;
828
+ dead_variants. push ( DeadVariant { def_id, name : variant. name , level } ) ;
829
+ continue ;
913
830
}
914
- self . visit_nested_body ( body_id)
831
+
832
+ let dead_fields = variant
833
+ . fields
834
+ . iter ( )
835
+ . filter_map ( |field| {
836
+ let def_id = field. did . expect_local ( ) ;
837
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
838
+ if visitor. should_warn_about_field ( & field) {
839
+ let level = tcx. lint_level_at_node ( lint:: builtin:: DEAD_CODE , hir_id) . 0 ;
840
+ Some ( DeadVariant { def_id, name : field. name , level } )
841
+ } else {
842
+ None
843
+ }
844
+ } )
845
+ . collect ( ) ;
846
+ visitor. warn_dead_fields_and_variants ( def_id, "read" , dead_fields)
915
847
}
916
- hir:: ImplItemKind :: TyAlias ( ..) => { }
848
+
849
+ visitor. warn_dead_fields_and_variants ( item. def_id , "constructed" , dead_variants) ;
917
850
}
918
851
}
919
852
920
- // Overwrite so that we don't warn the trait item itself.
921
- fn visit_trait_item ( & mut self , trait_item : & ' tcx hir:: TraitItem < ' tcx > ) {
922
- match trait_item. kind {
923
- hir:: TraitItemKind :: Const ( _, Some ( body_id) )
924
- | hir:: TraitItemKind :: Fn ( _, hir:: TraitFn :: Provided ( body_id) ) => {
925
- self . visit_nested_body ( body_id)
926
- }
927
- hir:: TraitItemKind :: Const ( _, None )
928
- | hir:: TraitItemKind :: Fn ( _, hir:: TraitFn :: Required ( _) )
929
- | hir:: TraitItemKind :: Type ( ..) => { }
930
- }
853
+ for impl_item in module_items. impl_items ( ) {
854
+ visitor. check_definition ( impl_item. def_id ) ;
931
855
}
932
- }
933
856
934
- fn check_mod_deathness ( tcx : TyCtxt < ' _ > , module : LocalDefId ) {
935
- let ( live_symbols, ignored_derived_traits) = tcx. live_symbols_and_ignored_derived_traits ( ( ) ) ;
936
- let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits } ;
937
- let ( module, _, module_id) = tcx. hir ( ) . get_module ( module) ;
938
- // Do not use an ItemLikeVisitor since we may want to skip visiting some items
939
- // when a surrounding one is warned against or `_`.
940
- intravisit:: walk_mod ( & mut visitor, module, module_id) ;
857
+ for foreign_item in module_items. foreign_items ( ) {
858
+ visitor. check_definition ( foreign_item. def_id ) ;
859
+ }
860
+
861
+ // We do not warn trait items.
941
862
}
942
863
943
864
pub ( crate ) fn provide ( providers : & mut Providers ) {
0 commit comments