Don't leak native dependencies of proc_macro (#1359)

Native dependencies of a `rust_proc_macro` shouldn't propagate to the libraries depending on the `rust_proc_macro` target.
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index 5a9d569..ac62460 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -191,7 +191,9 @@
                     ] else [dep_info.transitive_crate_outputs],
                 ),
             )
-            transitive_noncrates.append(dep_info.transitive_noncrates)
+
+            if "proc-macro" not in [crate_info.type, crate_info.wrapped_crate_type]:
+                transitive_noncrates.append(dep_info.transitive_noncrates)
             transitive_build_infos.append(dep_info.transitive_build_infos)
             transitive_link_search_paths.append(dep_info.link_search_path_files)
 
diff --git a/test/unit/proc_macro/leaks_deps/native/BUILD.bazel b/test/unit/proc_macro/leaks_deps/native/BUILD.bazel
new file mode 100644
index 0000000..988cfa3
--- /dev/null
+++ b/test/unit/proc_macro/leaks_deps/native/BUILD.bazel
@@ -0,0 +1,8 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
+package(default_visibility = ["//test:__subpackages__"])
+
+cc_library(
+    name = "native",
+    srcs = ["native.cc"],
+)
diff --git a/test/unit/proc_macro/leaks_deps/native/native.cc b/test/unit/proc_macro/leaks_deps/native/native.cc
new file mode 100644
index 0000000..7c6f54d
--- /dev/null
+++ b/test/unit/proc_macro/leaks_deps/native/native.cc
@@ -0,0 +1,7 @@
+#include <stdint.h>
+
+extern "C" {
+    int32_t forty_two_from_cc() {
+        return 42;
+    }
+}
diff --git a/test/unit/proc_macro/leaks_deps/proc_macro_definition_with_native_dependency.rs b/test/unit/proc_macro/leaks_deps/proc_macro_definition_with_native_dependency.rs
new file mode 100644
index 0000000..a4e368e
--- /dev/null
+++ b/test/unit/proc_macro/leaks_deps/proc_macro_definition_with_native_dependency.rs
@@ -0,0 +1,7 @@
+use proc_macro::TokenStream;
+use proc_macro_dep_with_native_dep::forty_two;
+
+#[proc_macro]
+pub fn make_forty_two_from_native_dep(_item: TokenStream) -> TokenStream {
+    forty_two().to_string().parse().unwrap()
+}
diff --git a/test/unit/proc_macro/leaks_deps/proc_macro_dep/BUILD.bazel b/test/unit/proc_macro/leaks_deps/proc_macro_dep/BUILD.bazel
index e7a4e7d..8bee950 100644
--- a/test/unit/proc_macro/leaks_deps/proc_macro_dep/BUILD.bazel
+++ b/test/unit/proc_macro/leaks_deps/proc_macro_dep/BUILD.bazel
@@ -1,8 +1,16 @@
 load("//rust:defs.bzl", "rust_library")
 
+package(default_visibility = ["//test:__subpackages__"])
+
 rust_library(
     name = "proc_macro_dep",
     srcs = ["proc_macro_dep.rs"],
     edition = "2018",
-    visibility = ["//test:__subpackages__"],
+)
+
+rust_library(
+    name = "proc_macro_dep_with_native_dep",
+    srcs = ["proc_macro_dep_with_native_dep.rs"],
+    edition = "2018",
+    deps = ["//test/unit/proc_macro/leaks_deps/native"],
 )
diff --git a/test/unit/proc_macro/leaks_deps/proc_macro_dep/proc_macro_dep_with_native_dep.rs b/test/unit/proc_macro/leaks_deps/proc_macro_dep/proc_macro_dep_with_native_dep.rs
new file mode 100644
index 0000000..dd925eb
--- /dev/null
+++ b/test/unit/proc_macro/leaks_deps/proc_macro_dep/proc_macro_dep_with_native_dep.rs
@@ -0,0 +1,7 @@
+extern "C" {
+    pub fn forty_two_from_cc() -> i32;
+}
+
+pub fn forty_two() -> i32 {
+    unsafe { forty_two_from_cc() }
+}
diff --git a/test/unit/proc_macro/leaks_deps/proc_macro_does_not_leak_deps.bzl b/test/unit/proc_macro/leaks_deps/proc_macro_does_not_leak_deps.bzl
index 4666c6f..40c2e48 100644
--- a/test/unit/proc_macro/leaks_deps/proc_macro_does_not_leak_deps.bzl
+++ b/test/unit/proc_macro/leaks_deps/proc_macro_does_not_leak_deps.bzl
@@ -2,25 +2,32 @@
 
 load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
 load("//rust:defs.bzl", "rust_proc_macro", "rust_test")
