Skip to content

Commit

Permalink
fix: Don't back out changes with --broken-code
Browse files Browse the repository at this point in the history
This commit updates the behavior of `cargo fix` when the `--broken-code`
flag is passed to Cargo. Previously Cargo would always back out
automatically applied changes to files whenever the fixed code failed to
compile. Now, with the `--broken-code` flag, fixed code is left as-is.
This means that if the fixed code can be more easily inspected by
humans to detect bugs and such.

The main use case intended here is that if you're working with a large
code base then lints like the edition idiom lints aren't 100% finished
yet to work as smoothly as `cargo fix`. The idiom lints are often
useful, however, to transition code to be idiomatic (who would have
guessed!) in the new edition.

To ease the experience of using not-quite-ready lints this flag can be
used to hopefully "fix 90% of lint warnings" and then the remaining
compiler errors can be sifted through manually. The intention is that we
have edition documentation indicating this workflow which also
encourages filing bugs for anything that fails to fix, and hopefully
this new behavior will make it easier for us to narrow down what the
minimal test case is too!
  • Loading branch information
alexcrichton committed Nov 14, 2018
1 parent 5d96734 commit 3e746ae
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/cargo/ops/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,11 @@ pub fn fix_maybe_exec_rustc() -> CargoResult<bool> {
// user's code with our changes. Back out everything and fall through
// below to recompile again.
if !output.status.success() {
for (path, file) in fixes.files.iter() {
fs::write(path, &file.original_code)
.with_context(|_| format!("failed to write file `{}`", path))?;
if env::var_os(BROKEN_CODE_ENV).is_none() {
for (path, file) in fixes.files.iter() {
fs::write(path, &file.original_code)
.with_context(|_| format!("failed to write file `{}`", path))?;
}
}
log_failed_fix(&output.stderr)?;
}
Expand Down
71 changes: 71 additions & 0 deletions tests/testsuite/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,3 +1116,74 @@ fn only_warn_for_relevant_crates() {
")
.run();
}

#[test]
fn fix_to_broken_code() {
if !is_nightly() {
return;
}
let p = project()
.file(
"foo/Cargo.toml",
r#"
[package]
name = 'foo'
version = '0.1.0'
[workspace]
"#,
).file(
"foo/src/main.rs",
r##"
use std::env;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::{self, Command};
fn main() {
let is_lib_rs = env::args_os()
.map(PathBuf::from)
.any(|l| l == Path::new("src/lib.rs"));
if is_lib_rs {
let path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let path = path.join("foo");
if path.exists() {
panic!()
} else {
fs::File::create(&path).unwrap();
}
}
let status = Command::new("rustc")
.args(env::args().skip(1))
.status()
.expect("failed to run rustc");
process::exit(status.code().unwrap_or(2));
}
"##,
).file(
"bar/Cargo.toml",
r#"
[package]
name = 'bar'
version = '0.1.0'
[workspace]
"#,
).file("bar/build.rs", "fn main() {}")
.file(
"bar/src/lib.rs",
"pub fn foo() { let mut x = 3; drop(x); }",
).build();

// Build our rustc shim
p.cargo("build").cwd(p.root().join("foo")).run();

// Attempt to fix code, but our shim will always fail the second compile
p.cargo("fix --allow-no-vcs --broken-code")
.cwd(p.root().join("bar"))
.env("RUSTC", p.root().join("foo/target/debug/foo"))
.with_status(101)
.run();

assert_eq!(p.read_file("bar/src/lib.rs"), "pub fn foo() { let x = 3; drop(x); }");
}

0 comments on commit 3e746ae

Please sign in to comment.