@@ -131,10 +131,11 @@ struct DrainState<'cfg> {
131131diag_dedupe :  DiagDedupe < ' cfg > , 
132132    /// Count of warnings, used to print a summary after the job succeeds. 
133133/// 
134- /// First value is the total number of warnings, and  the second value is 
134+ /// First value is the total number of warnings, the second value is 
135135/// the number that were suppressed because they were duplicates of a 
136- /// previous warning. 
137- warning_count :  HashMap < JobId ,  ( usize ,  usize ) > , 
136+ /// previous warning, and the third value is for the number of fixable 
137+ /// warnings (set to -1 if there are any errors). 
138+ warning_count :  HashMap < JobId ,  ( usize ,  usize ,  isize ) > , 
138139    active :  HashMap < JobId ,  Unit > , 
139140    compiled :  HashSet < PackageId > , 
140141    documented :  HashSet < PackageId > , 
@@ -311,10 +312,12 @@ enum Message {
311312        id :  JobId , 
312313        level :  String , 
313314        diag :  String , 
315+         fixable :  bool , 
314316    } , 
315317    WarningCount  { 
316318        id :  JobId , 
317319        emitted :  bool , 
320+         fixable :  bool , 
318321    } , 
319322    FixDiagnostic ( diagnostic_server:: Message ) , 
320323    Token ( io:: Result < Acquired > ) , 
@@ -363,20 +366,22 @@ impl<'a, 'cfg> JobState<'a, 'cfg> {
363366        Ok ( ( ) ) 
364367    } 
365368
366-     pub  fn  emit_diag ( & self ,  level :  String ,  diag :  String )  -> CargoResult < ( ) >  { 
369+     pub  fn  emit_diag ( & self ,  level :  String ,  diag :  String ,   fixable :   bool )  -> CargoResult < ( ) >  { 
367370        if  let  Some ( dedupe)  = self . output  { 
368371            let  emitted = dedupe. emit_diag ( & diag) ?; 
369372            if  level == "warning"  { 
370373                self . messages . push ( Message :: WarningCount  { 
371374                    id :  self . id , 
372375                    emitted, 
376+                     fixable, 
373377                } ) ; 
374378            } 
375379        }  else  { 
376380            self . messages . push_bounded ( Message :: Diagnostic  { 
377381                id :  self . id , 
378382                level, 
379383                diag, 
384+                 fixable, 
380385            } ) ; 
381386        } 
382387        Ok ( ( ) ) 
@@ -679,14 +684,31 @@ impl<'cfg> DrainState<'cfg> {
679684                shell. print_ansi_stderr ( err. as_bytes ( ) ) ?; 
680685                shell. err ( ) . write_all ( b"\n " ) ?; 
681686            } 
682-             Message :: Diagnostic  {  id,  level,  diag }  => { 
687+             Message :: Diagnostic  { 
688+                 id, 
689+                 level, 
690+                 diag, 
691+                 fixable, 
692+             }  => { 
683693                let  emitted = self . diag_dedupe . emit_diag ( & diag) ?; 
684694                if  level == "warning"  { 
685-                     self . bump_warning_count ( id,  emitted) ; 
695+                     self . bump_warning_count ( id,  emitted,  fixable) ; 
696+                 } 
697+                 if  level == "error"  { 
698+                     // If there is an error set fixable count to -1 so the `cargo fix` 
699+                     // message does not show 
700+                     let  cnts = self . warning_count . entry ( id) . or_default ( ) ; 
701+                     if  fixable { 
702+                         cnts. 2  = -1 ; 
703+                     } 
686704                } 
687705            } 
688-             Message :: WarningCount  {  id,  emitted }  => { 
689-                 self . bump_warning_count ( id,  emitted) ; 
706+             Message :: WarningCount  { 
707+                 id, 
708+                 emitted, 
709+                 fixable, 
710+             }  => { 
711+                 self . bump_warning_count ( id,  emitted,  fixable) ; 
690712            } 
691713            Message :: FixDiagnostic ( msg)  => { 
692714                self . print . print ( & msg) ?; 
@@ -1127,18 +1149,34 @@ impl<'cfg> DrainState<'cfg> {
11271149        Ok ( ( ) ) 
11281150    } 
11291151
1130-     fn  bump_warning_count ( & mut  self ,  id :  JobId ,  emitted :  bool )  { 
1152+     fn  bump_warning_count ( & mut  self ,  id :  JobId ,  emitted :  bool ,   fixable :   bool )  { 
11311153        let  cnts = self . warning_count . entry ( id) . or_default ( ) ; 
11321154        cnts. 0  += 1 ; 
11331155        if  !emitted { 
11341156            cnts. 1  += 1 ; 
1157+         // Don't add to fixable if it's already been emitted 
1158+         }  else  if  fixable { 
1159+             // Do not add anything to the fixable warning count if 
1160+             // is `-1` since that indicates there was an error while 
1161+             // building this `Unit` 
1162+             if  cnts. 2  >= 0  { 
1163+                 cnts. 2  += 1 ; 
1164+             } 
11351165        } 
11361166    } 
11371167
11381168    /// Displays a final report of the warnings emitted by a particular job. 
11391169fn  report_warning_count ( & mut  self ,  config :  & Config ,  id :  JobId )  { 
11401170        let  count = match  self . warning_count . remove ( & id)  { 
1141-             Some ( count)  => count, 
1171+             Some ( count)  => { 
1172+                 // An error could add an entry for a `Unit` 
1173+                 // with 0 warnings but with count.2 = -1 
1174+                 if  count. 0  > 0  { 
1175+                     count
1176+                 }  else  { 
1177+                     return ; 
1178+                 } 
1179+             } 
11421180            None  => return , 
11431181        } ; 
11441182        let  unit = & self . active [ & id] ; 
@@ -1160,6 +1198,41 @@ impl<'cfg> DrainState<'cfg> {
11601198            1  => message. push_str ( " (1 duplicate)" ) , 
11611199            n => drop ( write ! ( message,  " ({} duplicates)" ,  n) ) , 
11621200        } 
1201+         // Only show the `cargo fix` message if its a local `Unit` 
1202+         if  unit. is_local ( )  && config. nightly_features_allowed  { 
1203+             match  count. 2  { 
1204+                 // Do not show this if there are any errors (-1) or no fixable warnings 
1205+                 -1  | 0  => { } 
1206+                 n => { 
1207+                     // `cargo fix` doesnt have an option for custom builds 
1208+                     if  !unit. target . is_custom_build ( )  { 
1209+                         let  mut  command = { 
1210+                             let  named = unit. target . description_named ( ) ; 
1211+                             // if its a lib we need to add the package to fix 
1212+                             if  named == "lib"  { 
1213+                                 format ! ( "{} -p {}" ,  named,  unit. pkg. name( ) ) 
1214+                             }  else  { 
1215+                                 named
1216+                             } 
1217+                         } ; 
1218+                         if  unit. mode . is_rustc_test ( ) 
1219+                             && !( unit. target . is_test ( )  || unit. target . is_bench ( ) ) 
1220+                         { 
1221+                             command. push_str ( " --tests" ) ; 
1222+                         } 
1223+                         let  mut  suggestions = format ! ( "{} suggestion" ,  n) ; 
1224+                         if  n > 1  { 
1225+                             suggestions. push_str ( "s" ) 
1226+                         } 
1227+                         drop ( write ! ( 
1228+                             message, 
1229+                             " (run `cargo fix --{}` to apply {})" , 
1230+                             command,  suggestions
1231+                         ) ) 
1232+                     } 
1233+                 } 
1234+             } 
1235+         } 
11631236        // Errors are ignored here because it is tricky to handle them 
11641237        // correctly, and they aren't important. 
11651238        drop ( config. shell ( ) . warn ( message) ) ; 
0 commit comments