-load(
-    "//test/unit:common.bzl",
-    "assert_action_mnemonic",
-)
 
 def _proc_macro_does_not_leak_deps_impl(ctx):
     env = analysistest.begin(ctx)
     actions = analysistest.target_under_test(env).actions
-    action = actions[0]
-    assert_action_mnemonic(env, action, "Rustc")
+    rustc_action = None
+    for action in actions:
+        if action.mnemonic == "Rustc":
+            rustc_action = action
+            break
+
+    asserts.false(env, rustc_action == None)
 
     # Our test target has a dependency on "proc_macro_dep" via a rust_proc_macro target,
     # so the proc_macro_dep rlib should not appear as an input to the Rustc action, nor as -Ldependency on the command line.
-    proc_macro_dep_inputs = [i for i in action.inputs.to_list() if "proc_macro_dep" in i.path]
-    proc_macro_dep_args = [arg for arg in action.argv if "proc_macro_dep" in arg]
+    proc_macro_dep_inputs = [i for i in rustc_action.inputs.to_list() if "proc_macro_dep" in i.path]
+    proc_macro_dep_args = [arg for arg in rustc_action.argv if "proc_macro_dep" in arg]
 
     asserts.equals(env, 0, len(proc_macro_dep_inputs))
     asserts.equals(env, 0, len(proc_macro_dep_args))
 
+    # Our test target depends on proc_macro_dep:native directly, as well as transitively through the
+    # proc_macro. The proc_macro should not leak its dependency, so we should only get the "native"
+    # library once on the command line.
+    native_deps = [arg for arg in rustc_action.argv if arg.startswith("-Clink-arg=-lnative")]
+    asserts.equals(env, 1, len(native_deps))
+
     return analysistest.end(env)
 
 proc_macro_does_not_leak_deps_test = analysistest.make(_proc_macro_does_not_leak_deps_impl)
@@ -33,11 +40,27 @@
         deps = ["//test/unit/proc_macro/leaks_deps/proc_macro_dep"],
     )
 
+    rust_proc_macro(
+        name = "proc_macro_with_native_dep",
+        srcs = ["leaks_deps/proc_macro_definition_with_native_dependency.rs"],
+        edition = "2018",
+        deps = [
+            "//test/unit/proc_macro/leaks_deps/proc_macro_dep:proc_macro_dep_with_native_dep",
+            "//test/unit/proc_macro/leaks_deps/native",
+        ],
+    )
+
     rust_test(
         name = "deps_not_leaked",
         srcs = ["leaks_deps/proc_macro_user.rs"],
         edition = "2018",
-        proc_macro_deps = [":proc_macro_definition"],
+        deps = [
+            "//test/unit/proc_macro/leaks_deps/native",
+        ],
+        proc_macro_deps = [
+            ":proc_macro_definition",
+            ":proc_macro_with_native_dep",
+        ],
     )
 
     proc_macro_does_not_leak_deps_test(
diff --git a/test/unit/proc_macro/leaks_deps/proc_macro_user.rs b/test/unit/proc_macro/leaks_deps/proc_macro_user.rs
index 0be3419..c038dd5 100644
--- a/test/unit/proc_macro/leaks_deps/proc_macro_user.rs
+++ b/test/unit/proc_macro/leaks_deps/proc_macro_user.rs
@@ -1,6 +1,17 @@
 use proc_macro_definition::make_forty_two;
+use proc_macro_with_native_dep::make_forty_two_from_native_dep;
 
-#[test]
-fn test_answer_macro() {
-    assert_eq!(make_forty_two!(), 42);
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_forty_two() {
+        assert_eq!(make_forty_two!(), 42);
+    }
+
+    #[test]
+    fn test_forty_two_from_native_dep() {
+        assert_eq!(make_forty_two_from_native_dep!(), 42);
+    }
 }