Skip to content

unused_crate_dependencies false-positives in Cargo packages with muliple Cargo Targets (lib, bins, examples, tests, benches) #95513

Open
@MarijnS95

Description

@MarijnS95

I tried this code:

Consider a crate setup with the clap dependency, where clap is used only by the lib target:

Cargo.toml:

[package]
name = "multiple_targets"

[dependencies]
clap = { version = "3", features = ["derive"] }

src/lib.rs:

use clap::Parser;

#[derive(Parser)]
pub struct Args {}

This is fine when checking with this lint enabled:

$ RUSTFLAGS=-Wunused-crate-dependencies cargo c --all --all-targets

Now, consider adding multiple targets to this crate. For the sake of demonstration, we use a test and bin target that both utilize the library crate defined above:

src/main.rs:

fn main() {
    let _x = multiple_targets::Args {};
}

tests/test.rs:

#[test]
fn test() {
    let _x = multiple_targets::Args {};
}

We run the same check command again:

$ RUSTFLAGS=-Wunused-crate-dependencies cargo c --all --all-targets

I expected to see this happen:

No external crate `clap` unused warnings show up.

Instead, this happened:

Every target seems to be checked individually against the set of defined crate dependencies, instead of identifying dependencies that are not used by all targets combined (or at the very least lib+bins, as test-only dependencies should reside under dev-dependencies). As such, both the test and binary targets above are accused of not using clap:

warning: external crate `clap` unused in `multiple_targets`: remove the dependency or add `use clap as _;`
  |
  = note: requested on the command line with `-W unused-crate-dependencies`
  = help: remove unnecessary dependency `clap`

warning: external crate `clap` unused in `test`: remove the dependency or add `use clap as _;`
  |
  = note: requested on the command line with `-W unused-crate-dependencies`
  = help: remove unnecessary dependency `clap`

warning: `multiple_targets` (bin "multiple_targets") generated 1 warning
warning: `multiple_targets` (bin "multiple_targets" test) generated 1 warning (1 duplicate)
warning: `multiple_targets` (test "test") generated 1 warning

For the most part, especially larger library crates, this makes it impossible to write clean test binaries without having the top half filled with use {dep_a as _, dep_b as _, ...};.

Note that our project currently comprises 92 crates in a single git repository, and we use a single .cargo/config.toml in the workspace root to configure lints all at once. It is completely infeasible for us to duplicate these to every existing and up and coming crate, nor keep them in sync after the fact. As such, copy-pasting #[warn(unused-crate-dependencies)] across just the lib.rs/main.rs bits of our code base (where only a single target is used) is pretty much impossible.


EDIT: I can understand this warning to show up for the binary (test) targets if they do not reference the library target, but it is particularly confusing when these binary targets at least transitively use the dependency through the library target.

Meta

rustc --version --verbose:

rustc 1.61.0-nightly (c5cf08d37 2022-03-30)
binary: rustc
commit-hash: c5cf08d37b85f953b132951e868df5b924250fdc
commit-date: 2022-03-30
host: x86_64-unknown-linux-gnu
release: 1.61.0-nightly
LLVM version: 14.0.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-cratesArea: Crates and their interactions (like crate loading)A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.L-false-positiveLint: False positive (should not have fired).L-unused_crate_dependenciesLint: unused_crate_dependenciesT-cargoRelevant to the cargo team, which will review and decide on the PR/issue.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions