Skip to content

Commit 0810627

Browse files
committed
fix(cargo-fix): dont fix into standard library
This takes a more aggressive approach by stop any write into sysroot.
1 parent 8410c1e commit 0810627

File tree

2 files changed

+43
-55
lines changed

2 files changed

+43
-55
lines changed

src/cargo/ops/fix.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use rustfix::CodeFix;
5050
use semver::Version;
5151
use tracing::{debug, trace, warn};
5252

53+
use crate::core::compiler::CompileKind;
5354
use crate::core::compiler::RustcTargetData;
5455
use crate::core::resolver::features::{DiffMap, FeatureOpts, FeatureResolver, FeaturesFor};
5556
use crate::core::resolver::{HasDevUnits, Resolve, ResolveBehavior};
@@ -78,6 +79,14 @@ const EDITION_ENV_INTERNAL: &str = "__CARGO_FIX_EDITION";
7879
/// **Internal only.**
7980
/// For passing [`FixOptions::idioms`] through to cargo running in proxy mode.
8081
const IDIOMS_ENV_INTERNAL: &str = "__CARGO_FIX_IDIOMS";
82+
/// **Internal only.**
83+
/// The sysroot path.
84+
///
85+
/// This is for preventing `cargo fix` from fixing rust std/core libs. See
86+
///
87+
/// * <https://github.com/rust-lang/cargo/issues/9857>
88+
/// * <https://github.com/rust-lang/rust/issues/88514#issuecomment-2043469384>
89+
const SYSROOT_INTERNAL: &str = "__CARGO_FIX_RUST_SRC";
8190

8291
pub struct FixOptions {
8392
pub edition: bool,
@@ -97,6 +106,8 @@ pub fn fix(
97106
) -> CargoResult<()> {
98107
check_version_control(gctx, opts)?;
99108

109+
let mut target_data =
110+
RustcTargetData::new(original_ws, &opts.compile_opts.build_config.requested_kinds)?;
100111
if opts.edition {
101112
let specs = opts.compile_opts.spec.to_package_id_specs(&original_ws)?;
102113
let members: Vec<&Package> = original_ws
@@ -105,7 +116,7 @@ pub fn fix(
105116
.collect();
106117
migrate_manifests(original_ws, &members)?;
107118

108-
check_resolver_change(&original_ws, opts)?;
119+
check_resolver_change(&original_ws, &mut target_data, opts)?;
109120
}
110121
let mut ws = Workspace::new(&root_manifest, gctx)?;
111122
ws.set_honor_rust_version(original_ws.honor_rust_version());
@@ -129,6 +140,11 @@ pub fn fix(
129140
wrapper.env(IDIOMS_ENV_INTERNAL, "1");
130141
}
131142

143+
let sysroot = &target_data.info(CompileKind::Host).sysroot;
144+
if sysroot.is_dir() {
145+
wrapper.env(SYSROOT_INTERNAL, sysroot);
146+
}
147+
132148
*opts
133149
.compile_opts
134150
.build_config
@@ -328,7 +344,11 @@ fn add_feature_for_unused_deps(pkg: &Package, parent: &mut dyn toml_edit::TableL
328344
fixes
329345
}
330346

331-
fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<()> {
347+
fn check_resolver_change<'gctx>(
348+
ws: &Workspace<'gctx>,
349+
target_data: &mut RustcTargetData<'gctx>,
350+
opts: &FixOptions,
351+
) -> CargoResult<()> {
332352
let root = ws.root_maybe();
333353
match root {
334354
MaybePackage::Package(root_pkg) => {
@@ -355,12 +375,10 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
355375
// 2018 without `resolver` set must be V1
356376
assert_eq!(ws.resolve_behavior(), ResolveBehavior::V1);
357377
let specs = opts.compile_opts.spec.to_package_id_specs(ws)?;
358-
let mut target_data =
359-
RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
360378
let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
361379
let ws_resolve = ops::resolve_ws_with_opts(
362380
ws,
363-
&mut target_data,
381+
target_data,
364382
&opts.compile_opts.build_config.requested_kinds,
365383
&opts.compile_opts.cli_features,
366384
&specs,
@@ -371,7 +389,7 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
371389
let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);
372390
let v2_features = FeatureResolver::resolve(
373391
ws,
374-
&mut target_data,
392+
target_data,
375393
&ws_resolve.targeted_resolve,
376394
&ws_resolve.pkg_set,
377395
&opts.compile_opts.cli_features,
@@ -677,7 +695,8 @@ fn rustfix_crate(
677695
// We'll generate new errors below.
678696
file.errors_applying_fixes.clear();
679697
}
680-
(last_output, last_made_changes) = rustfix_and_fix(&mut files, rustc, filename, gctx)?;
698+
(last_output, last_made_changes) =
699+
rustfix_and_fix(&mut files, rustc, filename, args, gctx)?;
681700
if current_iteration == 0 {
682701
first_output = Some(last_output.clone());
683702
}
@@ -734,6 +753,7 @@ fn rustfix_and_fix(
734753
files: &mut HashMap<String, FixedFile>,
735754
rustc: &ProcessBuilder,
736755
filename: &Path,
756+
args: &FixArgs,
737757
gctx: &GlobalContext,
738758
) -> CargoResult<(Output, bool)> {
739759
// If not empty, filter by these lints.
@@ -798,10 +818,17 @@ fn rustfix_and_fix(
798818
continue;
799819
};
800820

821+
let file_path = Path::new(&file_name);
801822
// Do not write into registry cache. See rust-lang/cargo#9857.
802-
if Path::new(&file_name).starts_with(home_path) {
823+
if file_path.starts_with(home_path) {
803824
continue;
804825
}
826+
// Do not write into standard library source. See rust-lang/cargo#9857.
827+
if let Some(sysroot) = args.sysroot.as_deref() {
828+
if file_path.starts_with(sysroot) {
829+
continue;
830+
}
831+
}
805832

806833
if !file_names.clone().all(|f| f == &file_name) {
807834
trace!("rejecting as it changes multiple files: {:?}", suggestion);
@@ -958,6 +985,8 @@ struct FixArgs {
958985
other: Vec<OsString>,
959986
/// Path to the `rustc` executable.
960987
rustc: PathBuf,
988+
/// Path to host sysroot.
989+
sysroot: Option<PathBuf>,
961990
}
962991

963992
impl FixArgs {
@@ -1029,13 +1058,19 @@ impl FixArgs {
10291058
.saturating_next()
10301059
});
10311060

1061+
// ALLOWED: For the internal mechanism of `cargo fix` only.
1062+
// Shouldn't be set directly by anyone.
1063+
#[allow(clippy::disallowed_methods)]
1064+
let sysroot = env::var_os(SYSROOT_INTERNAL).map(PathBuf::from);
1065+
10321066
Ok(FixArgs {
10331067
file,
10341068
prepare_for_edition,
10351069
idioms,
10361070
enabled_edition,
10371071
other,
10381072
rustc,
1073+
sysroot,
10391074
})
10401075
}
10411076

tests/testsuite/fix.rs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,53 +2200,6 @@ fn fix_in_rust_src() {
22002200
.env("RUSTC", &rustc_bin)
22012201
.with_status(101)
22022202
.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-
22502203
error[E0308]: mismatched types
22512204
--> lib.rs:5:9
22522205
|

0 commit comments

Comments
 (0)