Skip to content

Commit 8410c1e

Browse files
committed
test(fix): verify cargo might fix into rust-src
The suggestion is slightly tweaked since the original diagnostic was rejected due to multiple files were involved. For the original diagnostic JSON, see rust-lang/rust#88514 (comment)
1 parent d29ad67 commit 8410c1e

File tree

1 file changed

+374
-0
lines changed

1 file changed

+374
-0
lines changed

tests/testsuite/fix.rs

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,6 +1906,380 @@ warning: `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply
19061906
.run();
19071907
}
19081908

1909+
#[cargo_test]
1910+
fn fix_in_rust_src() {
1911+
// Tests what happens if rustc emits a suggestion to modify the standard
1912+
// library in rust source. This should never happen, and indicates a bug in
1913+
// rustc. However, there are several known bugs in rustc where it does this
1914+
// (often involving macros), so `cargo fix` has a guard that says if the
1915+
// suggestion points to rust source under sysroot to not apply it.
1916+
//
1917+
// See https://github.com/rust-lang/cargo/issues/9857 for some other
1918+
// examples.
1919+
//
1920+
// This test uses a simulated rustc which replays a suggestion via a JSON
1921+
// message that points into rust-src. This does not use the real rustc
1922+
// because as the bugs are fixed in the real rustc, that would cause this
1923+
// test to stop working.
1924+
1925+
let p = project()
1926+
.file(
1927+
"Cargo.toml",
1928+
r#"
1929+
[package]
1930+
name = "foo"
1931+
edition = "2021"
1932+
"#,
1933+
)
1934+
.file(
1935+
"src/lib.rs",
1936+
r#"
1937+
pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
1938+
if true {
1939+
writeln!(w, "`;?` here ->")?;
1940+
} else {
1941+
writeln!(w, "but not here")
1942+
}
1943+
Ok(())
1944+
}
1945+
"#,
1946+
)
1947+
.build();
1948+
p.cargo("fetch").run();
1949+
1950+
// Since this is a substitution into a Rust string (representing a JSON
1951+
// string), deal with backslashes like on Windows.
1952+
let sysroot = paths::sysroot().replace("\\", "/");
1953+
1954+
// This is a fake rustc that will emit a JSON message when the `foo` crate
1955+
// builds that tells cargo to modify a file it shouldn't.
1956+
let rustc = project()
1957+
.at("rustc-replay")
1958+
.file("Cargo.toml", &basic_manifest("rustc-replay", "1.0.0"))
1959+
.file("src/main.rs",
1960+
&r##"
1961+
fn main() {
1962+
let pkg_name = match std::env::var("CARGO_PKG_NAME") {
1963+
Ok(pkg_name) => pkg_name,
1964+
Err(_) => {
1965+
let r = std::process::Command::new("rustc")
1966+
.args(std::env::args_os().skip(1))
1967+
.status();
1968+
std::process::exit(r.unwrap().code().unwrap_or(2));
1969+
}
1970+
};
1971+
if pkg_name == "foo" {
1972+
eprintln!("{}", r#"{
1973+
"$message_type": "diagnostic",
1974+
"message": "mismatched types",
1975+
"code":
1976+
{
1977+
"code": "E0308",
1978+
"explanation": "Expected type did not match the received type.\n\nErroneous code examples:\n\n```compile_fail,E0308\nfn plus_one(x: i32) -> i32 {\n x + 1\n}\n\nplus_one(\"Not a number\");\n// ^^^^^^^^^^^^^^ expected `i32`, found `&str`\n\nif \"Not a bool\" {\n// ^^^^^^^^^^^^ expected `bool`, found `&str`\n}\n\nlet x: f32 = \"Not a float\";\n// --- ^^^^^^^^^^^^^ expected `f32`, found `&str`\n// |\n// expected due to this\n```\n\nThis error occurs when an expression was used in a place where the compiler\nexpected an expression of a different type. It can occur in several cases, the\nmost common being when calling a function and passing an argument which has a\ndifferent type than the matching type in the function declaration.\n"
1979+
},
1980+
"level": "error",
1981+
"spans":
1982+
[
1983+
{
1984+
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
1985+
"byte_start": 23568,
1986+
"byte_end": 23617,
1987+
"line_start": 670,
1988+
"line_end": 670,
1989+
"column_start": 9,
1990+
"column_end": 58,
1991+
"is_primary": true,
1992+
"text":
1993+
[
1994+
{
1995+
"text": " $dst.write_fmt($crate::format_args_nl!($($arg)*))",
1996+
"highlight_start": 9,
1997+
"highlight_end": 58
1998+
}
1999+
],
2000+
"label": "expected `()`, found `Result<(), Error>`",
2001+
"suggested_replacement": null,
2002+
"suggestion_applicability": null,
2003+
"expansion":
2004+
{
2005+
"span":
2006+
{
2007+
"file_name": "lib.rs",
2008+
"byte_start": 144,
2009+
"byte_end": 171,
2010+
"line_start": 5,
2011+
"line_end": 5,
2012+
"column_start": 9,
2013+
"column_end": 36,
2014+
"is_primary": false,
2015+
"text":
2016+
[
2017+
{
2018+
"text": " writeln!(w, \"but not here\")",
2019+
"highlight_start": 9,
2020+
"highlight_end": 36
2021+
}
2022+
],
2023+
"label": null,
2024+
"suggested_replacement": null,
2025+
"suggestion_applicability": null,
2026+
"expansion": null
2027+
},
2028+
"macro_decl_name": "writeln!",
2029+
"def_site_span":
2030+
{
2031+
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
2032+
"byte_start": 23434,
2033+
"byte_end": 23454,
2034+
"line_start": 665,
2035+
"line_end": 665,
2036+
"column_start": 1,
2037+
"column_end": 21,
2038+
"is_primary": false,
2039+
"text":
2040+
[
2041+
{
2042+
"text": "macro_rules! writeln {",
2043+
"highlight_start": 1,
2044+
"highlight_end": 21
2045+
}
2046+
],
2047+
"label": null,
2048+
"suggested_replacement": null,
2049+
"suggestion_applicability": null,
2050+
"expansion": null
2051+
}
2052+
}
2053+
},
2054+
{
2055+
"file_name": "lib.rs",
2056+
"byte_start": 75,
2057+
"byte_end": 177,
2058+
"line_start": 2,
2059+
"line_end": 6,
2060+
"column_start": 5,
2061+
"column_end": 6,
2062+
"is_primary": false,
2063+
"text":
2064+
[
2065+
{
2066+
"text": " if true {",
2067+
"highlight_start": 5,
2068+
"highlight_end": 14
2069+
},
2070+
{
2071+
"text": " writeln!(w, \"`;?` here ->\")?;",
2072+
"highlight_start": 1,
2073+
"highlight_end": 38
2074+
},
2075+
{
2076+
"text": " } else {",
2077+
"highlight_start": 1,
2078+
"highlight_end": 13
2079+
},
2080+
{
2081+
"text": " writeln!(w, \"but not here\")",
2082+
"highlight_start": 1,
2083+
"highlight_end": 36
2084+
},
2085+
{
2086+
"text": " }",
2087+
"highlight_start": 1,
2088+
"highlight_end": 6
2089+
}
2090+
],
2091+
"label": "expected this to be `()`",
2092+
"suggested_replacement": null,
2093+
"suggestion_applicability": null,
2094+
"expansion": null
2095+
}
2096+
],
2097+
"children":
2098+
[
2099+
{
2100+
"message": "use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller",
2101+
"code": null,
2102+
"level": "help",
2103+
"spans":
2104+
[
2105+
{
2106+
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
2107+
"byte_start": 23617,
2108+
"byte_end": 23617,
2109+
"line_start": 670,
2110+
"line_end": 670,
2111+
"column_start": 58,
2112+
"column_end": 58,
2113+
"is_primary": true,
2114+
"text":
2115+
[
2116+
{
2117+
"text": " $dst.write_fmt($crate::format_args_nl!($($arg)*))",
2118+
"highlight_start": 58,
2119+
"highlight_end": 58
2120+
}
2121+
],
2122+
"label": null,
2123+
"suggested_replacement": "?",
2124+
"suggestion_applicability": "HasPlaceholders",
2125+
"expansion":
2126+
{
2127+
"span":
2128+
{
2129+
"file_name": "lib.rs",
2130+
"byte_start": 144,
2131+
"byte_end": 171,
2132+
"line_start": 5,
2133+
"line_end": 5,
2134+
"column_start": 9,
2135+
"column_end": 36,
2136+
"is_primary": false,
2137+
"text":
2138+
[
2139+
{
2140+
"text": " writeln!(w, \"but not here\")",
2141+
"highlight_start": 9,
2142+
"highlight_end": 36
2143+
}
2144+
],
2145+
"label": null,
2146+
"suggested_replacement": null,
2147+
"suggestion_applicability": null,
2148+
"expansion": null
2149+
},
2150+
"macro_decl_name": "writeln!",
2151+
"def_site_span":
2152+
{
2153+
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
2154+
"byte_start": 23434,
2155+
"byte_end": 23454,
2156+
"line_start": 665,
2157+
"line_end": 665,
2158+
"column_start": 1,
2159+
"column_end": 21,
2160+
"is_primary": false,
2161+
"text":
2162+
[
2163+
{
2164+
"text": "macro_rules! writeln {",
2165+
"highlight_start": 1,
2166+
"highlight_end": 21
2167+
}
2168+
],
2169+
"label": null,
2170+
"suggested_replacement": null,
2171+
"suggestion_applicability": null,
2172+
"expansion": null
2173+
}
2174+
}
2175+
}
2176+
],
2177+
"children":
2178+
[],
2179+
"rendered": null
2180+
}
2181+
],
2182+
"rendered": "error[E0308]: mismatched types\n --> lib.rs:5:9\n |\n2 | / if true {\n3 | | writeln!(w, \"`;?` here ->\")?;\n4 | | } else {\n5 | | writeln!(w, \"but not here\")\n | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`\n6 | | }\n | |_____- expected this to be `()`\n |\n = note: expected unit type `()`\n found enum `Result<(), std::fmt::Error>`\n = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider using a semicolon here\n |\n6 | };\n | +\nhelp: you might have meant to return this value\n |\n5 | return writeln!(w, \"but not here\");\n | ++++++ +\nhelp: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller\n --> __SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58\n |\n67| $dst.write_fmt($crate::format_args_nl!($($arg)*))?\n | +\n\n"
2183+
}"#.replace("\n", ""));
2184+
2185+
std::process::exit(2);
2186+
}
2187+
}
2188+
"##.replace("__SYSROOT__", &sysroot))
2189+
.build();
2190+
rustc.cargo("build").run();
2191+
let rustc_bin = rustc.bin("rustc-replay");
2192+
2193+
// The output here should not say `Fixed`.
2194+
//
2195+
// It is OK to compare the full diagnostic output here because the text is
2196+
// hard-coded in rustc-replay. Normally tests should not be checking the
2197+
// compiler output.
2198+
p.cargo("fix --lib --allow-no-vcs --broken-code")
2199+
.env("__CARGO_FIX_YOLO", "1")
2200+
.env("RUSTC", &rustc_bin)
2201+
.with_status(101)
2202+
.with_stderr(r#"[CHECKING] foo v0.0.0 ([..])
2203+
[WARNING] failed to automatically apply fixes suggested by rustc to crate `foo`
2204+
2205+
after fixes were automatically applied the compiler reported errors within these files:
2206+
2207+
* [..]/lib/rustlib/src/rust/library/core/src/macros/mod.rs
2208+
* lib.rs
2209+
2210+
This likely indicates a bug in either rustc or cargo itself,
2211+
and we would appreciate a bug report! You're likely to see
2212+
a number of compiler warnings after this message which cargo
2213+
attempted to fix but failed. If you could open an issue at
2214+
https://github.com/rust-lang/rust/issues
2215+
quoting the full output of this command we'd be very appreciative!
2216+
Note that you may be able to make some more progress in the near-term
2217+
fixing code with the `--broken-code` flag
2218+
2219+
The following errors were reported:
2220+
error[E0308]: mismatched types
2221+
--> lib.rs:5:9
2222+
|
2223+
2 | / if true {
2224+
3 | | writeln!(w, "`;?` here ->")?;
2225+
4 | | } else {
2226+
5 | | writeln!(w, "but not here")
2227+
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
2228+
6 | | }
2229+
| |_____- expected this to be `()`
2230+
|
2231+
= note: expected unit type `()`
2232+
found enum `Result<(), std::fmt::Error>`
2233+
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
2234+
help: consider using a semicolon here
2235+
|
2236+
6 | };
2237+
| +
2238+
help: you might have meant to return this value
2239+
|
2240+
5 | return writeln!(w, "but not here");
2241+
| ++++++ +
2242+
help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
2243+
--> [..]/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58
2244+
|
2245+
67| $dst.write_fmt($crate::format_args_nl!($($arg)*))?
2246+
| +
2247+
2248+
Original diagnostics will follow.
2249+
2250+
error[E0308]: mismatched types
2251+
--> lib.rs:5:9
2252+
|
2253+
2 | / if true {
2254+
3 | | writeln!(w, "`;?` here ->")?;
2255+
4 | | } else {
2256+
5 | | writeln!(w, "but not here")
2257+
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
2258+
6 | | }
2259+
| |_____- expected this to be `()`
2260+
|
2261+
= note: expected unit type `()`
2262+
found enum `Result<(), std::fmt::Error>`
2263+
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
2264+
help: consider using a semicolon here
2265+
|
2266+
6 | };
2267+
| +
2268+
help: you might have meant to return this value
2269+
|
2270+
5 | return writeln!(w, "but not here");
2271+
| ++++++ +
2272+
help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
2273+
--> [..]/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58
2274+
|
2275+
67| $dst.write_fmt($crate::format_args_nl!($($arg)*))?
2276+
| +
2277+
2278+
[ERROR] could not compile `foo` (lib) due to 1 previous error
2279+
"#)
2280+
.run();
2281+
}
2282+
19092283
// This fixes rust-lang/rust#123304.
19102284
// If that lint stops emitting duplicate suggestions,
19112285
// we might need to find a substitution.

0 commit comments

Comments
 (0)