@@ -14,7 +14,19 @@ use crate::core::builder::Builder;
1414use crate :: utils:: exec:: command;
1515use crate :: utils:: helpers:: { self , program_out_of_date, t} ;
1616
17- fn rustfmt ( src : & Path , rustfmt : & Path , paths : & [ PathBuf ] , check : bool ) -> impl FnMut ( bool ) -> bool {
17+ #[ must_use]
18+ enum RustfmtStatus {
19+ InProgress ,
20+ Ok ,
21+ Failed ,
22+ }
23+
24+ fn rustfmt (
25+ src : & Path ,
26+ rustfmt : & Path ,
27+ paths : & [ PathBuf ] ,
28+ check : bool ,
29+ ) -> impl FnMut ( bool ) -> RustfmtStatus {
1830 let mut cmd = Command :: new ( rustfmt) ;
1931 // Avoid the submodule config paths from coming into play. We only allow a single global config
2032 // for the workspace for now.
@@ -26,30 +38,20 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
2638 cmd. arg ( "--check" ) ;
2739 }
2840 cmd. args ( paths) ;
29- let cmd_debug = format ! ( "{cmd:?}" ) ;
3041 let mut cmd = cmd. spawn ( ) . expect ( "running rustfmt" ) ;
3142 // Poor man's async: return a closure that might wait for rustfmt's completion (depending on
3243 // the value of the `block` argument).
33- move |block : bool | -> bool {
44+ move |block : bool | -> RustfmtStatus {
3445 let status = if !block {
3546 match cmd. try_wait ( ) {
3647 Ok ( Some ( status) ) => Ok ( status) ,
37- Ok ( None ) => return false ,
48+ Ok ( None ) => return RustfmtStatus :: InProgress ,
3849 Err ( err) => Err ( err) ,
3950 }
4051 } else {
4152 cmd. wait ( )
4253 } ;
43- if !status. unwrap ( ) . success ( ) {
44- eprintln ! (
45- "fmt error: Running `{}` failed.\n If you're running `tidy`, \
46- try again with `--bless`. Or, if you just want to format \
47- code, run `./x.py fmt` instead.",
48- cmd_debug,
49- ) ;
50- crate :: exit!( 1 ) ;
51- }
52- true
54+ if status. unwrap ( ) . success ( ) { RustfmtStatus :: Ok } else { RustfmtStatus :: Failed }
5355 }
5456}
5557
@@ -240,6 +242,8 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
240242 // Spawn child processes on a separate thread so we can batch entries we have received from
241243 // ignore.
242244 let thread = std:: thread:: spawn ( move || {
245+ let mut result = Ok ( ( ) ) ;
246+
243247 let mut children = VecDeque :: new ( ) ;
244248 while let Ok ( path) = rx. recv ( ) {
245249 // Try getting more paths from the channel to amortize the overhead of spawning
@@ -251,22 +255,38 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
251255
252256 // Poll completion before waiting.
253257 for i in ( 0 ..children. len ( ) ) . rev ( ) {
254- if children[ i] ( false ) {
255- children. swap_remove_back ( i) ;
256- break ;
258+ match children[ i] ( false ) {
259+ RustfmtStatus :: InProgress => { }
260+ RustfmtStatus :: Failed => {
261+ result = Err ( ( ) ) ;
262+ children. swap_remove_back ( i) ;
263+ break ;
264+ }
265+ RustfmtStatus :: Ok => {
266+ children. swap_remove_back ( i) ;
267+ break ;
268+ }
257269 }
258270 }
259271
260272 if children. len ( ) >= max_processes {
261273 // Await oldest child.
262- children. pop_front ( ) . unwrap ( ) ( true ) ;
274+ match children. pop_front ( ) . unwrap ( ) ( true ) {
275+ RustfmtStatus :: InProgress | RustfmtStatus :: Ok => { }
276+ RustfmtStatus :: Failed => result = Err ( ( ) ) ,
277+ }
263278 }
264279 }
265280
266281 // Await remaining children.
267282 for mut child in children {
268- child ( true ) ;
283+ match child ( true ) {
284+ RustfmtStatus :: InProgress | RustfmtStatus :: Ok => { }
285+ RustfmtStatus :: Failed => result = Err ( ( ) ) ,
286+ }
269287 }
288+
289+ result
270290 } ) ;
271291
272292 let formatted_paths = Mutex :: new ( Vec :: new ( ) ) ;
@@ -299,7 +319,12 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
299319
300320 drop ( tx) ;
301321
302- thread. join ( ) . unwrap ( ) ;
322+ let result = thread. join ( ) . unwrap ( ) ;
323+
324+ if result. is_err ( ) {
325+ crate :: exit!( 1 ) ;
326+ }
327+
303328 if !check {
304329 update_rustfmt_version ( build) ;
305330 }
0 commit comments