Skip to content

Commit 1ef1b7e

Browse files
committed
Fix fix::fix_in_dependency to not rely on rustc
1 parent 4f70d17 commit 1ef1b7e

File tree

1 file changed

+154
-3
lines changed

1 file changed

+154
-3
lines changed

tests/testsuite/fix.rs

+154-3
Original file line numberDiff line numberDiff line change
@@ -1858,9 +1858,22 @@ fn non_edition_lint_migration() {
18581858
assert!(contents.contains("from_utf8(crate::foo::FOO)"));
18591859
}
18601860

1861-
// For rust-lang/cargo#9857
18621861
#[cargo_test]
18631862
fn fix_in_dependency() {
1863+
// Tests what happens if rustc emits a suggestion to modify a file from a
1864+
// dependency in cargo's home directory. This should never happen, and
1865+
// indicates a bug in rustc. However, there are several known bugs in
1866+
// rustc where it does this (often involving macros), so `cargo fix` has a
1867+
// guard that says if the suggestion points to some location in CARGO_HOME
1868+
// to not apply it.
1869+
//
1870+
// See https://github.com/rust-lang/cargo/issues/9857 for some other
1871+
// examples.
1872+
//
1873+
// This test uses a simulated rustc which replays a suggestion via a JSON
1874+
// message that points into CARGO_HOME. This does not use the real rustc
1875+
// because as the bugs are fixed in the real rustc, that would cause this
1876+
// test to stop working.
18641877
Package::new("bar", "1.0.0")
18651878
.file(
18661879
"src/lib.rs",
@@ -1896,8 +1909,146 @@ fn fix_in_dependency() {
18961909
"#,
18971910
)
18981911
.build();
1912+
p.cargo("fetch").run();
1913+
1914+
// The path in CARGO_HOME.
1915+
let bar_path = std::fs::read_dir(paths::home().join(".cargo/registry/src"))
1916+
.unwrap()
1917+
.next()
1918+
.unwrap()
1919+
.unwrap()
1920+
.path();
1921+
// Since this is a substitution into a Rust string (representing a JSON
1922+
// string), deal with backslashes like on Windows.
1923+
let bar_path_str = bar_path.to_str().unwrap().replace("\\", "/");
1924+
1925+
// This is a fake rustc that will emit a JSON message when the `foo` crate
1926+
// builds that tells cargo to modify a file it shouldn't.
1927+
let rustc = project()
1928+
.at("rustc-replay")
1929+
.file("Cargo.toml", &basic_manifest("rustc-replay", "1.0.0"))
1930+
.file("src/main.rs",
1931+
&r##"
1932+
fn main() {
1933+
let pkg_name = match std::env::var("CARGO_PKG_NAME") {
1934+
Ok(pkg_name) => pkg_name,
1935+
Err(_) => {
1936+
let r = std::process::Command::new("rustc")
1937+
.args(std::env::args_os().skip(1))
1938+
.status();
1939+
std::process::exit(r.unwrap().code().unwrap_or(2));
1940+
}
1941+
};
1942+
if pkg_name == "foo" {
1943+
eprintln!("{}", r#"{
1944+
"$message_type": "diagnostic",
1945+
"message": "unused variable: `abc`",
1946+
"code":
1947+
{
1948+
"code": "unused_variables",
1949+
"explanation": null
1950+
},
1951+
"level": "warning",
1952+
"spans":
1953+
[
1954+
{
1955+
"file_name": "__BAR_PATH__/bar-1.0.0/src/lib.rs",
1956+
"byte_start": 127,
1957+
"byte_end": 129,
1958+
"line_start": 5,
1959+
"line_end": 5,
1960+
"column_start": 29,
1961+
"column_end": 31,
1962+
"is_primary": true,
1963+
"text":
1964+
[
1965+
{
1966+
"text": " let $i = 1;",
1967+
"highlight_start": 29,
1968+
"highlight_end": 31
1969+
}
1970+
],
1971+
"label": null,
1972+
"suggested_replacement": null,
1973+
"suggestion_applicability": null,
1974+
"expansion": null
1975+
}
1976+
],
1977+
"children":
1978+
[
1979+
{
1980+
"message": "`#[warn(unused_variables)]` on by default",
1981+
"code": null,
1982+
"level": "note",
1983+
"spans":
1984+
[],
1985+
"children":
1986+
[],
1987+
"rendered": null
1988+
},
1989+
{
1990+
"message": "if this is intentional, prefix it with an underscore",
1991+
"code": null,
1992+
"level": "help",
1993+
"spans":
1994+
[
1995+
{
1996+
"file_name": "__BAR_PATH__/bar-1.0.0/src/lib.rs",
1997+
"byte_start": 127,
1998+
"byte_end": 129,
1999+
"line_start": 5,
2000+
"line_end": 5,
2001+
"column_start": 29,
2002+
"column_end": 31,
2003+
"is_primary": true,
2004+
"text":
2005+
[
2006+
{
2007+
"text": " let $i = 1;",
2008+
"highlight_start": 29,
2009+
"highlight_end": 31
2010+
}
2011+
],
2012+
"label": null,
2013+
"suggested_replacement": "_abc",
2014+
"suggestion_applicability": "MachineApplicable",
2015+
"expansion": null
2016+
}
2017+
],
2018+
"children":
2019+
[],
2020+
"rendered": null
2021+
}
2022+
],
2023+
"rendered": "warning: unused variable: `abc`\n --> __BAR_PATH__/bar-1.0.0/src/lib.rs:5:29\n |\n5 | let $i = 1;\n | ^^ help: if this is intentional, prefix it with an underscore: `_abc`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n"
2024+
}"#.replace("\n", ""));
2025+
}
2026+
}
2027+
"##.replace("__BAR_PATH__", &bar_path_str))
2028+
.build();
2029+
rustc.cargo("build").run();
2030+
let rustc_bin = rustc.bin("rustc-replay");
18992031

1900-
p.cargo("fix --allow-no-vcs")
1901-
.with_stderr_does_not_contain("[FIXED] [..]")
2032+
// The output here should not say `Fixed`.
2033+
//
2034+
// It is OK to compare the full diagnostic output here because the text is
2035+
// hard-coded in rustc-replay. Normally tests should not be checking the
2036+
// compiler output.
2037+
p.cargo("fix --lib --allow-no-vcs")
2038+
.env("RUSTC", &rustc_bin)
2039+
.with_stderr("\
2040+
[CHECKING] bar v1.0.0
2041+
[CHECKING] foo v0.1.0 [..]
2042+
warning: unused variable: `abc`
2043+
--> [ROOT]/home/.cargo/registry/src/[..]/bar-1.0.0/src/lib.rs:5:29
2044+
|
2045+
5 | let $i = 1;
2046+
| ^^ help: if this is intentional, prefix it with an underscore: `_abc`
2047+
|
2048+
= note: `#[warn(unused_variables)]` on by default
2049+
2050+
warning: `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)
2051+
[FINISHED] [..]
2052+
")
19022053
.run();
19032054
}

0 commit comments

Comments
 (0)