1
- // This implements the dead-code warning pass. It follows middle::reachable
2
- // closely. The idea is that all reachable symbols are live, codes called
3
- // from live codes are live, and everything else is dead.
1
+ // This implements the dead-code warning pass.
2
+ // All reachable symbols are live, code called from live code is live, code with certain lint
3
+ // expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else
4
+ // is dead.
4
5
5
6
use hir:: def_id:: { LocalDefIdMap , LocalDefIdSet } ;
6
7
use itertools:: Itertools ;
@@ -747,7 +748,7 @@ fn live_symbols_and_ignored_derived_traits(
747
748
( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits )
748
749
}
749
750
750
- struct DeadVariant {
751
+ struct DeadItem {
751
752
def_id : LocalDefId ,
752
753
name : Symbol ,
753
754
level : lint:: Level ,
@@ -785,7 +786,13 @@ impl<'tcx> DeadVisitor<'tcx> {
785
786
ShouldWarnAboutField :: Yes ( is_positional)
786
787
}
787
788
788
- fn warn_multiple_dead_codes (
789
+ // # Panics
790
+ // All `dead_codes` must have the same lint level, otherwise we will intentionally ICE.
791
+ // This is because we emit a multi-spanned lint using the lint level of the `dead_codes`'s
792
+ // first local def id.
793
+ // Prefer calling `Self.warn_dead_code` or `Self.warn_dead_code_grouped_by_lint_level`
794
+ // since those methods group by lint level before calling this method.
795
+ fn lint_at_single_level (
789
796
& self ,
790
797
dead_codes : & [ LocalDefId ] ,
791
798
participle : & str ,
@@ -796,6 +803,15 @@ impl<'tcx> DeadVisitor<'tcx> {
796
803
return ;
797
804
} ;
798
805
let tcx = self . tcx ;
806
+
807
+ let first_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( first_id) ;
808
+ let first_lint_level = tcx. lint_level_at_node ( lint:: builtin:: DEAD_CODE , first_hir_id) . 0 ;
809
+ assert ! ( dead_codes. iter( ) . skip( 1 ) . all( |id| {
810
+ let hir_id = tcx. hir( ) . local_def_id_to_hir_id( * id) ;
811
+ let level = tcx. lint_level_at_node( lint:: builtin:: DEAD_CODE , hir_id) . 0 ;
812
+ level == first_lint_level
813
+ } ) ) ;
814
+
799
815
let names: Vec < _ > =
800
816
dead_codes. iter ( ) . map ( |& def_id| tcx. item_name ( def_id. to_def_id ( ) ) ) . collect ( ) ;
801
817
let spans: Vec < _ > = dead_codes
@@ -876,31 +892,26 @@ impl<'tcx> DeadVisitor<'tcx> {
876
892
}
877
893
} ;
878
894
879
- self . tcx . emit_spanned_lint (
880
- lint,
881
- tcx. hir ( ) . local_def_id_to_hir_id ( first_id) ,
882
- MultiSpan :: from_spans ( spans) ,
883
- diag,
884
- ) ;
895
+ self . tcx . emit_spanned_lint ( lint, first_hir_id, MultiSpan :: from_spans ( spans) , diag) ;
885
896
}
886
897
887
- fn warn_dead_fields_and_variants (
898
+ fn warn_multiple (
888
899
& self ,
889
900
def_id : LocalDefId ,
890
901
participle : & str ,
891
- dead_codes : Vec < DeadVariant > ,
902
+ dead_codes : Vec < DeadItem > ,
892
903
is_positional : bool ,
893
904
) {
894
905
let mut dead_codes = dead_codes
895
906
. iter ( )
896
907
. filter ( |v| !v. name . as_str ( ) . starts_with ( '_' ) )
897
- . collect :: < Vec < & DeadVariant > > ( ) ;
908
+ . collect :: < Vec < & DeadItem > > ( ) ;
898
909
if dead_codes. is_empty ( ) {
899
910
return ;
900
911
}
901
912
dead_codes. sort_by_key ( |v| v. level ) ;
902
913
for ( _, group) in & dead_codes. into_iter ( ) . group_by ( |v| v. level ) {
903
- self . warn_multiple_dead_codes (
914
+ self . lint_at_single_level (
904
915
& group. map ( |v| v. def_id ) . collect :: < Vec < _ > > ( ) ,
905
916
participle,
906
917
Some ( def_id) ,
@@ -910,7 +921,7 @@ impl<'tcx> DeadVisitor<'tcx> {
910
921
}
911
922
912
923
fn warn_dead_code ( & mut self , id : LocalDefId , participle : & str ) {
913
- self . warn_multiple_dead_codes ( & [ id] , participle, None , false ) ;
924
+ self . lint_at_single_level ( & [ id] , participle, None , false ) ;
914
925
}
915
926
916
927
fn check_definition ( & mut self , def_id : LocalDefId ) {
@@ -954,17 +965,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
954
965
if let hir:: ItemKind :: Impl ( impl_item) = tcx. hir ( ) . item ( item) . kind {
955
966
let mut dead_items = Vec :: new ( ) ;
956
967
for item in impl_item. items {
957
- let did = item. id . owner_id . def_id ;
958
- if !visitor. is_live_code ( did) {
959
- dead_items. push ( did)
968
+ let def_id = item. id . owner_id . def_id ;
969
+ if !visitor. is_live_code ( def_id) {
970
+ let name = tcx. item_name ( def_id. to_def_id ( ) ) ;
971
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
972
+ let level = tcx. lint_level_at_node ( lint:: builtin:: DEAD_CODE , hir_id) . 0 ;
973
+
974
+ dead_items. push ( DeadItem { def_id, name, level } )
960
975
}
961
976
}
962
- visitor. warn_multiple_dead_codes (
963
- & dead_items,
964
- "used" ,
965
- Some ( item. owner_id . def_id ) ,
966
- false ,
967
- ) ;
977
+ visitor. warn_multiple ( item. owner_id . def_id , "used" , dead_items, false ) ;
968
978
}
969
979
970
980
if !live_symbols. contains ( & item. owner_id . def_id ) {
@@ -988,7 +998,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
988
998
// Record to group diagnostics.
989
999
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
990
1000
let level = tcx. lint_level_at_node ( lint:: builtin:: DEAD_CODE , hir_id) . 0 ;
991
- dead_variants. push ( DeadVariant { def_id, name : variant. name , level } ) ;
1001
+ dead_variants. push ( DeadItem { def_id, name : variant. name , level } ) ;
992
1002
continue ;
993
1003
}
994
1004
@@ -1013,21 +1023,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
1013
1023
hir_id,
1014
1024
)
1015
1025
. 0 ;
1016
- Some ( DeadVariant { def_id, name : field. name , level } )
1026
+ Some ( DeadItem { def_id, name : field. name , level } )
1017
1027
} else {
1018
1028
None
1019
1029
}
1020
1030
} )
1021
1031
. collect ( ) ;
1022
- visitor. warn_dead_fields_and_variants ( def_id, "read" , dead_fields, is_positional)
1032
+ visitor. warn_multiple ( def_id, "read" , dead_fields, is_positional) ;
1023
1033
}
1024
1034
1025
- visitor. warn_dead_fields_and_variants (
1026
- item. owner_id . def_id ,
1027
- "constructed" ,
1028
- dead_variants,
1029
- false ,
1030
- ) ;
1035
+ visitor. warn_multiple ( item. owner_id . def_id , "constructed" , dead_variants, false ) ;
1031
1036
}
1032
1037
}
1033
1038
0 commit comments