From f71515698ee4b168f8ee33cb7b40159ed0a0e2e2 Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Mon, 29 Apr 2024 14:05:17 -0500
Subject: [PATCH 1/8] refactor(toml): Pull bin crate-types validation out

---
 src/cargo/util/toml/targets.rs | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs
index 0dca91b621f..126026b5163 100644
--- a/src/cargo/util/toml/targets.rs
+++ b/src/cargo/util/toml/targets.rs
@@ -64,6 +64,7 @@ pub(super) fn to_targets(
         resolved_toml.bin.as_deref().unwrap_or_default(),
         package_root,
         edition,
+        warnings,
         errors,
     )?);
 
@@ -308,6 +309,7 @@ fn to_bin_targets(
     bins: &[TomlBinTarget],
     package_root: &Path,
     edition: Edition,
+    warnings: &mut Vec<String>,
     errors: &mut Vec<String>,
 ) -> CargoResult<Vec<Target>> {
     // This loop performs basic checks on each of the TomlTarget in `bins`.
@@ -318,17 +320,7 @@ fn to_bin_targets(
             features.require(Feature::different_binary_name())?;
         }
 
-        if let Some(crate_types) = bin.crate_types() {
-            if !crate_types.is_empty() {
-                let name = name_or_panic(bin);
-                errors.push(format!(
-                    "the target `{}` is a binary and can't have any \
-                     crate-types set (currently \"{}\")",
-                    name,
-                    crate_types.join(", ")
-                ));
-            }
-        }
+        validate_bin_crate_types(bin, warnings, errors)?;
 
         if bin.proc_macro() == Some(true) {
             let name = name_or_panic(bin);
@@ -1093,6 +1085,25 @@ fn validate_proc_macro(
     )
 }
 
+fn validate_bin_crate_types(
+    target: &TomlTarget,
+    _warnings: &mut Vec<String>,
+    errors: &mut Vec<String>,
+) -> CargoResult<()> {
+    if let Some(crate_types) = target.crate_types() {
+        if !crate_types.is_empty() {
+            let name = name_or_panic(target);
+            errors.push(format!(
+                "the target `{}` is a binary and can't have any \
+                     crate-types set (currently \"{}\")",
+                name,
+                crate_types.join(", ")
+            ));
+        }
+    }
+    Ok(())
+}
+
 fn validate_crate_types(
     target: &TomlTarget,
     kind: &str,

From 330d5ea93a7553f262a3d99f200d9219e38dfc7e Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Mon, 29 Apr 2024 14:06:23 -0500
Subject: [PATCH 2/8] refactor(toml): Pull bin proc-macro validation out

---
 src/cargo/util/toml/targets.rs | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs
index 126026b5163..d5d107b7a30 100644
--- a/src/cargo/util/toml/targets.rs
+++ b/src/cargo/util/toml/targets.rs
@@ -321,15 +321,7 @@ fn to_bin_targets(
         }
 
         validate_bin_crate_types(bin, warnings, errors)?;
-
-        if bin.proc_macro() == Some(true) {
-            let name = name_or_panic(bin);
-            errors.push(format!(
-                "the target `{}` is a binary and can't have `proc-macro` \
-                 set `true`",
-                name
-            ));
-        }
+        validate_bin_proc_macro(bin, warnings, errors)?;
     }
 
     validate_unique_names(&bins, "binary")?;
@@ -1068,6 +1060,22 @@ fn name_or_panic(target: &TomlTarget) -> &str {
         .unwrap_or_else(|| panic!("target name is required"))
 }
 
+fn validate_bin_proc_macro(
+    target: &TomlTarget,
+    _warnings: &mut Vec<String>,
+    errors: &mut Vec<String>,
+) -> CargoResult<()> {
+    if target.proc_macro() == Some(true) {
+        let name = name_or_panic(target);
+        errors.push(format!(
+            "the target `{}` is a binary and can't have `proc-macro` \
+                 set `true`",
+            name
+        ));
+    }
+    Ok(())
+}
+
 fn validate_proc_macro(
     target: &TomlTarget,
     kind: &str,

From 640d41d6412cdf3967ef94497e24b73ec1522dd5 Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Mon, 29 Apr 2024 14:30:46 -0500
Subject: [PATCH 3/8] refactor(toml): Validate bin in resolve, like other
 targets

---
 src/cargo/util/toml/mod.rs     |  4 ++--
 src/cargo/util/toml/targets.rs | 11 +++--------
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs
index a03e8ba5254..82c154bf218 100644
--- a/src/cargo/util/toml/mod.rs
+++ b/src/cargo/util/toml/mod.rs
@@ -333,6 +333,7 @@ fn resolve_toml(
             edition,
             original_package.autobins,
             warnings,
+            errors,
             resolved_toml.lib.is_some(),
         )?);
         resolved_toml.example = Some(targets::resolve_examples(
@@ -1070,7 +1071,7 @@ fn to_real_manifest(
     manifest_file: &Path,
     gctx: &GlobalContext,
     warnings: &mut Vec<String>,
-    errors: &mut Vec<String>,
+    _errors: &mut Vec<String>,
 ) -> CargoResult<Manifest> {
     let embedded = is_embedded(manifest_file);
     let package_root = manifest_file.parent().unwrap();
@@ -1212,7 +1213,6 @@ fn to_real_manifest(
         edition,
         &resolved_package.metabuild,
         warnings,
-        errors,
     )?;
 
     if targets.iter().all(|t| t.is_custom_build()) {
diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs
index d5d107b7a30..efa86ec04a7 100644
--- a/src/cargo/util/toml/targets.rs
+++ b/src/cargo/util/toml/targets.rs
@@ -40,7 +40,6 @@ pub(super) fn to_targets(
     edition: Edition,
     metabuild: &Option<StringOrVec>,
     warnings: &mut Vec<String>,
-    errors: &mut Vec<String>,
 ) -> CargoResult<Vec<Target>> {
     let mut targets = Vec::new();
 
@@ -64,8 +63,6 @@ pub(super) fn to_targets(
         resolved_toml.bin.as_deref().unwrap_or_default(),
         package_root,
         edition,
-        warnings,
-        errors,
     )?);
 
     targets.extend(to_example_targets(
@@ -261,6 +258,7 @@ pub fn resolve_bins(
     edition: Edition,
     autodiscover: Option<bool>,
     warnings: &mut Vec<String>,
+    errors: &mut Vec<String>,
     has_lib: bool,
 ) -> CargoResult<Vec<TomlBinTarget>> {
     let inferred = inferred_bins(package_root, package_name);
@@ -279,6 +277,8 @@ pub fn resolve_bins(
 
     for bin in &mut bins {
         validate_bin_name(bin, warnings)?;
+        validate_bin_crate_types(bin, warnings, errors)?;
+        validate_bin_proc_macro(bin, warnings, errors)?;
 
         let path = target_path(bin, &inferred, "bin", package_root, edition, &mut |_| {
             if let Some(legacy_path) = legacy_bin_path(package_root, name_or_panic(bin), has_lib) {
@@ -309,8 +309,6 @@ fn to_bin_targets(
     bins: &[TomlBinTarget],
     package_root: &Path,
     edition: Edition,
-    warnings: &mut Vec<String>,
-    errors: &mut Vec<String>,
 ) -> CargoResult<Vec<Target>> {
     // This loop performs basic checks on each of the TomlTarget in `bins`.
     for bin in bins {
@@ -319,9 +317,6 @@ fn to_bin_targets(
         if bin.filename.is_some() {
             features.require(Feature::different_binary_name())?;
         }
-
-        validate_bin_crate_types(bin, warnings, errors)?;
-        validate_bin_proc_macro(bin, warnings, errors)?;
     }
 
     validate_unique_names(&bins, "binary")?;

From 72b170e7e1090bd63a97ac6fb4326f25270bd828 Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Mon, 29 Apr 2024 14:56:24 -0500
Subject: [PATCH 4/8] refactor(toml): Group related validation functions

---
 src/cargo/util/toml/targets.rs | 104 ++++++++++++++++-----------------
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs
index efa86ec04a7..9b30dd7fcaf 100644
--- a/src/cargo/util/toml/targets.rs
+++ b/src/cargo/util/toml/targets.rs
@@ -791,58 +791,6 @@ fn inferred_to_toml_targets(inferred: &[(String, PathBuf)]) -> Vec<TomlTarget> {
         .collect()
 }
 
-fn validate_lib_name(target: &TomlTarget, warnings: &mut Vec<String>) -> CargoResult<()> {
-    validate_target_name(target, "library", "lib", warnings)?;
-    let name = name_or_panic(target);
-    if name.contains('-') {
-        anyhow::bail!("library target names cannot contain hyphens: {}", name)
-    }
-
-    Ok(())
-}
-
-fn validate_bin_name(bin: &TomlTarget, warnings: &mut Vec<String>) -> CargoResult<()> {
-    validate_target_name(bin, "binary", "bin", warnings)?;
-    let name = name_or_panic(bin).to_owned();
-    if restricted_names::is_conflicting_artifact_name(&name) {
-        anyhow::bail!(
-            "the binary target name `{name}` is forbidden, \
-                 it conflicts with cargo's build directory names",
-        )
-    }
-
-    Ok(())
-}
-
-fn validate_target_name(
-    target: &TomlTarget,
-    target_kind_human: &str,
-    target_kind: &str,
-    warnings: &mut Vec<String>,
-) -> CargoResult<()> {
-    match target.name {
-        Some(ref name) => {
-            if name.trim().is_empty() {
-                anyhow::bail!("{} target names cannot be empty", target_kind_human)
-            }
-            if cfg!(windows) && restricted_names::is_windows_reserved(name) {
-                warnings.push(format!(
-                    "{} target `{}` is a reserved Windows filename, \
-                        this target will not work on Windows platforms",
-                    target_kind_human, name
-                ));
-            }
-        }
-        None => anyhow::bail!(
-            "{} target {}.name is required",
-            target_kind_human,
-            target_kind
-        ),
-    }
-
-    Ok(())
-}
-
 /// Will check a list of toml targets, and make sure the target names are unique within a vector.
 fn validate_unique_names(targets: &[TomlTarget], target_kind: &str) -> CargoResult<()> {
     let mut seen = HashSet::new();
@@ -1055,6 +1003,58 @@ fn name_or_panic(target: &TomlTarget) -> &str {
         .unwrap_or_else(|| panic!("target name is required"))
 }
 
+fn validate_lib_name(target: &TomlTarget, warnings: &mut Vec<String>) -> CargoResult<()> {
+    validate_target_name(target, "library", "lib", warnings)?;
+    let name = name_or_panic(target);
+    if name.contains('-') {
+        anyhow::bail!("library target names cannot contain hyphens: {}", name)
+    }
+
+    Ok(())
+}
+
+fn validate_bin_name(bin: &TomlTarget, warnings: &mut Vec<String>) -> CargoResult<()> {
+    validate_target_name(bin, "binary", "bin", warnings)?;
+    let name = name_or_panic(bin).to_owned();
+    if restricted_names::is_conflicting_artifact_name(&name) {
+        anyhow::bail!(
+            "the binary target name `{name}` is forbidden, \
+                 it conflicts with cargo's build directory names",
+        )
+    }
+
+    Ok(())
+}
+
+fn validate_target_name(
+    target: &TomlTarget,
+    target_kind_human: &str,
+    target_kind: &str,
+    warnings: &mut Vec<String>,
+) -> CargoResult<()> {
+    match target.name {
+        Some(ref name) => {
+            if name.trim().is_empty() {
+                anyhow::bail!("{} target names cannot be empty", target_kind_human)
+            }
+            if cfg!(windows) && restricted_names::is_windows_reserved(name) {
+                warnings.push(format!(
+                    "{} target `{}` is a reserved Windows filename, \
+                        this target will not work on Windows platforms",
+                    target_kind_human, name
+                ));
+            }
+        }
+        None => anyhow::bail!(
+            "{} target {}.name is required",
+            target_kind_human,
+            target_kind
+        ),
+    }
+
+    Ok(())
+}
+
 fn validate_bin_proc_macro(
     target: &TomlTarget,
     _warnings: &mut Vec<String>,

From d59e7a3443895d53ba369ff1ad55edd1475ac23c Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Wed, 1 May 2024 19:32:13 -0500
Subject: [PATCH 5/8] test(toml): Scope proc_macro2 tests to libs

---
 tests/testsuite/bad_config.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs
index 07ae1d76897..aaf5212fdef 100644
--- a/tests/testsuite/bad_config.rs
+++ b/tests/testsuite/bad_config.rs
@@ -1852,7 +1852,7 @@ Caused by:
 }
 
 #[cargo_test]
-fn proc_macro2() {
+fn lib_proc_macro2() {
     let foo = project()
         .file(
             "Cargo.toml",
@@ -1879,7 +1879,7 @@ fn proc_macro2() {
 }
 
 #[cargo_test(nightly, reason = "edition2024 is not stable")]
-fn proc_macro2_2024() {
+fn lib_proc_macro2_2024() {
     let foo = project()
         .file(
             "Cargo.toml",
@@ -1913,7 +1913,7 @@ Caused by:
 }
 
 #[cargo_test]
-fn proc_macro2_conflict() {
+fn lib_proc_macro2_conflict() {
     let foo = project()
         .file(
             "Cargo.toml",

From 2c31fe33e861bd10960d8a9dd0cc09918e32a844 Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Wed, 1 May 2024 19:35:53 -0500
Subject: [PATCH 6/8] test(toml): Show underscore behavior for bin targets

---
 tests/testsuite/bad_config.rs | 191 ++++++++++++++++++++++++++++++++++
 1 file changed, 191 insertions(+)

diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs
index aaf5212fdef..86f3f097fbb 100644
--- a/tests/testsuite/bad_config.rs
+++ b/tests/testsuite/bad_config.rs
@@ -1136,6 +1136,100 @@ fn lib_crate_type2_conflict() {
         .run();
 }
 
+#[cargo_test]
+fn bin_crate_type2() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [package]
+                name = "foo"
+                version = "0.5.0"
+                edition = "2015"
+                authors = ["wycats@example.com"]
+
+                [[bin]]
+                name = "foo"
+                path = "src/main.rs"
+                crate_type = []
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+    p.cargo("check")
+        .with_stderr(
+            "\
+[CHECKING] foo v0.5.0 ([CWD])
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+",
+        )
+        .run();
+}
+
+#[cargo_test(nightly, reason = "edition2024 is not stable")]
+fn bin_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"]
+
+                [[bin]]
+                name = "foo"
+                path = "src/main.rs"
+                crate_type = []
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+    p.cargo("check")
+        .masquerade_as_nightly_cargo(&["edition2024"])
+        .with_stderr(
+            "\
+[CHECKING] foo v0.5.0 ([CWD])
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+",
+        )
+        .run();
+}
+
+#[cargo_test]
+fn bin_crate_type2_conflict() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [package]
+                name = "foo"
+                version = "0.5.0"
+                edition = "2015"
+                authors = ["wycats@example.com"]
+
+                [[bin]]
+                name = "foo"
+                path = "src/main.rs"
+                crate_type = []
+                crate-type = []
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+    p.cargo("check")
+        .with_stderr(
+            "\
+[CHECKING] foo v0.5.0 ([CWD])
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+",
+        )
+        .run();
+}
+
 #[cargo_test]
 fn examples_crate_type2() {
     let p = project()
@@ -1939,6 +2033,103 @@ fn lib_proc_macro2_conflict() {
         .run();
 }
 
+#[cargo_test]
+fn bin_proc_macro2() {
+    let foo = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [package]
+                name = "foo"
+                version = "0.5.0"
+                edition = "2015"
+                authors = ["wycats@example.com"]
+
+                [[bin]]
+                name = "foo"
+                path = "src/main.rs"
+                proc_macro = false
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    foo.cargo("check")
+        .with_stderr(
+            "\
+[CHECKING] foo v0.5.0 ([CWD])
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+",
+        )
+        .run();
+}
+
+#[cargo_test(nightly, reason = "edition2024 is not stable")]
+fn bin_proc_macro2_2024() {
+    let foo = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                cargo-features = ["edition2024"]
+
+                [package]
+                name = "foo"
+                version = "0.5.0"
+                edition = "2015"
+                authors = ["wycats@example.com"]
+
+                [[bin]]
+                name = "foo"
+                path = "src/main.rs"
+                proc_macro = false
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    foo.cargo("check")
+        .masquerade_as_nightly_cargo(&["edition2024"])
+        .with_stderr(
+            "\
+[CHECKING] foo v0.5.0 ([CWD])
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+",
+        )
+        .run();
+}
+
+#[cargo_test]
+fn bin_proc_macro2_conflict() {
+    let foo = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [package]
+                name = "foo"
+                version = "0.5.0"
+                edition = "2015"
+                authors = ["wycats@example.com"]
+
+                [[bin]]
+                name = "foo"
+                path = "src/main.rs"
+                proc-macro = false
+                proc_macro = false
+            "#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    foo.cargo("check")
+        .with_stderr(
+            "\
+[CHECKING] foo v0.5.0 ([CWD])
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+",
+        )
+        .run();
+}
+
 #[cargo_test]
 fn invalid_toml_historically_allowed_fails() {
     let p = project()

From fe0819ee9e55d7042af3ac4afebe0e84991ebaa0 Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Mon, 29 Apr 2024 15:01:21 -0500
Subject: [PATCH 7/8] fix(toml): Validate crates_types/proc-macro for bin like
 others

Turns out, we allow these fields, just in limited ways, so we need to be
consistent.

I limited when this applies to reduce noise from the user solving there
problem because they are unlikely to keep the field and switch it to the
opposite value
---
 src/cargo/util/toml/targets.rs | 14 ++++++++++----
 tests/testsuite/bad_config.rs  | 24 +++++++++++++++++++-----
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs
index 9b30dd7fcaf..401761a8483 100644
--- a/src/cargo/util/toml/targets.rs
+++ b/src/cargo/util/toml/targets.rs
@@ -277,8 +277,8 @@ pub fn resolve_bins(
 
     for bin in &mut bins {
         validate_bin_name(bin, warnings)?;
-        validate_bin_crate_types(bin, warnings, errors)?;
-        validate_bin_proc_macro(bin, warnings, errors)?;
+        validate_bin_crate_types(bin, edition, warnings, errors)?;
+        validate_bin_proc_macro(bin, edition, warnings, errors)?;
 
         let path = target_path(bin, &inferred, "bin", package_root, edition, &mut |_| {
             if let Some(legacy_path) = legacy_bin_path(package_root, name_or_panic(bin), has_lib) {
@@ -1057,7 +1057,8 @@ fn validate_target_name(
 
 fn validate_bin_proc_macro(
     target: &TomlTarget,
-    _warnings: &mut Vec<String>,
+    edition: Edition,
+    warnings: &mut Vec<String>,
     errors: &mut Vec<String>,
 ) -> CargoResult<()> {
     if target.proc_macro() == Some(true) {
@@ -1067,6 +1068,8 @@ fn validate_bin_proc_macro(
                  set `true`",
             name
         ));
+    } else {
+        validate_proc_macro(target, "binary", edition, warnings)?;
     }
     Ok(())
 }
@@ -1090,7 +1093,8 @@ fn validate_proc_macro(
 
 fn validate_bin_crate_types(
     target: &TomlTarget,
-    _warnings: &mut Vec<String>,
+    edition: Edition,
+    warnings: &mut Vec<String>,
     errors: &mut Vec<String>,
 ) -> CargoResult<()> {
     if let Some(crate_types) = target.crate_types() {
@@ -1102,6 +1106,8 @@ fn validate_bin_crate_types(
                 name,
                 crate_types.join(", ")
             ));
+        } else {
+            validate_crate_types(target, "binary", edition, warnings)?;
         }
     }
     Ok(())
diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs
index 86f3f097fbb..3ed3cce127e 100644
--- a/tests/testsuite/bad_config.rs
+++ b/tests/testsuite/bad_config.rs
@@ -1159,6 +1159,8 @@ fn bin_crate_type2() {
     p.cargo("check")
         .with_stderr(
             "\
+[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition
+(in the `foo` binary target)
 [CHECKING] foo v0.5.0 ([CWD])
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
 ",
@@ -1190,10 +1192,14 @@ fn bin_crate_type2_2024() {
         .build();
     p.cargo("check")
         .masquerade_as_nightly_cargo(&["edition2024"])
+        .with_status(101)
         .with_stderr(
             "\
-[CHECKING] foo v0.5.0 ([CWD])
-[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+[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` binary target)
 ",
         )
         .run();
@@ -1223,6 +1229,7 @@ fn bin_crate_type2_conflict() {
     p.cargo("check")
         .with_stderr(
             "\
+[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `foo` binary target
 [CHECKING] foo v0.5.0 ([CWD])
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
 ",
@@ -2057,6 +2064,8 @@ fn bin_proc_macro2() {
     foo.cargo("check")
         .with_stderr(
             "\
+[WARNING] `proc_macro` is deprecated in favor of `proc-macro` and will not work in the 2024 edition
+(in the `foo` binary target)
 [CHECKING] foo v0.5.0 ([CWD])
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
 ",
@@ -2075,7 +2084,7 @@ fn bin_proc_macro2_2024() {
                 [package]
                 name = "foo"
                 version = "0.5.0"
-                edition = "2015"
+                edition = "2024"
                 authors = ["wycats@example.com"]
 
                 [[bin]]
@@ -2089,10 +2098,14 @@ fn bin_proc_macro2_2024() {
 
     foo.cargo("check")
         .masquerade_as_nightly_cargo(&["edition2024"])
+        .with_status(101)
         .with_stderr(
             "\
-[CHECKING] foo v0.5.0 ([CWD])
-[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
+[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` binary target)
 ",
         )
         .run();
@@ -2123,6 +2136,7 @@ fn bin_proc_macro2_conflict() {
     foo.cargo("check")
         .with_stderr(
             "\
+[WARNING] `proc_macro` is redundant with `proc-macro`, preferring `proc-macro` in the `foo` binary target
 [CHECKING] foo v0.5.0 ([CWD])
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s
 ",

From cdae596394b8c2faf84a1fc151d7d92a9c121c6c Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
Date: Mon, 29 Apr 2024 15:25:06 -0500
Subject: [PATCH 8/8] refactor(toml): Consistently document motivation for
 validation order

---
 src/cargo/util/toml/targets.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs
index 401761a8483..9d7a26dcc7b 100644
--- a/src/cargo/util/toml/targets.rs
+++ b/src/cargo/util/toml/targets.rs
@@ -141,10 +141,10 @@ pub fn resolve_lib(
     let Some(mut lib) = lib else { return Ok(None) };
     lib.name
         .get_or_insert_with(|| package_name.replace("-", "_"));
+
     // Check early to improve error messages
     validate_lib_name(&lib, warnings)?;
 
-    // Checking the original lib
     validate_proc_macro(&lib, "library", edition, warnings)?;
     validate_crate_types(&lib, "library", edition, warnings)?;
 
@@ -276,7 +276,9 @@ pub fn resolve_bins(
     );
 
     for bin in &mut bins {
+        // Check early to improve error messages
         validate_bin_name(bin, warnings)?;
+
         validate_bin_crate_types(bin, edition, warnings, errors)?;
         validate_bin_proc_macro(bin, edition, warnings, errors)?;
 
@@ -587,7 +589,9 @@ fn resolve_targets_with_legacy_path(
     );
 
     for target in &toml_targets {
+        // Check early to improve error messages
         validate_target_name(target, target_kind_human, target_kind, warnings)?;
+
         validate_proc_macro(target, target_kind_human, edition, warnings)?;
         validate_crate_types(target, target_kind_human, edition, warnings)?;
     }