Skip to content

Commit 944a540

Browse files
committed
fix(compile): Ignore unused deps if also transitive
This is to reduce false positives without having to ignore them. In fact, I plan to revert support for `ignore` after this change.
1 parent 5442d49 commit 944a540

2 files changed

Lines changed: 47 additions & 14 deletions

File tree

src/cargo/core/compiler/unused_deps.rs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,13 @@ impl UnusedDepState {
9898
} else {
9999
continue;
100100
};
101-
state
102-
.externs
103-
.insert(dep.extern_crate_name, ExternState { manifest_deps });
101+
state.externs.insert(
102+
dep.extern_crate_name,
103+
ExternState {
104+
unit: dep.unit.clone(),
105+
manifest_deps,
106+
},
107+
);
104108
}
105109
}
106110

@@ -229,6 +233,14 @@ impl UnusedDepState {
229233
);
230234
continue;
231235
}
236+
if is_transitive_dep(&extern_state.unit, &state.unused_externs, build_runner) {
237+
debug!(
238+
"pkg {} v{} ({dep_kind:?}): ignoring unused extern `{ext}`, may be activating features",
239+
pkg_id.name(),
240+
pkg_id.version(),
241+
);
242+
continue;
243+
}
232244

233245
// Implicitly added dependencies (in the same crate) aren't interesting
234246
let dependency = if let Some(dependency) = &extern_state.manifest_deps {
@@ -332,6 +344,7 @@ struct DependenciesState {
332344

333345
#[derive(Clone)]
334346
struct ExternState {
347+
unit: Unit,
335348
manifest_deps: Option<Vec<Dependency>>,
336349
}
337350

@@ -359,3 +372,34 @@ fn unit_desc(unit: &Unit) -> String {
359372
unit.mode,
360373
)
361374
}
375+
376+
#[instrument(skip_all)]
377+
fn is_transitive_dep(
378+
direct_dep_unit: &Unit,
379+
unused_externs: &IndexMap<Unit, Vec<InternedString>>,
380+
build_runner: &mut BuildRunner<'_, '_>,
381+
) -> bool {
382+
let mut queue = std::collections::VecDeque::new();
383+
for root_unit in unused_externs.keys() {
384+
for unit_dep in build_runner.unit_deps(root_unit) {
385+
if root_unit.pkg.package_id() == unit_dep.unit.pkg.package_id() {
386+
continue;
387+
}
388+
if unit_dep.unit == *direct_dep_unit {
389+
continue;
390+
}
391+
queue.push_back(&unit_dep.unit);
392+
}
393+
}
394+
395+
while let Some(dep_unit) = queue.pop_front() {
396+
for unit_dep in build_runner.unit_deps(dep_unit) {
397+
if unit_dep.unit == *direct_dep_unit {
398+
return true;
399+
}
400+
queue.push_back(&unit_dep.unit);
401+
}
402+
}
403+
404+
false
405+
}

tests/testsuite/lints/unused_dependencies.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,17 +1320,6 @@ pub fn fun() -> &'static str {
13201320
[CHECKING] transitive v0.1.1
13211321
[CHECKING] intermediate v0.1.0
13221322
[CHECKING] foo v0.1.0 ([ROOT]/foo)
1323-
[WARNING] unused dependency
1324-
--> Cargo.toml:10:13
1325-
|
1326-
10 | transitive = { version = "0.1.1", features = ["a"] }
1327-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1328-
|
1329-
= [NOTE] `cargo::unused_dependencies` is set to `warn` in `[lints]`
1330-
[HELP] remove the dependency
1331-
|
1332-
10 - transitive = { version = "0.1.1", features = ["a"] }
1333-
|
13341323
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
13351324
13361325
"#]]

0 commit comments

Comments
 (0)