From b81f94a8e944a946fa959736abc6c8516b485926 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 24 Apr 2024 13:32:04 -0500 Subject: [PATCH 1/6] refactor(toml): Move underscore validation to resolving --- src/cargo/util/toml/mod.rs | 82 +++++++++++++++++----------------- src/cargo/util/toml/targets.rs | 17 +++---- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 06887da68d9..414adf9eaaa 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -306,6 +306,8 @@ fn resolve_toml( }; if let Some(original_package) = original_toml.package() { + let package_name = &original_package.name; + let resolved_package = resolve_package_toml(original_package, features, package_root, &inherit)?; let edition = resolved_package @@ -341,6 +343,14 @@ fn resolve_toml( package_root, warnings, )?; + deprecated_underscore( + &original_toml.dev_dependencies2, + &original_toml.dev_dependencies, + "dev-dependencies", + package_name, + "package", + warnings, + ); resolved_toml.dev_dependencies = resolve_dependencies( gctx, edition, @@ -352,6 +362,14 @@ fn resolve_toml( package_root, warnings, )?; + deprecated_underscore( + &original_toml.build_dependencies2, + &original_toml.build_dependencies, + "build-dependencies", + package_name, + "package", + warnings, + ); resolved_toml.build_dependencies = resolve_dependencies( gctx, edition, @@ -376,6 +394,14 @@ fn resolve_toml( package_root, warnings, )?; + deprecated_underscore( + &platform.dev_dependencies2, + &platform.dev_dependencies, + "dev-dependencies", + name, + "platform target", + warnings, + ); let resolved_dev_dependencies = resolve_dependencies( gctx, edition, @@ -387,6 +413,14 @@ fn resolve_toml( package_root, warnings, )?; + deprecated_underscore( + &platform.build_dependencies2, + &platform.build_dependencies, + "build-dependencies", + name, + "platform target", + warnings, + ); let resolved_build_dependencies = resolve_dependencies( gctx, edition, @@ -617,6 +651,14 @@ fn resolve_dependencies<'a>( let mut resolved = dependency_inherit_with(v.clone(), name_in_toml, inherit, package_root, warnings)?; if let manifest::TomlDependency::Detailed(ref mut d) = resolved { + deprecated_underscore( + &d.default_features2, + &d.default_features, + "default-features", + name_in_toml, + "dependency", + warnings, + ); if d.public.is_some() { let public_feature = features.require(Feature::public_dependency()); let with_public_feature = public_feature.is_ok(); @@ -1146,28 +1188,12 @@ fn to_real_manifest( } validate_dependencies(original_toml.dependencies.as_ref(), None, None, warnings)?; - deprecated_underscore( - &original_toml.dev_dependencies2, - &original_toml.dev_dependencies, - "dev-dependencies", - package_name, - "package", - warnings, - ); validate_dependencies( original_toml.dev_dependencies(), None, Some(DepKind::Development), warnings, )?; - deprecated_underscore( - &original_toml.build_dependencies2, - &original_toml.build_dependencies, - "build-dependencies", - package_name, - "package", - warnings, - ); validate_dependencies( original_toml.build_dependencies(), None, @@ -1184,28 +1210,12 @@ fn to_real_manifest( None, warnings, )?; - deprecated_underscore( - &platform.build_dependencies2, - &platform.build_dependencies, - "build-dependencies", - name, - "platform target", - warnings, - ); validate_dependencies( platform.build_dependencies(), platform_kind.as_ref(), Some(DepKind::Build), warnings, )?; - deprecated_underscore( - &platform.dev_dependencies2, - &platform.dev_dependencies, - "dev-dependencies", - name, - "platform target", - warnings, - ); validate_dependencies( platform.dev_dependencies(), platform_kind.as_ref(), @@ -1811,14 +1821,6 @@ fn detailed_dep_to_dependency( let version = orig.version.as_deref(); let mut dep = Dependency::parse(pkg_name, version, new_source_id)?; - deprecated_underscore( - &orig.default_features2, - &orig.default_features, - "default-features", - name_in_toml, - "dependency", - manifest_ctx.warnings, - ); dep.set_features(orig.features.iter().flatten()) .set_default_features(orig.default_features().unwrap_or(true)) .set_optional(orig.optional.unwrap_or(false)) diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index 9c1268a39b8..415b8f43e61 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -97,12 +97,7 @@ pub(super) fn to_targets( warnings, errors, )?; - targets.extend(to_example_targets( - &toml_examples, - package_root, - edition, - warnings, - )?); + targets.extend(to_example_targets(&toml_examples, package_root, edition)?); let toml_tests = resolve_tests( resolved_toml.test.as_ref(), @@ -183,6 +178,10 @@ fn resolve_lib( // Check early to improve error messages validate_lib_name(&lib, warnings)?; + // Checking the original lib + validate_proc_macro(&lib, "library", warnings); + validate_crate_types(&lib, "library", warnings); + if lib.path.is_none() { if let Some(inferred) = inferred { lib.path = Some(PathValue(inferred)); @@ -218,8 +217,6 @@ fn to_lib_target( let Some(lib) = resolved_lib else { return Ok(None); }; - validate_proc_macro(lib, "library", warnings); - validate_crate_types(lib, "library", warnings); let path = lib.path.as_ref().expect("previously resolved"); let path = package_root.join(&path.0); @@ -442,14 +439,12 @@ fn to_example_targets( targets: &[TomlExampleTarget], package_root: &Path, edition: Edition, - warnings: &mut Vec, ) -> CargoResult> { validate_unique_names(&targets, "example")?; let mut result = Vec::new(); for toml in targets { let path = package_root.join(&toml.path.as_ref().expect("previously resolved").0); - validate_crate_types(&toml, "example", warnings); let crate_types = match toml.crate_types() { Some(kinds) => kinds.iter().map(|s| s.into()).collect(), None => Vec::new(), @@ -637,6 +632,8 @@ fn resolve_targets_with_legacy_path( for target in &toml_targets { validate_target_name(target, target_kind_human, target_kind, warnings)?; + validate_proc_macro(target, target_kind_human, warnings); + validate_crate_types(target, target_kind_human, warnings); } let mut result = Vec::new(); From aecb40baac329bab5a27bbfab98b601321d7b4a8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 25 Apr 2024 11:56:32 -0500 Subject: [PATCH 2/6] fix(toml): Remove underscore field support in 2024 This is part of the 2024 Edition and is part of rust-lang/rust#123754 and #13629 --- src/cargo/util/toml/mod.rs | 24 +- src/cargo/util/toml/targets.rs | 28 ++- tests/testsuite/bad_config.rs | 448 +++++++++++++++++++++++++++++++++ 3 files changed, 485 insertions(+), 15 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 414adf9eaaa..b6f97b29c68 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -349,8 +349,9 @@ fn resolve_toml( "dev-dependencies", package_name, "package", + edition, warnings, - ); + )?; resolved_toml.dev_dependencies = resolve_dependencies( gctx, edition, @@ -368,8 +369,9 @@ fn resolve_toml( "build-dependencies", package_name, "package", + edition, warnings, - ); + )?; resolved_toml.build_dependencies = resolve_dependencies( gctx, edition, @@ -400,8 +402,9 @@ fn resolve_toml( "dev-dependencies", name, "platform target", + edition, warnings, - ); + )?; let resolved_dev_dependencies = resolve_dependencies( gctx, edition, @@ -419,8 +422,9 @@ fn resolve_toml( "build-dependencies", name, "platform target", + edition, warnings, - ); + )?; let resolved_build_dependencies = resolve_dependencies( gctx, edition, @@ -657,8 +661,9 @@ fn resolve_dependencies<'a>( "default-features", name_in_toml, "dependency", + edition, warnings, - ); + )?; if d.public.is_some() { let public_feature = features.require(Feature::public_dependency()); let with_public_feature = public_feature.is_ok(); @@ -2323,9 +2328,13 @@ fn deprecated_underscore( new_path: &str, name: &str, kind: &str, + edition: Edition, warnings: &mut Vec, -) { - if old.is_some() && new.is_some() { +) -> CargoResult<()> { + if old.is_some() && Edition::Edition2024 <= edition { + let old_path = new_path.replace("-", "_"); + anyhow::bail!("`{old_path}` is unsupported as of the 2024 edition; instead use `{new_path}`\n(in the `{name}` {kind})"); + } else if old.is_some() && new.is_some() { let old_path = new_path.replace("-", "_"); warnings.push(format!( "`{old_path}` is redundant with `{new_path}`, preferring `{new_path}` in the `{name}` {kind}" @@ -2336,6 +2345,7 @@ fn deprecated_underscore( "`{old_path}` is deprecated in favor of `{new_path}` and will not work in the 2024 edition\n(in the `{name}` {kind})" )) } + Ok(()) } fn warn_on_unused(unused: &BTreeSet, warnings: &mut Vec) { diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index 415b8f43e61..1795cf24752 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -179,8 +179,8 @@ fn resolve_lib( validate_lib_name(&lib, warnings)?; // Checking the original lib - validate_proc_macro(&lib, "library", warnings); - validate_crate_types(&lib, "library", warnings); + validate_proc_macro(&lib, "library", edition, warnings)?; + validate_crate_types(&lib, "library", edition, warnings)?; if lib.path.is_none() { if let Some(inferred) = inferred { @@ -632,8 +632,8 @@ fn resolve_targets_with_legacy_path( for target in &toml_targets { validate_target_name(target, target_kind_human, target_kind, warnings)?; - validate_proc_macro(target, target_kind_human, warnings); - validate_crate_types(target, target_kind_human, warnings); + validate_proc_macro(target, target_kind_human, edition, warnings)?; + validate_crate_types(target, target_kind_human, edition, warnings)?; } let mut result = Vec::new(); @@ -1098,24 +1098,36 @@ fn name_or_panic(target: &TomlTarget) -> &str { .unwrap_or_else(|| panic!("target name is required")) } -fn validate_proc_macro(target: &TomlTarget, kind: &str, warnings: &mut Vec) { +fn validate_proc_macro( + target: &TomlTarget, + kind: &str, + edition: Edition, + warnings: &mut Vec, +) -> CargoResult<()> { deprecated_underscore( &target.proc_macro2, &target.proc_macro, "proc-macro", name_or_panic(target), format!("{kind} target").as_str(), + edition, warnings, - ); + ) } -fn validate_crate_types(target: &TomlTarget, kind: &str, warnings: &mut Vec) { +fn validate_crate_types( + target: &TomlTarget, + kind: &str, + edition: Edition, + warnings: &mut Vec, +) -> CargoResult<()> { deprecated_underscore( &target.crate_type2, &target.crate_type, "crate-type", name_or_panic(target), format!("{kind} target").as_str(), + edition, warnings, - ); + ) } diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs index a45e654b5fa..07ae1d76897 100644 --- a/tests/testsuite/bad_config.rs +++ b/tests/testsuite/bad_config.rs @@ -841,6 +841,50 @@ fn dev_dependencies2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn dev_dependencies2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + + [dev_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies` + (in the `foo` package) +", + ) + .run(); +} + #[cargo_test] fn dev_dependencies2_conflict() { let p = project() @@ -916,6 +960,50 @@ fn build_dependencies2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn build_dependencies2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + + [build_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `build_dependencies` is unsupported as of the 2024 edition; instead use `build-dependencies` + (in the `foo` package) +", + ) + .run(); +} + #[cargo_test] fn build_dependencies2_conflict() { let p = project() @@ -983,6 +1071,42 @@ fn lib_crate_type2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn lib_crate_type2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [lib] + name = "foo" + crate_type = ["staticlib", "dylib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `crate_type` is unsupported as of the 2024 edition; instead use `crate-type` + (in the `foo` library target) +", + ) + .run(); +} + #[cargo_test] fn lib_crate_type2_conflict() { let p = project() @@ -1060,6 +1184,59 @@ fn examples_crate_type2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn examples_crate_type2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [[example]] + name = "ex" + path = "examples/ex.rs" + crate_type = ["proc_macro"] + [[example]] + name = "goodbye" + path = "examples/ex-goodbye.rs" + crate_type = ["rlib", "staticlib"] + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + fn main() { println!("ex"); } + "#, + ) + .file( + "examples/ex-goodbye.rs", + r#" + fn main() { println!("goodbye"); } + "#, + ) + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `crate_type` is unsupported as of the 2024 edition; instead use `crate-type` + (in the `ex` example target) +", + ) + .run(); +} + #[cargo_test] fn examples_crate_type2_conflict() { let p = project() @@ -1148,6 +1325,53 @@ fn cargo_platform_build_dependencies2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn cargo_platform_build_dependencies2_2024() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + build = "build.rs" + + [target.{host}.build_dependencies] + build = {{ path = "build" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "build.rs", + "extern crate build; fn main() { build::build(); }", + ) + .file("build/Cargo.toml", &basic_manifest("build", "0.5.0")) + .file("build/src/lib.rs", "pub fn build() {}") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr(format!( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `build_dependencies` is unsupported as of the 2024 edition; instead use `build-dependencies` + (in the `{host}` platform target) +" + )) + .run(); +} + #[cargo_test] fn cargo_platform_build_dependencies2_conflict() { let host = rustc_host(); @@ -1228,6 +1452,52 @@ fn cargo_platform_dev_dependencies2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn cargo_platform_dev_dependencies2_2024() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [target.{host}.dev_dependencies] + dev = {{ path = "dev" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "tests/foo.rs", + "extern crate dev; #[test] fn foo() { dev::dev() }", + ) + .file("dev/Cargo.toml", &basic_manifest("dev", "0.5.0")) + .file("dev/src/lib.rs", "pub fn dev() {}") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr(format!( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies` + (in the `{host}` platform target) +" + )) + .run(); +} + #[cargo_test] fn cargo_platform_dev_dependencies2_conflict() { let host = rustc_host(); @@ -1312,6 +1582,57 @@ fn default_features2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn default_features2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + authors = [] + + [dependencies] + a = { path = "a", features = ["f1"], default_features = false } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `default_features` is unsupported as of the 2024 edition; instead use `default-features` + (in the `a` dependency) +", + ) + .run(); +} + #[cargo_test] fn default_features2_conflict() { let p = project() @@ -1437,6 +1758,99 @@ warning: [CWD]/workspace_only/Cargo.toml: `default_features` is deprecated in fa .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn workspace_default_features2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["workspace_only", "dep_workspace_only", "package_only", "dep_package_only"] + + [workspace.dependencies] + dep_workspace_only = { path = "dep_workspace_only", default_features = true } + dep_package_only = { path = "dep_package_only" } + "#, + ) + .file( + "workspace_only/Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "workspace_only" + version = "0.1.0" + edition = "2024" + authors = [] + + [dependencies] + dep_workspace_only.workspace = true + "#, + ) + .file("workspace_only/src/lib.rs", "") + .file( + "dep_workspace_only/Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "dep_workspace_only" + version = "0.1.0" + edition = "2024" + authors = [] + "#, + ) + .file("dep_workspace_only/src/lib.rs", "") + .file( + "package_only/Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "package_only" + version = "0.1.0" + edition = "2024" + authors = [] + + [dependencies] + dep_package_only = { workspace = true, default_features = true } + "#, + ) + .file("package_only/src/lib.rs", "") + .file( + "dep_package_only/Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "dep_package_only" + version = "0.1.0" + edition = "2024" + authors = [] + "#, + ) + .file("dep_package_only/src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to load manifest for workspace member `[CWD]/workspace_only` +referenced by workspace at `[CWD]/Cargo.toml` + +Caused by: + failed to parse manifest at `[CWD]/workspace_only/Cargo.toml` + +Caused by: + `default_features` is unsupported as of the 2024 edition; instead use `default-features` + (in the `dep_workspace_only` dependency) +", + ) + .run(); +} + #[cargo_test] fn proc_macro2() { let foo = project() @@ -1464,6 +1878,40 @@ fn proc_macro2() { .run(); } +#[cargo_test(nightly, reason = "edition2024 is not stable")] +fn proc_macro2_2024() { + let foo = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + [lib] + proc_macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `proc_macro` is unsupported as of the 2024 edition; instead use `proc-macro` + (in the `foo` library target) +", + ) + .run(); +} + #[cargo_test] fn proc_macro2_conflict() { let foo = project() From bcf032e5bed5ee87fa6f8d85a60d458a2bb4e770 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 25 Apr 2024 12:44:53 -0500 Subject: [PATCH 3/6] test(fix): Show underscore field migration --- tests/testsuite/fix.rs | 162 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index 7997a68ae62..179d7d9c275 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -2050,6 +2050,168 @@ edition = "2021" ); } +#[cargo_test] +fn migrate_rename_underscore_fields() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["edition2024"] + +[workspace.dependencies] +# Before default_features +a = {path = "a", default_features = false} # After default_features value +# After default_features line + +[package] +name = "foo" +edition = "2021" + +[lib] +name = "foo" +# Before crate_type +crate_type = ["staticlib", "dylib"] # After crate_type value +# After crate_type line + +[[example]] +name = "ex" +path = "examples/ex.rs" +# Before crate_type +crate_type = ["proc-macro"] # After crate_type value +# After crate_type line + +# Before dev_dependencies +[ dev_dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default_features = false} +# After dev_dependencies table + +# Before build_dependencies +[ build_dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default_features = false} +# After build_dependencies table + +# Before dev_dependencies +[ target.'cfg(any())'.dev_dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default_features = false} +# After dev_dependencies table + +# Before build_dependencies +[ target.'cfg(any())'.build_dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default_features = false} +# After build_dependencies table +"#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + fn main() { println!("ex"); } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_stderr( + "\ +[MIGRATING] Cargo.toml from 2021 edition to 2024 +[WARNING] [CWD]/Cargo.toml: `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition +(in the `foo` package) +[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition +(in the `a` dependency) +[WARNING] [CWD]/Cargo.toml: `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition +(in the `foo` package) +[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition +(in the `a` dependency) +[WARNING] [CWD]/Cargo.toml: `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition +(in the `cfg(any())` platform target) +[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition +(in the `a` dependency) +[WARNING] [CWD]/Cargo.toml: `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition +(in the `cfg(any())` platform target) +[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition +(in the `a` dependency) +[WARNING] [CWD]/Cargo.toml: `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition +(in the `foo` library target) +[WARNING] [CWD]/Cargo.toml: `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition +(in the `ex` example target) + Locking 2 packages to latest compatible versions + Checking a v0.0.1 ([CWD]/a) +[CHECKING] foo v0.0.0 ([CWD]) +[MIGRATING] src/lib.rs from 2021 edition to 2024 +[MIGRATING] examples/ex.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s +", + ) + .run(); + assert_eq!( + p.read_file("Cargo.toml"), + r#" +cargo-features = ["edition2024"] + +[workspace.dependencies] +# Before default_features +a = {path = "a", default_features = false} # After default_features value +# After default_features line + +[package] +name = "foo" +edition = "2021" + +[lib] +name = "foo" +# Before crate_type +crate_type = ["staticlib", "dylib"] # After crate_type value +# After crate_type line + +[[example]] +name = "ex" +path = "examples/ex.rs" +# Before crate_type +crate_type = ["proc-macro"] # After crate_type value +# After crate_type line + +# Before dev_dependencies +[ dev_dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default_features = false} +# After dev_dependencies table + +# Before build_dependencies +[ build_dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default_features = false} +# After build_dependencies table + +# Before dev_dependencies +[ target.'cfg(any())'.dev_dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default_features = false} +# After dev_dependencies table + +# Before build_dependencies +[ target.'cfg(any())'.build_dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default_features = false} +# After build_dependencies table +"# + ); +} + #[cargo_test] fn add_feature_for_unused_dep() { Package::new("bar", "0.1.0").publish(); From a71b8fecf309178684c747256aa21a3b13dad61f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 25 Apr 2024 13:22:06 -0500 Subject: [PATCH 4/6] feat(fix): Migrate underscore toml fields --- src/cargo/ops/fix.rs | 83 ++++++++++++++++++++++++++++++++++++++++++ tests/testsuite/fix.rs | 45 +++++++---------------- 2 files changed, 96 insertions(+), 32 deletions(-) diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 743bd486646..686ae3b318e 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -254,10 +254,53 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { let mut fixes = 0; let root = document.as_table_mut(); + + if let Some(workspace) = root + .get_mut("workspace") + .and_then(|t| t.as_table_like_mut()) + { + // strictly speaking, the edition doesn't apply to this table but it should be safe + // enough + fixes += rename_dep_fields_2024(workspace, "dependencies"); + } + fixes += add_feature_for_unused_deps(pkg, root); if rename_table(root, "project", "package") { fixes += 1; } + if let Some(target) = root.get_mut("lib").and_then(|t| t.as_table_like_mut()) { + fixes += rename_target_fields_2024(target); + } + fixes += rename_array_of_target_fields_2024(root, "bin"); + fixes += rename_array_of_target_fields_2024(root, "example"); + fixes += rename_array_of_target_fields_2024(root, "test"); + fixes += rename_array_of_target_fields_2024(root, "bench"); + fixes += rename_dep_fields_2024(root, "dependencies"); + if rename_table(root, "dev_dependencies", "dev-dependencies") { + fixes += 1; + } + fixes += rename_dep_fields_2024(root, "dev-dependencies"); + if rename_table(root, "build_dependencies", "build-dependencies") { + fixes += 1; + } + fixes += rename_dep_fields_2024(root, "build-dependencies"); + for target in root + .get_mut("target") + .and_then(|t| t.as_table_like_mut()) + .iter_mut() + .flat_map(|t| t.iter_mut()) + .filter_map(|(_k, t)| t.as_table_like_mut()) + { + fixes += rename_dep_fields_2024(target, "dependencies"); + if rename_table(target, "dev_dependencies", "dev-dependencies") { + fixes += 1; + } + fixes += rename_dep_fields_2024(target, "dev-dependencies"); + if rename_table(target, "build_dependencies", "build-dependencies") { + fixes += 1; + } + fixes += rename_dep_fields_2024(target, "build-dependencies"); + } if 0 < fixes { let verb = if fixes == 1 { "fix" } else { "fixes" }; @@ -274,6 +317,46 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { Ok(()) } +fn rename_dep_fields_2024(parent: &mut dyn toml_edit::TableLike, dep_kind: &str) -> usize { + let mut fixes = 0; + for target in parent + .get_mut(dep_kind) + .and_then(|t| t.as_table_like_mut()) + .iter_mut() + .flat_map(|t| t.iter_mut()) + .filter_map(|(_k, t)| t.as_table_like_mut()) + { + if rename_table(target, "default_features", "default-features") { + fixes += 1; + } + } + fixes +} + +fn rename_array_of_target_fields_2024(root: &mut dyn toml_edit::TableLike, kind: &str) -> usize { + let mut fixes = 0; + for target in root + .get_mut(kind) + .and_then(|t| t.as_array_of_tables_mut()) + .iter_mut() + .flat_map(|t| t.iter_mut()) + { + fixes += rename_target_fields_2024(target); + } + fixes +} + +fn rename_target_fields_2024(target: &mut dyn toml_edit::TableLike) -> usize { + let mut fixes = 0; + if rename_table(target, "crate_type", "crate-type") { + fixes += 1; + } + if rename_table(target, "proc_macro", "proc-macro") { + fixes += 1; + } + fixes +} + fn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> bool { let Some(old_key) = parent.key(old).cloned() else { return false; diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index 179d7d9c275..2eb3c79ae54 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -2129,26 +2129,7 @@ a = {path = "a", default_features = false} .with_stderr( "\ [MIGRATING] Cargo.toml from 2021 edition to 2024 -[WARNING] [CWD]/Cargo.toml: `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition -(in the `foo` package) -[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition -(in the `a` dependency) -[WARNING] [CWD]/Cargo.toml: `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition -(in the `foo` package) -[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition -(in the `a` dependency) -[WARNING] [CWD]/Cargo.toml: `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition -(in the `cfg(any())` platform target) -[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition -(in the `a` dependency) -[WARNING] [CWD]/Cargo.toml: `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition -(in the `cfg(any())` platform target) -[WARNING] [CWD]/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition -(in the `a` dependency) -[WARNING] [CWD]/Cargo.toml: `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition -(in the `foo` library target) -[WARNING] [CWD]/Cargo.toml: `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition -(in the `ex` example target) +[FIXED] Cargo.toml (11 fixes) Locking 2 packages to latest compatible versions Checking a v0.0.1 ([CWD]/a) [CHECKING] foo v0.0.0 ([CWD]) @@ -2165,7 +2146,7 @@ cargo-features = ["edition2024"] [workspace.dependencies] # Before default_features -a = {path = "a", default_features = false} # After default_features value +a = {path = "a", default-features = false} # After default_features value # After default_features line [package] @@ -2175,40 +2156,40 @@ edition = "2021" [lib] name = "foo" # Before crate_type -crate_type = ["staticlib", "dylib"] # After crate_type value +crate-type = ["staticlib", "dylib"] # After crate_type value # After crate_type line [[example]] name = "ex" path = "examples/ex.rs" # Before crate_type -crate_type = ["proc-macro"] # After crate_type value +crate-type = ["proc-macro"] # After crate_type value # After crate_type line # Before dev_dependencies -[ dev_dependencies ] # After dev_dependencies header +[ dev-dependencies ] # After dev_dependencies header # After dev_dependencies line -a = {path = "a", default_features = false} +a = {path = "a", default-features = false} # After dev_dependencies table # Before build_dependencies -[ build_dependencies ] # After build_dependencies header +[ build-dependencies ] # After build_dependencies header # After build_dependencies line -a = {path = "a", default_features = false} +a = {path = "a", default-features = false} # After build_dependencies table # Before dev_dependencies -[ target.'cfg(any())'.dev_dependencies ] # After dev_dependencies header +[ target.'cfg(any())'.dev-dependencies ] # After dev_dependencies header # After dev_dependencies line -a = {path = "a", default_features = false} +a = {path = "a", default-features = false} # After dev_dependencies table # Before build_dependencies -[ target.'cfg(any())'.build_dependencies ] # After build_dependencies header +[ target.'cfg(any())'.build-dependencies ] # After build_dependencies header # After build_dependencies line -a = {path = "a", default_features = false} +a = {path = "a", default-features = false} # After build_dependencies table -"# +"#, ); } From 57b4ab90a622b3193a1f74225fd37480ffe03fe6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 10:53:28 -0500 Subject: [PATCH 5/6] refactor(toml): Consolidate field name conversion --- src/cargo/util/toml/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index b6f97b29c68..96720937a92 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -2331,16 +2331,14 @@ fn deprecated_underscore( edition: Edition, warnings: &mut Vec, ) -> CargoResult<()> { + let old_path = new_path.replace("-", "_"); if old.is_some() && Edition::Edition2024 <= edition { - let old_path = new_path.replace("-", "_"); anyhow::bail!("`{old_path}` is unsupported as of the 2024 edition; instead use `{new_path}`\n(in the `{name}` {kind})"); } else if old.is_some() && new.is_some() { - let old_path = new_path.replace("-", "_"); warnings.push(format!( "`{old_path}` is redundant with `{new_path}`, preferring `{new_path}` in the `{name}` {kind}" )) } else if old.is_some() { - let old_path = new_path.replace("-", "_"); warnings.push(format!( "`{old_path}` is deprecated in favor of `{new_path}` and will not work in the 2024 edition\n(in the `{name}` {kind})" )) From 8ab7683f93b942f775ef40159c88fe428844fbd3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 26 Apr 2024 10:57:50 -0500 Subject: [PATCH 6/6] refactor(fix): Be consistent in fix tracking --- src/cargo/ops/fix.rs | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 686ae3b318e..398ad46b40f 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -265,9 +265,7 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { } fixes += add_feature_for_unused_deps(pkg, root); - if rename_table(root, "project", "package") { - fixes += 1; - } + fixes += rename_table(root, "project", "package"); if let Some(target) = root.get_mut("lib").and_then(|t| t.as_table_like_mut()) { fixes += rename_target_fields_2024(target); } @@ -276,13 +274,9 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { fixes += rename_array_of_target_fields_2024(root, "test"); fixes += rename_array_of_target_fields_2024(root, "bench"); fixes += rename_dep_fields_2024(root, "dependencies"); - if rename_table(root, "dev_dependencies", "dev-dependencies") { - fixes += 1; - } + fixes += rename_table(root, "dev_dependencies", "dev-dependencies"); fixes += rename_dep_fields_2024(root, "dev-dependencies"); - if rename_table(root, "build_dependencies", "build-dependencies") { - fixes += 1; - } + fixes += rename_table(root, "build_dependencies", "build-dependencies"); fixes += rename_dep_fields_2024(root, "build-dependencies"); for target in root .get_mut("target") @@ -292,13 +286,9 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { .filter_map(|(_k, t)| t.as_table_like_mut()) { fixes += rename_dep_fields_2024(target, "dependencies"); - if rename_table(target, "dev_dependencies", "dev-dependencies") { - fixes += 1; - } + fixes += rename_table(target, "dev_dependencies", "dev-dependencies"); fixes += rename_dep_fields_2024(target, "dev-dependencies"); - if rename_table(target, "build_dependencies", "build-dependencies") { - fixes += 1; - } + fixes += rename_table(target, "build_dependencies", "build-dependencies"); fixes += rename_dep_fields_2024(target, "build-dependencies"); } @@ -326,9 +316,7 @@ fn rename_dep_fields_2024(parent: &mut dyn toml_edit::TableLike, dep_kind: &str) .flat_map(|t| t.iter_mut()) .filter_map(|(_k, t)| t.as_table_like_mut()) { - if rename_table(target, "default_features", "default-features") { - fixes += 1; - } + fixes += rename_table(target, "default_features", "default-features"); } fixes } @@ -348,18 +336,14 @@ fn rename_array_of_target_fields_2024(root: &mut dyn toml_edit::TableLike, kind: fn rename_target_fields_2024(target: &mut dyn toml_edit::TableLike) -> usize { let mut fixes = 0; - if rename_table(target, "crate_type", "crate-type") { - fixes += 1; - } - if rename_table(target, "proc_macro", "proc-macro") { - fixes += 1; - } + fixes += rename_table(target, "crate_type", "crate-type"); + fixes += rename_table(target, "proc_macro", "proc-macro"); fixes } -fn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> bool { +fn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> usize { let Some(old_key) = parent.key(old).cloned() else { - return false; + return 0; }; let project = parent.remove(old).expect("returned early"); @@ -369,7 +353,7 @@ fn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> *new_key.dotted_decor_mut() = old_key.dotted_decor().clone(); *new_key.leaf_decor_mut() = old_key.leaf_decor().clone(); } - true + 1 } fn add_feature_for_unused_deps(pkg: &Package, parent: &mut dyn toml_edit::TableLike) -> usize {