Remove uses of `DepInfo.transitive_libs` (#1054)

This is a step further towards https://github.com/bazelbuild/rules_rust/issues/1051.

With this change, `rules_rust` doesn't need `DepInfo.transitive_libs` anymore. The only place where this field was used was to pass the files it contains as inputs to rust compile actions. We use `DepInfo.transitive_crate_outputs` for that now. For non-rlib compile actions, which need non-crate inputs as well, we add those inputs to the `additional_transitive_inputs` variable.
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index 0c141a3..89aa097 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -179,11 +179,9 @@
             transitive_build_infos.append(dep_info.transitive_build_infos)
         elif cc_info:
             # This dependency is a cc_library
-
-            # TODO: We could let the user choose how to link, instead of always preferring to link static libraries.
-            linker_inputs = cc_info.linking_context.linker_inputs.to_list()
-            libs = [get_preferred_artifact(lib) for li in linker_inputs for lib in li.libraries]
-            transitive_noncrate_libs.append(depset(libs))
+            transitive_noncrate_libs.append(depset(
+                _collect_libs_from_linker_inputs(cc_info.linking_context.linker_inputs.to_list()),
+            ))
             transitive_noncrates.append(cc_info.linking_context.linker_inputs)
         elif dep_build_info:
             if build_info:
@@ -218,6 +216,14 @@
         depset(transitive = linkstamps),
     )
 
+def _collect_libs_from_linker_inputs(linker_inputs):
+    # TODO: We could let the user choose how to link, instead of always preferring to link static libraries.
+    return [
+        get_preferred_artifact(lib)
+        for li in linker_inputs
+        for lib in li.libraries
+    ]
+
 def _get_crate_and_dep_info(dep):
     if type(dep) == "Target" and rust_common.crate_info in dep:
         return (dep[rust_common.crate_info], dep[rust_common.dep_info])
@@ -369,15 +375,19 @@
 
     linker_depset = cc_toolchain.all_files
 
-    # Pass linker additional inputs (e.g., linker scripts) only for linking-like
-    # actions, not for example where the output is rlib. This avoids quadratic
-    # behavior where transitive noncrates are flattened on each transitive
-    # rust_library dependency.
+    # Pass linker inputs only for linking-like actions, not for example where
+    # the output is rlib. This avoids quadratic behavior where transitive noncrates are
+    # flattened on each transitive rust_library dependency.
     additional_transitive_inputs = []
-    if crate_info.type in ("bin", "dylib", "cdylib"):
-        additional_transitive_inputs = [
+    if crate_info.type in ("staticlib", "proc-macro"):
+        additional_transitive_inputs = _collect_libs_from_linker_inputs(
+            dep_info.transitive_noncrates.to_list(),
+        )
+    elif crate_info.type in ("bin", "dylib", "cdylib"):
+        linker_inputs = dep_info.transitive_noncrates.to_list()
+        additional_transitive_inputs = _collect_libs_from_linker_inputs(linker_inputs) + [
             additional_input
-            for linker_input in dep_info.transitive_noncrates.to_list()
+            for linker_input in linker_inputs
             for additional_input in linker_input.additional_inputs
         ]
 
@@ -398,7 +408,7 @@
             toolchain.rust_lib.files,
             linker_depset,
             crate_info.srcs,
-            dep_info.transitive_libs,
+            dep_info.transitive_crate_outputs,
             depset(additional_transitive_inputs),
             crate_info.compile_data,
         ],
diff --git a/test/unit/native_deps/BUILD.bazel b/test/unit/native_deps/BUILD.bazel
index 7864dfb..cfb6557 100644
--- a/test/unit/native_deps/BUILD.bazel
+++ b/test/unit/native_deps/BUILD.bazel
@@ -1,4 +1,7 @@
+load(":native_action_inputs_test.bzl", "native_action_inputs_test_suite")
 load(":native_deps_test.bzl", "native_deps_test_suite")
 
 ############################ UNIT TESTS #############################
 native_deps_test_suite(name = "native_deps_test_suite")
