@@ -50,6 +50,7 @@ use rustfix::CodeFix;
5050use semver:: Version ;
5151use tracing:: { debug, trace, warn} ;
5252
53+ use crate :: core:: compiler:: CompileKind ;
5354use crate :: core:: compiler:: RustcTargetData ;
5455use crate :: core:: resolver:: features:: { DiffMap , FeatureOpts , FeatureResolver , FeaturesFor } ;
5556use 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.
8081const 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
8291pub 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
963992impl 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
0 commit comments