Inform users that `crate` and `srcs` are mutually exclusive (#1650)

This should avoid confusion in cases where users have defined tests with
both `rust_test.crate` and `rust_test.srcs` set and later find
`rust_test.srcs` are actually unused and not being tested.

relates to https://github.com/bazelbuild/rules_rust/issues/2324
diff --git a/examples/crate_universe/no_cargo_manifests/BUILD.bazel b/examples/crate_universe/no_cargo_manifests/BUILD.bazel
index 2691eb2..3dc2664 100644
--- a/examples/crate_universe/no_cargo_manifests/BUILD.bazel
+++ b/examples/crate_universe/no_cargo_manifests/BUILD.bazel
@@ -19,7 +19,6 @@
 
 rust_test(
     name = "unit_test",
-    srcs = glob(["**/*.rs"]),
     crate = ":no_cargo_manifests",
     edition = "2018",
 )
diff --git a/examples/crate_universe/vendor_local_pkgs/BUILD.bazel b/examples/crate_universe/vendor_local_pkgs/BUILD.bazel
index 195809b..a4b3947 100644
--- a/examples/crate_universe/vendor_local_pkgs/BUILD.bazel
+++ b/examples/crate_universe/vendor_local_pkgs/BUILD.bazel
@@ -69,7 +69,6 @@
 
 rust_test(
     name = "unit_test",
-    srcs = glob(["**/*.rs"]),
     crate = ":vendor_local",
     edition = "2018",
 )
diff --git a/examples/crate_universe/vendor_remote_pkgs/BUILD.bazel b/examples/crate_universe/vendor_remote_pkgs/BUILD.bazel
index 63d12f4..d5b4e17 100644
--- a/examples/crate_universe/vendor_remote_pkgs/BUILD.bazel
+++ b/examples/crate_universe/vendor_remote_pkgs/BUILD.bazel
@@ -75,7 +75,6 @@
 
 rust_test(
     name = "unit_test",
-    srcs = glob(["**/*.rs"]),
     crate = ":vendor_remote",
     edition = "2018",
 )
diff --git a/examples/crate_universe_unnamed/vendor_remote_pkgs/BUILD.bazel b/examples/crate_universe_unnamed/vendor_remote_pkgs/BUILD.bazel
index 747d334..271bbd8 100644
--- a/examples/crate_universe_unnamed/vendor_remote_pkgs/BUILD.bazel
+++ b/examples/crate_universe_unnamed/vendor_remote_pkgs/BUILD.bazel
@@ -70,7 +70,6 @@
 
 rust_test(
     name = "unit_test",
-    srcs = glob(["**/*.rs"]),
     crate = ":vendor_remote",
     edition = "2018",
 )
diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl
index 4147bf5..724e044 100644
--- a/rust/private/rust.bzl
+++ b/rust/private/rust.bzl
@@ -283,6 +283,12 @@
     deps = transform_deps(ctx.attr.deps)
     proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx))
 
+    if toolchain._incompatible_test_attr_crate_and_srcs_mutually_exclusive:
+        if ctx.attr.crate and ctx.attr.srcs:
+            fail("rust_test.crate and rust_test.srcs are mutually exclusive. Update {} to use only one of these attributes".format(
+                ctx.label,
+            ))
+
     if ctx.attr.crate:
         # Target is building the crate in `test` config
         crate = ctx.attr.crate[rust_common.crate_info] if rust_common.crate_info in ctx.attr.crate else ctx.attr.crate[rust_common.test_crate_info].crate
diff --git a/rust/settings/BUILD.bazel b/rust/settings/BUILD.bazel
index 40b7d31..f1ba202 100644
--- a/rust/settings/BUILD.bazel
+++ b/rust/settings/BUILD.bazel
@@ -4,6 +4,11 @@
 
 package(default_visibility = ["//visibility:public"])
 
+bzl_library(
+    name = "bzl_lib",
+    srcs = glob(["**/*.bzl"]),
+)
+
 # A flag controlling whether to rename first-party crates such that their names
 # encode the Bazel package and target name, instead of just the target name.
 #
@@ -60,14 +65,16 @@
     build_setting_default = False,
 )
 
-bzl_library(
-    name = "bzl_lib",
-    srcs = glob(["**/*.bzl"]),
-)
-
 # A flag to set rustc --sysroot flag to the sysroot generated by rust_toolchain
 incompatible_flag(
     name = "experimental_toolchain_generated_sysroot",
     build_setting_default = True,
     issue = "https://github.com/bazelbuild/rules_rust/issues/2039",
 )
