4
4
5
5
use itertools:: Itertools ;
6
6
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
7
- use rustc_errors:: { pluralize , Applicability , MultiSpan } ;
7
+ use rustc_errors:: MultiSpan ;
8
8
use rustc_hir as hir;
9
9
use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
10
10
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -18,7 +18,10 @@ use rustc_session::lint;
18
18
use rustc_span:: symbol:: { sym, Symbol } ;
19
19
use std:: mem;
20
20
21
- use crate :: errors:: UselessAssignment ;
21
+ use crate :: errors:: {
22
+ ChangeFieldsToBeOfUnitType , IgnoredDerivedImpls , MultipleDeadCodes , ParentInfo ,
23
+ UselessAssignment ,
24
+ } ;
22
25
23
26
// Any local node that may call something in its body block should be
24
27
// explored. For example, if it's a live Node::Item that is a
@@ -693,99 +696,89 @@ impl<'tcx> DeadVisitor<'tcx> {
693
696
parent_item : Option < LocalDefId > ,
694
697
is_positional : bool ,
695
698
) {
696
- if let Some ( & first_id) = dead_codes. first ( ) {
697
- let tcx = self . tcx ;
698
- let names: Vec < _ > = dead_codes
699
- . iter ( )
700
- . map ( |& def_id| tcx. item_name ( def_id. to_def_id ( ) ) . to_string ( ) )
701
- . collect ( ) ;
702
- let spans: Vec < _ > = dead_codes
703
- . iter ( )
704
- . map ( |& def_id| match tcx. def_ident_span ( def_id) {
705
- Some ( s) => s. with_ctxt ( tcx. def_span ( def_id) . ctxt ( ) ) ,
706
- None => tcx. def_span ( def_id) ,
699
+ let Some ( & first_id) = dead_codes. first ( ) else {
700
+ return ;
701
+ } ;
702
+ let tcx = self . tcx ;
703
+ let names: Vec < _ > =
704
+ dead_codes. iter ( ) . map ( |& def_id| tcx. item_name ( def_id. to_def_id ( ) ) ) . collect ( ) ;
705
+ let spans: Vec < _ > = dead_codes
706
+ . iter ( )
707
+ . map ( |& def_id| match tcx. def_ident_span ( def_id) {
708
+ Some ( s) => s. with_ctxt ( tcx. def_span ( def_id) . ctxt ( ) ) ,
709
+ None => tcx. def_span ( def_id) ,
710
+ } )
711
+ . collect ( ) ;
712
+
713
+ let descr = tcx. def_kind ( first_id) . descr ( first_id. to_def_id ( ) ) ;
714
+ let num = dead_codes. len ( ) ;
715
+ let multiple = num > 6 ;
716
+ let name_list = names. into ( ) ;
717
+
718
+ let lint = if is_positional {
719
+ lint:: builtin:: UNUSED_TUPLE_STRUCT_FIELDS
720
+ } else {
721
+ lint:: builtin:: DEAD_CODE
722
+ } ;
723
+
724
+ let parent_info = if let Some ( parent_item) = parent_item {
725
+ let parent_descr = tcx. def_kind ( parent_item) . descr ( parent_item. to_def_id ( ) ) ;
726
+ Some ( ParentInfo {
727
+ num,
728
+ descr,
729
+ parent_descr,
730
+ span : tcx. def_ident_span ( parent_item) . unwrap ( ) ,
731
+ } )
732
+ } else {
733
+ None
734
+ } ;
735
+
736
+ let encl_def_id = parent_item. unwrap_or ( first_id) ;
737
+ let ignored_derived_impls =
738
+ if let Some ( ign_traits) = self . ignored_derived_traits . get ( & encl_def_id) {
739
+ let trait_list = ign_traits
740
+ . iter ( )
741
+ . map ( |( trait_id, _) | self . tcx . item_name ( * trait_id) )
742
+ . collect :: < Vec < _ > > ( ) ;
743
+ let trait_list_len = trait_list. len ( ) ;
744
+ Some ( IgnoredDerivedImpls {
745
+ name : self . tcx . item_name ( encl_def_id. to_def_id ( ) ) ,
746
+ trait_list : trait_list. into ( ) ,
747
+ trait_list_len,
707
748
} )
708
- . collect ( ) ;
709
-
710
- let descr = tcx. def_kind ( first_id) . descr ( first_id. to_def_id ( ) ) ;
711
- let span_len = dead_codes. len ( ) ;
712
- let names = match & names[ ..] {
713
- _ if span_len > 6 => String :: new ( ) ,
714
- [ name] => format ! ( "`{name}` " ) ,
715
- [ names @ .., last] => {
716
- format ! (
717
- "{} and `{last}` " ,
718
- names. iter( ) . map( |name| format!( "`{name}`" ) ) . join( ", " )
719
- )
720
- }
721
- [ ] => unreachable ! ( ) ,
749
+ } else {
750
+ None
722
751
} ;
723
- let msg = format ! (
724
- "{these}{descr}{s} {names}{are} never {participle}" ,
725
- these = if span_len > 6 { "multiple " } else { "" } ,
726
- s = pluralize!( span_len) ,
727
- are = pluralize!( "is" , span_len) ,
728
- ) ;
729
-
730
- tcx. struct_span_lint_hir (
731
- if is_positional {
732
- lint:: builtin:: UNUSED_TUPLE_STRUCT_FIELDS
733
- } else {
734
- lint:: builtin:: DEAD_CODE
735
- } ,
736
- tcx. hir ( ) . local_def_id_to_hir_id ( first_id) ,
737
- MultiSpan :: from_spans ( spans. clone ( ) ) ,
738
- msg,
739
- |err| {
740
- if is_positional {
741
- err. multipart_suggestion (
742
- & format ! (
743
- "consider changing the field{s} to be of unit type to \
744
- suppress this warning while preserving the field \
745
- numbering, or remove the field{s}",
746
- s = pluralize!( span_len)
747
- ) ,
748
- spans. iter ( ) . map ( |sp| ( * sp, "()" . to_string ( ) ) ) . collect ( ) ,
749
- // "HasPlaceholders" because applying this fix by itself isn't
750
- // enough: All constructor calls have to be adjusted as well
751
- Applicability :: HasPlaceholders ,
752
- ) ;
753
- }
754
752
755
- if let Some ( parent_item) = parent_item {
756
- let parent_descr = tcx. def_kind ( parent_item) . descr ( parent_item. to_def_id ( ) ) ;
757
- err. span_label (
758
- tcx. def_ident_span ( parent_item) . unwrap ( ) ,
759
- format ! ( "{descr}{s} in this {parent_descr}" , s = pluralize!( span_len) ) ,
760
- ) ;
761
- }
753
+ let diag = if is_positional {
754
+ MultipleDeadCodes :: UnusedTupleStructFields {
755
+ multiple,
756
+ num,
757
+ descr,
758
+ participle,
759
+ name_list,
760
+ change_fields_suggestion : ChangeFieldsToBeOfUnitType { num, spans : spans. clone ( ) } ,
761
+ parent_info,
762
+ ignored_derived_impls,
763
+ }
764
+ } else {
765
+ MultipleDeadCodes :: DeadCodes {
766
+ multiple,
767
+ num,
768
+ descr,
769
+ participle,
770
+ name_list,
771
+ parent_info,
772
+ ignored_derived_impls,
773
+ }
774
+ } ;
762
775
763
- let encl_def_id = parent_item. unwrap_or ( first_id) ;
764
- if let Some ( ign_traits) = self . ignored_derived_traits . get ( & encl_def_id) {
765
- let traits_str = ign_traits
766
- . iter ( )
767
- . map ( |( trait_id, _) | format ! ( "`{}`" , self . tcx. item_name( * trait_id) ) )
768
- . collect :: < Vec < _ > > ( )
769
- . join ( " and " ) ;
770
- let plural_s = pluralize ! ( ign_traits. len( ) ) ;
771
- let article = if ign_traits. len ( ) > 1 { "" } else { "a " } ;
772
- let is_are = if ign_traits. len ( ) > 1 { "these are" } else { "this is" } ;
773
- let msg = format ! (
774
- "`{}` has {}derived impl{} for the trait{} {}, but {} \
775
- intentionally ignored during dead code analysis",
776
- self . tcx. item_name( encl_def_id. to_def_id( ) ) ,
777
- article,
778
- plural_s,
779
- plural_s,
780
- traits_str,
781
- is_are
782
- ) ;
783
- err. note ( & msg) ;
784
- }
785
- err
786
- } ,
787
- ) ;
788
- }
776
+ self . tcx . emit_spanned_lint (
777
+ lint,
778
+ tcx. hir ( ) . local_def_id_to_hir_id ( first_id) ,
779
+ MultiSpan :: from_spans ( spans. clone ( ) ) ,
780
+ diag,
781
+ ) ;
789
782
}
790
783
791
784
fn warn_dead_fields_and_variants (
0 commit comments