+
+native_action_inputs_test_suite(name = "native_action_inputs_test_suite")
diff --git a/test/unit/native_deps/bar.cc b/test/unit/native_deps/bar.cc
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/unit/native_deps/bar.cc
@@ -0,0 +1 @@
+
diff --git a/test/unit/native_deps/foo.rs b/test/unit/native_deps/foo.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/unit/native_deps/foo.rs
@@ -0,0 +1 @@
+
diff --git a/test/unit/native_deps/foo_main.rs b/test/unit/native_deps/foo_main.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/test/unit/native_deps/foo_main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/test/unit/native_deps/native_action_inputs_test.bzl b/test/unit/native_deps/native_action_inputs_test.bzl
new file mode 100644
index 0000000..2363e1e
--- /dev/null
+++ b/test/unit/native_deps/native_action_inputs_test.bzl
@@ -0,0 +1,155 @@
+"""Unittests for rust rules."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(
+    "//rust:defs.bzl",
+    "rust_binary",
+    "rust_library",
+    "rust_proc_macro",
+    "rust_shared_library",
+    "rust_static_library",
+)
+load("//test/unit:common.bzl", "assert_action_mnemonic")
+
+def _native_action_inputs_present_test_impl(ctx):
+    env = analysistest.begin(ctx)
+    tut = analysistest.target_under_test(env)
+    action = tut.actions[0]
+    assert_action_mnemonic(env, action, "Rustc")
+    inputs = action.inputs.to_list()
+    lib_name = _native_dep_lib_name(ctx)
+
+    asserts.true(
+        env,
+        _has_action_input(lib_name, inputs),
+        "Expected to contain {lib_name} as action input, got {inputs}".format(
+            lib_name = lib_name,
+            inputs = inputs,
+        ),
+    )
+
+    return analysistest.end(env)
+
+def _native_action_inputs_not_present_test_impl(ctx):
+    env = analysistest.begin(ctx)
+    tut = analysistest.target_under_test(env)
+    action = tut.actions[0]
+    assert_action_mnemonic(env, action, "Rustc")
+    inputs = action.inputs.to_list()
+    lib_name = _native_dep_lib_name(ctx)
+
+    asserts.false(
+        env,
+        _has_action_input(lib_name, inputs),
+        "Expected not to contain {lib_name}".format(lib_name = lib_name),
+    )
+
+    return analysistest.end(env)
+
+def _native_dep_lib_name(ctx):
+    if ctx.target_platform_has_constraint(
+        ctx.attr._windows_constraint[platform_common.ConstraintValueInfo],
+    ):
+        return "bar.lib"
+    else:
+        return "libbar.a"
+
+def _has_action_input(name, inputs):
+    for file in inputs:
+        if file.basename == name:
+            return True
+    return False
+
+native_action_inputs_present_test = analysistest.make(
+    _native_action_inputs_present_test_impl,
+    attrs = {
+        "_windows_constraint": attr.label(default = Label("@platforms//os:windows")),
+    },
+)
+native_action_inputs_not_present_test = analysistest.make(
+    _native_action_inputs_not_present_test_impl,
+    attrs = {
+        "_windows_constraint": attr.label(default = Label("@platforms//os:windows")),
+    },
+)
+
+def _native_action_inputs_test():
+    rust_library(
+        name = "foo_lib",
+        srcs = ["foo.rs"],
+        deps = [":bar"],
+    )
+
+    rust_binary(
+        name = "foo_bin",
+        srcs = ["foo_main.rs"],
+        deps = [":bar"],
+    )
+
+    rust_shared_library(
+        name = "foo_dylib",
+        srcs = ["foo.rs"],
+        deps = [":bar"],
+    )
+
+    rust_static_library(
+        name = "foo_static",
+        srcs = ["foo.rs"],
+        deps = [":bar"],
+    )
+
+    rust_proc_macro(
+        name = "foo_proc_macro",
+        srcs = ["foo.rs"],
+        deps = [":bar"],
+    )
+
+    # buildifier: disable=native-cc
+    native.cc_library(
+        name = "bar",
+        srcs = ["bar.cc"],
+    )
+
+    native_action_inputs_not_present_test(
+        name = "native_action_inputs_lib_test",
+        target_under_test = ":foo_lib",
+    )
+
+    native_action_inputs_present_test(
+        name = "native_action_inputs_bin_test",
+        target_under_test = ":foo_bin",
+    )
+
+    native_action_inputs_present_test(
+        name = "native_action_inputs_dylib_test",
+        target_under_test = ":foo_dylib",
+    )
+
+    native_action_inputs_present_test(
+        name = "native_action_inputs_static_test",
+        target_under_test = ":foo_static",
+    )
+
+    native_action_inputs_present_test(
+        name = "native_action_inputs_proc_macro_test",
+        target_under_test = ":foo_proc_macro",
+    )
+
+def native_action_inputs_test_suite(name):
+    """Entry-point macro called from the BUILD file.
+
+    Args:
+        name: Name of the macro.
+    """
+    _native_action_inputs_test()
+
+    native.test_suite(
+        name = name,
+        tests = [
+            ":native_action_inputs_lib_test",
+            ":native_action_inputs_bin_test",
+            ":native_action_inputs_dylib_test",
+            ":native_action_inputs_static_test",
+            ":native_action_inputs_proc_macro_test",
+        ],
+    )