@@ -174,6 +174,37 @@ pub struct ErrorsDuringDrain {
174174 pub count : usize ,
175175}
176176
177+ struct ErrorToHandle {
178+ error : anyhow:: Error ,
179+
180+ /// This field is true for "interesting" errors and false for "mundane"
181+ /// errors. If false, we print the above error only if it's the first one
182+ /// encountered so far while draining the job queue.
183+ ///
184+ /// At most places that an error is propagated, we set this to false to
185+ /// avoid scenarios where Cargo might end up spewing tons of redundant error
186+ /// messages. For example if an i/o stream got closed somewhere, we don't
187+ /// care about individually reporting every thread that it broke; just the
188+ /// first is enough.
189+ ///
190+ /// The exception where print_always is true is that we do report every
191+ /// instance of a rustc invocation that failed with diagnostics. This
192+ /// corresponds to errors from Message::Finish.
193+ print_always : bool ,
194+ }
195+
196+ impl < E > From < E > for ErrorToHandle
197+ where
198+ anyhow:: Error : From < E > ,
199+ {
200+ fn from ( error : E ) -> Self {
201+ ErrorToHandle {
202+ error : anyhow:: Error :: from ( error) ,
203+ print_always : false ,
204+ }
205+ }
206+ }
207+
177208#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
178209pub struct JobId ( pub u32 ) ;
179210
@@ -617,7 +648,7 @@ impl<'cfg> DrainState<'cfg> {
617648 jobserver_helper : & HelperThread ,
618649 plan : & mut BuildPlan ,
619650 event : Message ,
620- ) -> CargoResult < ( ) > {
651+ ) -> Result < ( ) , ErrorToHandle > {
621652 match event {
622653 Message :: Run ( id, cmd) => {
623654 cx. bcx
@@ -682,11 +713,14 @@ impl<'cfg> DrainState<'cfg> {
682713 debug ! ( "end ({:?}): {:?}" , unit, result) ;
683714 match result {
684715 Ok ( ( ) ) => self . finish ( id, & unit, artifact, cx) ?,
685- Err ( e ) => {
716+ Err ( error ) => {
686717 let msg = "The following warnings were emitted during compilation:" ;
687718 self . emit_warnings ( Some ( msg) , & unit, cx) ?;
688719 self . back_compat_notice ( cx, & unit) ?;
689- return Err ( e) ;
720+ return Err ( ErrorToHandle {
721+ error,
722+ print_always : true ,
723+ } ) ;
690724 }
691725 }
692726 }
@@ -854,7 +888,7 @@ impl<'cfg> DrainState<'cfg> {
854888 }
855889 . to_json_string ( ) ;
856890 if let Err ( e) = writeln ! ( shell. out( ) , "{}" , msg) {
857- self . handle_error ( & mut shell, & mut errors, e. into ( ) ) ;
891+ self . handle_error ( & mut shell, & mut errors, e) ;
858892 }
859893 }
860894
@@ -887,13 +921,18 @@ impl<'cfg> DrainState<'cfg> {
887921 & self ,
888922 shell : & mut Shell ,
889923 err_state : & mut ErrorsDuringDrain ,
890- new_err : anyhow :: Error ,
924+ new_err : impl Into < ErrorToHandle > ,
891925 ) {
892- crate :: display_error ( & new_err, shell) ;
893- if !self . active . is_empty ( ) && err_state. count == 0 {
894- drop ( shell. warn ( "build failed, waiting for other jobs to finish..." ) ) ;
926+ let new_err = new_err. into ( ) ;
927+ if new_err. print_always || err_state. count == 0 {
928+ crate :: display_error ( & new_err. error , shell) ;
929+ if err_state. count == 0 && !self . active . is_empty ( ) {
930+ drop ( shell. warn ( "build failed, waiting for other jobs to finish..." ) ) ;
931+ }
932+ err_state. count += 1 ;
933+ } else {
934+ log:: warn!( "{:?}" , new_err. error) ;
895935 }
896- err_state. count += 1 ;
897936 }
898937
899938 // This also records CPU usage and marks concurrency; we roughly want to do
0 commit comments