@@ -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