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
@@ -698,99 +701,89 @@ impl<'tcx> DeadVisitor<'tcx> {
698
701
parent_item : Option < LocalDefId > ,
699
702
is_positional : bool ,
700
703
) {
701
- if let Some ( & first_id) = dead_codes. first ( ) {
702
- let tcx = self . tcx ;
703
- let names: Vec < _ > = dead_codes
704
- . iter ( )
705
- . map ( |& def_id| tcx. item_name ( def_id. to_def_id ( ) ) . to_string ( ) )
706
- . collect ( ) ;
707
- let spans: Vec < _ > = dead_codes
708
- . iter ( )
709
- . map ( |& def_id| match tcx. def_ident_span ( def_id) {
710
- Some ( s) => s. with_ctxt ( tcx. def_span ( def_id) . ctxt ( ) ) ,
711
- None => tcx. def_span ( def_id) ,
704
+ let Some ( & first_id) = dead_codes. first ( ) else {
705
+ return ;
706
+ } ;
707
+ let tcx = self . tcx ;
708
+ let names: Vec < _ > =
709
+ dead_codes. iter ( ) . map ( |& def_id| tcx. item_name ( def_id. to_def_id ( ) ) ) . collect ( ) ;
710
+ let spans: Vec < _ > = dead_codes
711
+ . iter ( )
712
+ . map ( |& def_id| match tcx. def_ident_span ( def_id) {
713
+ Some ( s) => s. with_ctxt ( tcx. def_span ( def_id) . ctxt ( ) ) ,
714
+ None => tcx. def_span ( def_id) ,
715
+ } )
716
+ . collect ( ) ;
717
+
718
+ let descr = tcx. def_kind ( first_id) . descr ( first_id. to_def_id ( ) ) ;
719
+ let num = dead_codes. len ( ) ;
720
+ let multiple = num > 6 ;
721
+ let name_list = names. into ( ) ;
722
+
723
+ let lint = if is_positional {
724
+ lint:: builtin:: UNUSED_TUPLE_STRUCT_FIELDS
725
+ } else {
726
+ lint:: builtin:: DEAD_CODE
727
+ } ;
728
+
729
+ let parent_info = if let Some ( parent_item) = parent_item {
730
+ let parent_descr = tcx. def_kind ( parent_item) . descr ( parent_item. to_def_id ( ) ) ;
731
+ Some ( ParentInfo {
732
+ num,
733
+ descr,
734
+ parent_descr,
735
+ span : tcx. def_ident_span ( parent_item) . unwrap ( ) ,
736
+ } )
737
+ } else {
738
+ None
739
+ } ;
740
+
741
+ let encl_def_id = parent_item. unwrap_or ( first_id) ;
742
+ let ignored_derived_impls =
743
+ if let Some ( ign_traits) = self . ignored_derived_traits . get ( & encl_def_id) {
744
+ let trait_list = ign_traits
745
+ . iter ( )
746
+ . map ( |( trait_id, _) | self . tcx . item_name ( * trait_id) )
747
+ . collect :: < Vec < _ > > ( ) ;
748
+ let trait_list_len = trait_list. len ( ) ;
749
+ Some ( IgnoredDerivedImpls {
750
+ name : self . tcx . item_name ( encl_def_id. to_def_id ( ) ) ,
751
+ trait_list : trait_list. into ( ) ,
752
+ trait_list_len,
712
753
} )
713
- . collect ( ) ;
714
-
715
- let descr = tcx. def_kind ( first_id) . descr ( first_id. to_def_id ( ) ) ;
716
- let span_len = dead_codes. len ( ) ;
717
- let names = match & names[ ..] {
718
- _ if span_len > 6 => String :: new ( ) ,
719
- [ name] => format ! ( "`{name}` " ) ,
720
- [ names @ .., last] => {
721
- format ! (
722
- "{} and `{last}` " ,
723
- names. iter( ) . map( |name| format!( "`{name}`" ) ) . join( ", " )
724
- )
725
- }
726
- [ ] => unreachable ! ( ) ,
754
+ } else {
755
+ None
727
756
} ;
728
- let msg = format ! (
729
- "{these}{descr}{s} {names}{are} never {participle}" ,
730
- these = if span_len > 6 { "multiple " } else { "" } ,
731
- s = pluralize!( span_len) ,
732
- are = pluralize!( "is" , span_len) ,
733
- ) ;
734
-
735
- tcx. struct_span_lint_hir (
736
- if is_positional {
737
- lint:: builtin:: UNUSED_TUPLE_STRUCT_FIELDS
738
- } else {
739
- lint:: builtin:: DEAD_CODE
740
- } ,
741
- tcx. hir ( ) . local_def_id_to_hir_id ( first_id) ,
742
- MultiSpan :: from_spans ( spans. clone ( ) ) ,
743
- msg,
744
- |err| {
745
- if is_positional {
746
- err. multipart_suggestion (
747
- & format ! (
748
- "consider changing the field{s} to be of unit type to \
749
- suppress this warning while preserving the field \
750
- numbering, or remove the field{s}",
751
- s = pluralize!( span_len)
752
- ) ,
753
- spans. iter ( ) . map ( |sp| ( * sp, "()" . to_string ( ) ) ) . collect ( ) ,
754
- // "HasPlaceholders" because applying this fix by itself isn't
755
- // enough: All constructor calls have to be adjusted as well
756
- Applicability :: HasPlaceholders ,
757
- ) ;
758
- }
759
757
760
- if let Some ( parent_item) = parent_item {
761
- let parent_descr = tcx. def_kind ( parent_item) . descr ( parent_item. to_def_id ( ) ) ;
762
- err. span_label (
763
- tcx. def_ident_span ( parent_item) . unwrap ( ) ,
764
- format ! ( "{descr}{s} in this {parent_descr}" , s = pluralize!( span_len) ) ,
765
- ) ;
766
- }
758
+ let diag = if is_positional {
759
+ MultipleDeadCodes :: UnusedTupleStructFields {
760
+ multiple,
761
+ num,
762
+ descr,
763
+ participle,
764
+ name_list,
765
+ change_fields_suggestion : ChangeFieldsToBeOfUnitType { num, spans : spans. clone ( ) } ,
766
+ parent_info,
767
+ ignored_derived_impls,
768
+ }
769
+ } else {
770
+ MultipleDeadCodes :: DeadCodes {
771
+ multiple,
772
+ num,
773
+ descr,
774
+ participle,
775
+ name_list,
776
+ parent_info,
777
+ ignored_derived_impls,
778
+ }
779
+ } ;
767
780
768
- let encl_def_id = parent_item. unwrap_or ( first_id) ;
769
- if let Some ( ign_traits) = self . ignored_derived_traits . get ( & encl_def_id) {
770
- let traits_str = ign_traits
771
- . iter ( )
772
- . map ( |( trait_id, _) | format ! ( "`{}`" , self . tcx. item_name( * trait_id) ) )
773
- . collect :: < Vec < _ > > ( )
774
- . join ( " and " ) ;
775
- let plural_s = pluralize ! ( ign_traits. len( ) ) ;
776
- let article = if ign_traits. len ( ) > 1 { "" } else { "a " } ;
777
- let is_are = if ign_traits. len ( ) > 1 { "these are" } else { "this is" } ;
778
- let msg = format ! (
779
- "`{}` has {}derived impl{} for the trait{} {}, but {} \
780
- intentionally ignored during dead code analysis",
781
- self . tcx. item_name( encl_def_id. to_def_id( ) ) ,
782
- article,
783
- plural_s,
784
- plural_s,
785
- traits_str,
786
- is_are
787
- ) ;
788
- err. note ( & msg) ;
789
- }
790
- err
791
- } ,
792
- ) ;
793
- }
781
+ self . tcx . emit_spanned_lint (
782
+ lint,
783
+ tcx. hir ( ) . local_def_id_to_hir_id ( first_id) ,
784
+ MultiSpan :: from_spans ( spans. clone ( ) ) ,
785
+ diag,
786
+ ) ;
794
787
}
795
788
796
789
fn warn_dead_fields_and_variants (
0 commit comments