about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/src/bin/rustc.rs5
-rw-r--r--src/bootstrap/src/utils/proc_macro_deps.rs71
-rw-r--r--src/tools/tidy/Cargo.toml2
-rw-r--r--src/tools/tidy/src/deps.rs75
-rw-r--r--src/tools/tidy/src/main.rs2
5 files changed, 150 insertions, 5 deletions
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 88595ff7e51..61045067592 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -28,6 +28,9 @@ use shared_helpers::{
 #[path = "../utils/shared_helpers.rs"]
 mod shared_helpers;
 
+#[path = "../utils/proc_macro_deps.rs"]
+mod proc_macro_deps;
+
 fn main() {
     let orig_args = env::args_os().skip(1).collect::<Vec<_>>();
     let mut args = orig_args.clone();
@@ -167,7 +170,7 @@ fn main() {
         // issue https://github.com/rust-lang/rust/issues/100530
         if env::var("RUSTC_TLS_MODEL_INITIAL_EXEC").is_ok()
             && crate_type != Some("proc-macro")
-            && !matches!(crate_name, Some("proc_macro2" | "quote" | "syn" | "synstructure"))
+            && proc_macro_deps::CRATES.binary_search(&crate_name.unwrap_or_default()).is_err()
         {
             cmd.arg("-Ztls-model=initial-exec");
         }
diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs
new file mode 100644
index 00000000000..dbfd6f47dc6
--- /dev/null
+++ b/src/bootstrap/src/utils/proc_macro_deps.rs
@@ -0,0 +1,71 @@
+/// Do not update manually - use `./x.py test tidy --bless`
+/// Holds all direct and indirect dependencies of proc-macro crates in tree.
+/// See <https://github.com/rust-lang/rust/issues/134863>
+pub static CRATES: &[&str] = &[
+    // tidy-alphabetical-start
+    "annotate-snippets",
+    "anstyle",
+    "basic-toml",
+    "block-buffer",
+    "bumpalo",
+    "cfg-if",
+    "cpufeatures",
+    "crypto-common",
+    "darling",
+    "darling_core",
+    "derive_builder_core",
+    "digest",
+    "fluent-bundle",
+    "fluent-langneg",
+    "fluent-syntax",
+    "fnv",
+    "generic-array",
+    "heck",
+    "ident_case",
+    "intl-memoizer",
+    "intl_pluralrules",
+    "libc",
+    "log",
+    "memchr",
+    "mime",
+    "mime_guess",
+    "minimal-lexical",
+    "nom",
+    "num-conv",
+    "once_cell",
+    "pest",
+    "pest_generator",
+    "pest_meta",
+    "proc-macro2",
+    "quote",
+    "rinja_parser",
+    "rustc-hash",
+    "self_cell",
+    "serde",
+    "sha2",
+    "smallvec",
+    "stable_deref_trait",
+    "strsim",
+    "syn",
+    "synstructure",
+    "thiserror",
+    "time-core",
+    "tinystr",
+    "type-map",
+    "typenum",
+    "ucd-trie",
+    "unic-langid",
+    "unic-langid-impl",
+    "unic-langid-macros",
+    "unicase",
+    "unicode-ident",
+    "unicode-width",
+    "version_check",
+    "wasm-bindgen-backend",
+    "wasm-bindgen-macro-support",
+    "wasm-bindgen-shared",
+    "yoke",
+    "zerofrom",
+    "zerovec",
+    // tidy-alphabetical-end
+];
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index bc75787fb1a..2f424a482b5 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -6,7 +6,7 @@ autobins = false
 
 [dependencies]
 build_helper = { path = "../../build_helper" }
-cargo_metadata = "0.18"
+cargo_metadata = "0.19"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }
 walkdir = "2"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index beeb33b46ff..1794d0fbca7 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,12 +1,16 @@
 //! Checks the licenses of third-party dependencies.
 
 use std::collections::HashSet;
-use std::fs::read_dir;
+use std::fs::{File, read_dir};
+use std::io::Write;
 use std::path::Path;
 
 use build_helper::ci::CiEnv;
 use cargo_metadata::{Metadata, Package, PackageId};
 
+#[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
+mod proc_macro_deps;
+
 /// These are licenses that are allowed for all crates, including the runtime,
 /// rustc, tools, etc.
 #[rustfmt::skip]
@@ -564,9 +568,11 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
 ///
 /// `root` is path to the directory with the root `Cargo.toml` (for the workspace). `cargo` is path
 /// to the cargo executable.
-pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
+pub fn check(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
     let mut checked_runtime_licenses = false;
 
+    check_proc_macro_dep_list(root, cargo, bless, bad);
+
     for &(workspace, exceptions, permitted_deps, submodules) in WORKSPACES {
         if has_missing_submodule(root, submodules) {
             continue;
@@ -600,6 +606,71 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
     assert!(checked_runtime_licenses);
 }
 
+/// Ensure the list of proc-macro crate transitive dependencies is up to date
+fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
+    let mut cmd = cargo_metadata::MetadataCommand::new();
+    cmd.cargo_path(cargo)
+        .manifest_path(root.join("Cargo.toml"))
+        .features(cargo_metadata::CargoOpt::AllFeatures)
+        .other_options(vec!["--locked".to_owned()]);
+    let metadata = t!(cmd.exec());
+    let is_proc_macro_pkg = |pkg: &Package| pkg.targets.iter().any(|target| target.is_proc_macro());
+
+    let mut proc_macro_deps = HashSet::new();
+    for pkg in metadata.packages.iter().filter(|pkg| is_proc_macro_pkg(*pkg)) {
+        deps_of(&metadata, &pkg.id, &mut proc_macro_deps);
+    }
+    // Remove the proc-macro crates themselves
+    proc_macro_deps.retain(|pkg| !is_proc_macro_pkg(&metadata[pkg]));
+    let proc_macro_deps_iter = proc_macro_deps.into_iter().map(|dep| metadata[dep].name.clone());
+
+    if bless {
+        let mut proc_macro_deps: Vec<_> = proc_macro_deps_iter.collect();
+        proc_macro_deps.sort();
+        proc_macro_deps.dedup();
+        let mut file = File::create(root.join("src/bootstrap/src/utils/proc_macro_deps.rs"))
+            .expect("`proc_macro_deps` should exist");
+        writeln!(
+            &mut file,
+            "/// Do not update manually - use `./x.py test tidy --bless`
+/// Holds all direct and indirect dependencies of proc-macro crates in tree.
+/// See <https://github.com/rust-lang/rust/issues/134863>
+pub static CRATES: &[&str] = &[
+    // tidy-alphabetical-start"
+        )
+        .unwrap();
+        for dep in proc_macro_deps {
+            writeln!(&mut file, "    {dep:?},").unwrap();
+        }
+        writeln!(
+            &mut file,
+            "    // tidy-alphabetical-end
+];"
+        )
+        .unwrap();
+    } else {
+        let proc_macro_deps: HashSet<_> = proc_macro_deps_iter.collect();
+        let expected =
+            proc_macro_deps::CRATES.iter().map(|s| s.to_string()).collect::<HashSet<_>>();
+        let old_bad = *bad;
+        for missing in proc_macro_deps.difference(&expected) {
+            tidy_error!(
+                bad,
+                "proc-macro crate dependency `{missing}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`",
+            );
+        }
+        for extra in expected.difference(&proc_macro_deps) {
+            tidy_error!(
+                bad,
+                "`{extra}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
+            );
+        }
+        if *bad != old_bad {
+            eprintln!("Run `./x.py test tidy --bless` to regenerate the list");
+        }
+    }
+}
+
 /// Used to skip a check if a submodule is not checked out, and not in a CI environment.
 ///
 /// This helps prevent enforcing developers to fetch submodules for tidy.
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 40608952c0b..13a558fea48 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -95,7 +95,7 @@ fn main() {
         check!(target_specific_tests, &tests_path);
 
         // Checks that are done on the cargo workspace.
-        check!(deps, &root_path, &cargo);
+        check!(deps, &root_path, &cargo, bless);
         check!(extdeps, &root_path);
 
         // Checks over tests.