+
+# A flag to make `rust_test.crate` and `rust_test.srcs` mutually exclusive.
+incompatible_flag(
+    name = "incompatible_test_attr_crate_and_srcs_mutually_exclusive",
+    build_setting_default = True,
+    issue = "https://github.com/bazelbuild/rules_rust/issues/2324",
+)
diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl
index 66f6b0e..f2cf3c7 100644
--- a/rust/toolchain.bzl
+++ b/rust/toolchain.bzl
@@ -643,6 +643,7 @@
         _experimental_use_global_allocator = experimental_use_global_allocator,
         _experimental_use_coverage_metadata_files = ctx.attr._experimental_use_coverage_metadata_files[BuildSettingInfo].value,
         _experimental_toolchain_generated_sysroot = ctx.attr._experimental_toolchain_generated_sysroot[IncompatibleFlagInfo].enabled,
+        _incompatible_test_attr_crate_and_srcs_mutually_exclusive = ctx.attr._incompatible_test_attr_crate_and_srcs_mutually_exclusive[IncompatibleFlagInfo].enabled,
         _no_std = no_std,
     )
     return [
@@ -806,6 +807,9 @@
                 "This flag is only relevant when used together with --@rules_rust//rust/settings:experimental_use_global_allocator."
             ),
         ),
+        "_incompatible_test_attr_crate_and_srcs_mutually_exclusive": attr.label(
+            default = Label("//rust/settings:incompatible_test_attr_crate_and_srcs_mutually_exclusive"),
+        ),
         "_no_std": attr.label(
             default = Label("//:no_std"),
         ),
diff --git a/test/inline_test_with_deps/test_with_srcs/BUILD.bazel b/test/inline_test_with_deps/test_with_srcs/BUILD.bazel
deleted file mode 100644
index 64d628e..0000000
--- a/test/inline_test_with_deps/test_with_srcs/BUILD.bazel
+++ /dev/null
@@ -1,20 +0,0 @@
-load("//rust:defs.bzl", "rust_library", "rust_test")
-
-package(default_visibility = ["//visibility:public"])
-
-rust_library(
-    name = "inline",
-    srcs = ["src/lib.rs"],
-    edition = "2018",
-    # Not all source files are included in this this target (`extra.rs`)
-    # and as a result, rustfmt complains about a missing module. Do not
-    # run rustfmt to avoid this issue.
-    tags = ["norustfmt"],
-)
-
-rust_test(
-    name = "inline_test",
-    srcs = ["src/extra.rs"],
-    crate = ":inline",
-    deps = ["//test/inline_test_with_deps/dep"],
-)
diff --git a/test/inline_test_with_deps/test_with_srcs/src/extra.rs b/test/inline_test_with_deps/test_with_srcs/src/extra.rs
deleted file mode 100644
index b72dd58..0000000
--- a/test/inline_test_with_deps/test_with_srcs/src/extra.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[cfg(test)]
-pub(crate) fn extra_test_fn() -> u32 {
-    100
-}
diff --git a/test/inline_test_with_deps/test_with_srcs/src/lib.rs b/test/inline_test_with_deps/test_with_srcs/src/lib.rs
deleted file mode 100644
index da59d95..0000000
--- a/test/inline_test_with_deps/test_with_srcs/src/lib.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#[allow(dead_code)]
-fn multiply(val: u32) -> u32 {
-    val * 100
-}
-
-#[cfg(test)]
-mod extra;
-
-#[cfg(test)]
-mod tests {
-    use super::{extra, multiply};
-    use dep::example_test_dep_fn;
-
-    #[test]
-    fn test() {
-        assert_eq!(extra::extra_test_fn(), multiply(example_test_dep_fn()));
-    }
-}
diff --git a/test/out_dir_in_tests/BUILD.bazel b/test/out_dir_in_tests/BUILD.bazel
index c46bae9..496f5aa 100644
--- a/test/out_dir_in_tests/BUILD.bazel
+++ b/test/out_dir_in_tests/BUILD.bazel
@@ -30,9 +30,6 @@
 rust_test_suite(
     name = "suite",
     srcs = glob(["tests/**"]),
-    # Add the 'crate' argument, which will be passed as a kwarg
-    # to the underlying rust_test rules. This will make OUT_DIR
-    # available when compiling integration tests.
-    crate = ":demo_lib",
     edition = "2018",
+    deps = [":build_script"],
 )