@@ -109,7 +109,6 @@ fn broken_fixes_backed_out() {
109109                            fs::File::create(&first).unwrap(); 
110110                        } 
111111                    } 
112- 
113112                    let status = Command::new("rustc") 
114113                        .args(env::args().skip(1)) 
115114                        .status() 
@@ -160,7 +159,157 @@ fn broken_fixes_backed_out() {
160159\n \ 
161160\n \ 
162161\n \ 
163- \n \ 
162+ \n \ 
163+ \n \ 
164+ \n \ 
165+ \n \ 
166+ \n \ 
167+ \n \ 
168+ \n \ 
169+ , 
170+         ) 
171+         . with_stderr_contains ( "Original diagnostics will follow." ) 
172+         . with_stderr_contains ( "[WARNING] variable does not need to be mutable" ) 
173+         . with_stderr_does_not_contain ( "[..][FIXED][..]" ) 
174+         . run ( ) ; 
175+ 
176+     // Make sure the fix which should have been applied was backed out 
177+     assert ! ( p. read_file( "bar/src/lib.rs" ) . contains( "let mut x = 3;" ) ) ; 
178+ } 
179+ 
180+ #[ cargo_test]  
181+ fn  broken_clippy_fixes_backed_out ( )  { 
182+     // A wrapper around `rustc` instead of calling `clippy` 
183+     let  clippy_driver = project ( ) 
184+         . at ( cargo_test_support:: paths:: global_root ( ) . join ( "clippy-driver" ) ) 
185+         . file ( "Cargo.toml" ,  & basic_manifest ( "clippy-driver" ,  "0.0.1" ) ) 
186+         . file ( 
187+             "src/main.rs" , 
188+             r#" 
189+             fn main() { 
190+                 let mut args = std::env::args_os(); 
191+                 let _me = args.next().unwrap(); 
192+                 let rustc = args.next().unwrap(); 
193+                 let status = std::process::Command::new(rustc).args(args).status().unwrap(); 
194+                 std::process::exit(status.code().unwrap_or(1)); 
195+             } 
196+             "# , 
197+         ) 
198+         . build ( ) ; 
199+     clippy_driver. cargo ( "build" ) . run ( ) ; 
200+ 
201+     // This works as follows: 
202+     // - Create a `rustc` shim (the "foo" project) which will pretend that the 
203+     //   verification step fails. 
204+     // - There is an empty build script so `foo` has `OUT_DIR` to track the steps. 
205+     // - The first "check", `foo` creates a file in OUT_DIR, and it completes 
206+     //   successfully with a warning diagnostic to remove unused `mut`. 
207+     // - rustfix removes the `mut`. 
208+     // - The second "check" to verify the changes, `foo` swaps out the content 
209+     //   with something that fails to compile. It creates a second file so it 
210+     //   won't do anything in the third check. 
211+     // - cargo fix discovers that the fix failed, and it backs out the changes. 
212+     // - The third "check" is done to display the original diagnostics of the 
213+     //   original code. 
214+     let  p = project ( ) 
215+         . file ( 
216+             "foo/Cargo.toml" , 
217+             r#" 
218+                 [package] 
219+                 name = 'foo' 
220+                 version = '0.1.0' 
221+                 [workspace] 
222+             "# , 
223+         ) 
224+         . file ( 
225+             "foo/src/main.rs" , 
226+             r#" 
227+                 use std::env; 
228+                 use std::fs; 
229+                 use std::io::Write; 
230+                 use std::path::{Path, PathBuf}; 
231+                 use std::process::{self, Command}; 
232+ 
233+                 fn main() { 
234+                     // Ignore calls to things like --print=file-names and compiling build.rs. 
235+                     // Also compatible for rustc invocations with `@path` argfile. 
236+                     let is_lib_rs = env::args_os() 
237+                         .map(PathBuf::from) 
238+                         .flat_map(|p| if let Some(p) = p.to_str().unwrap_or_default().strip_prefix("@") { 
239+                             fs::read_to_string(p).unwrap().lines().map(PathBuf::from).collect() 
240+                         } else { 
241+                             vec![p] 
242+                         }) 
243+                         .any(|l| l == Path::new("src/lib.rs")); 
244+                     if is_lib_rs { 
245+                         let path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); 
246+                         let first = path.join("first"); 
247+                         let second = path.join("second"); 
248+                         if first.exists() && !second.exists() { 
249+                             fs::write("src/lib.rs", b"not rust code").unwrap(); 
250+                             fs::File::create(&second).unwrap(); 
251+                         } else { 
252+                             fs::File::create(&first).unwrap(); 
253+                         } 
254+                     } 
255+                     let status = Command::new("rustc") 
256+                         .args(env::args().skip(1)) 
257+                         .status() 
258+                         .expect("failed to run rustc"); 
259+                     process::exit(status.code().unwrap_or(2)); 
260+                 } 
261+             "# , 
262+         ) 
263+         . file ( 
264+             "bar/Cargo.toml" , 
265+             r#" 
266+                 [package] 
267+                 name = 'bar' 
268+                 version = '0.1.0' 
269+                 [workspace] 
270+             "# , 
271+         ) 
272+         . file ( "bar/build.rs" ,  "fn main() {}" ) 
273+         . file ( 
274+             "bar/src/lib.rs" , 
275+             r#" 
276+                 pub fn foo() { 
277+                     let mut x = 3; 
278+                     drop(x); 
279+                 } 
280+             "# , 
281+         ) 
282+         . build ( ) ; 
283+ 
284+     // Build our rustc shim 
285+     p. cargo ( "build" ) . cwd ( "foo" ) . run ( ) ; 
286+ 
287+     // Attempt to fix code, but our shim will always fail the second compile. 
288+     // Also, we use `clippy` as a workspace wrapper to make sure that we properly 
289+     // generate the report bug text. 
290+     p. cargo ( "fix --allow-no-vcs --lib" ) 
291+         . cwd ( "bar" ) 
292+         . env ( "__CARGO_FIX_YOLO" ,  "1" ) 
293+         . env ( "RUSTC" ,  p. root ( ) . join ( "foo/target/debug/foo" ) ) 
294+         //  We can't use `clippy` so we use a `rustc` workspace wrapper instead 
295+         . env ( 
296+             "RUSTC_WORKSPACE_WRAPPER" , 
297+             clippy_driver. bin ( "clippy-driver" ) , 
298+         ) 
299+         . with_stderr_contains ( 
300+             "warning: failed to automatically apply fixes suggested by rustc \  
301+ \n \ 
302+ \n \ 
303+ \ 
304+ \n \ 
305+ \n   \ 
306+ \n \ 
307+ \n \ 
308+ \n \ 
309+ \n \ 
310+ \n \ 
311+ \n \ 
312+ \n \ 
164313\n \ 
165314\n \ 
166315\n \ 
0 commit comments