Skip to content

Commit dede9f5

Browse files
authored
refactor(compile): Log all ignored unused externs (#16920)
### What does this PR try to resolve? Shoring up the logging we do for unused dependency lints to help with debugging and profiling. This could also be useful for users to get more insight on things we can't or won't show, like helping hunt down features to deactivate to reduce unused dependencies (e.g. `cli` on `pulldown-cmark`) or removing transitively unused dependencies. ### How to test and review this PR? Running this on `cargo` itself: ```console $ CARGO_LOG=cargo::core::compiler::unused_deps=debug nargo check ... 2.537113285s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg crypto-common v0.1.6 (normal): ignoring unused extern `typenum`, untracked dependent 2.537569241s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg heapless v0.8.0 (normal): ignoring unused extern `stable_deref_trait`, untracked dependent 2.537758659s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg faster-hex v0.10.0 (normal): ignoring unused extern `heapless`, untracked dependent 2.537984665s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-date v0.15.1 (normal): ignoring unused extern `bstr`, untracked dependent 2.538312867s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-object v0.58.0 (normal): ignoring unused extern `gix_hashtable`, untracked dependent 2.538704975s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-tempfile v21.0.2 (normal): ignoring unused extern `libc`, untracked dependent 2.538762374s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-tempfile v21.0.2 (normal): ignoring unused extern `parking_lot`, untracked dependent 2.539010269s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-commitgraph v0.35.0 (normal): ignoring unused extern `bstr`, untracked dependent 2.539205527s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg libnghttp2-sys v0.1.13+1.68.1 (normal): ignoring unused extern `libc`, untracked dependent 2.539597903s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg curl-sys v0.4.87+curl-8.19.0 (normal): ignoring unused extern `libnghttp2_sys`, untracked dependent 2.539654548s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg curl-sys v0.4.87+curl-8.19.0 (normal): ignoring unused extern `libz_sys`, untracked dependent 2.539711192s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg curl-sys v0.4.87+curl-8.19.0 (normal): ignoring unused extern `openssl_sys`, untracked dependent 2.540319246s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg curl v0.4.49 (normal): ignoring unused extern `openssl_probe`, untracked dependent 2.540373049s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg curl v0.4.49 (normal): ignoring unused extern `openssl_sys`, untracked dependent 2.540811522s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-index v0.49.0 (normal): ignoring unused extern `gix_fs`, untracked dependent 2.541504178s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-revision v0.43.0 (normal): ignoring unused extern `gix_commitgraph`, untracked dependent 2.541560742s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-revision v0.43.0 (normal): ignoring unused extern `nonempty`, untracked dependent 2.541873702s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg nix v0.30.1 (normal): ignoring unused extern `bitflags`, lint is allowed 2.542548816s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg nom v7.1.3 (normal): ignoring unused extern `minimal_lexical`, lint is allowed 2.542935941s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-negotiate v0.29.0 (normal): ignoring unused extern `gix_commitgraph`, untracked dependent 2.542989018s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix-negotiate v0.29.0 (normal): ignoring unused extern `gix_object`, untracked dependent 2.543198046s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg tracing-subscriber v0.3.23 (normal): ignoring unused extern `once_cell`, lint is allowed 2.543249959s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg tracing-subscriber v0.3.23 (normal): ignoring unused extern `regex_automata`, lint is allowed 2.543640436s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg git2 v0.20.4 (normal): ignoring unused extern `openssl_sys`, untracked dependent 2.544004330s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg regex v1.12.3 (normal): ignoring unused extern `aho_corasick`, lint is allowed 2.544419766s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg futures v0.3.32 (normal): ignoring unused extern `futures_task`, lint is allowed 2.544564859s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix v0.81.0 (normal): ignoring unused extern `gix_revision`, untracked dependent 2.544617049s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg gix v0.81.0 (normal): ignoring unused extern `prodash`, untracked dependent 2.544779907s debug emit_unused_warnings: cargo::core::compiler::unused_deps: pkg rustfix v0.9.6 (normal): ignoring unused extern `tracing`, untracked dependent Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.54s ``` Doesn't work too well for `--all-targets` because we don't support dev targets at the moment, so we don't track which externs came from dependencies vs dev-dependencies. Also, of note that I found while doing this that confused me at first is that we don't fingerprint `-Zcargo-lints`, so users can have stale caches with no unused externs "reported" by rustc to cargo.
2 parents 06ac0e7 + 4bcdfc1 commit dede9f5

1 file changed

Lines changed: 55 additions & 25 deletions

File tree

src/cargo/core/compiler/unused_deps.rs

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use cargo_util_terminal::report::Patch;
77
use cargo_util_terminal::report::Snippet;
88
use indexmap::IndexMap;
99
use indexmap::IndexSet;
10-
use tracing::trace;
10+
use tracing::{debug, instrument, trace};
1111

1212
use super::BuildRunner;
1313
use super::unit::Unit;
@@ -30,13 +30,11 @@ pub struct UnusedDepState {
3030
}
3131

3232
impl UnusedDepState {
33+
#[instrument(name = "UnusedDepState::new", skip_all)]
3334
pub fn new(build_runner: &mut BuildRunner<'_, '_>) -> Self {
34-
let mut states = IndexMap::<_, IndexMap<_, DependenciesState>>::new();
35-
36-
let roots = &build_runner.bcx.roots;
37-
3835
// Find all units for a package that can report unused externs
3936
let mut root_build_script_builds = IndexSet::new();
37+
let roots = &build_runner.bcx.roots;
4038
for root in roots.iter() {
4139
for build_script_run in build_runner.unit_deps(root).iter() {
4240
if !build_script_run.unit.target.is_custom_build()
@@ -62,6 +60,7 @@ impl UnusedDepState {
6260
"selected dep kinds: {:?}",
6361
build_runner.bcx.selected_dep_kinds
6462
);
63+
let mut states = IndexMap::<_, IndexMap<_, DependenciesState>>::new();
6564
for root in roots.iter().chain(root_build_script_builds.iter()) {
6665
let pkg_id = root.pkg.package_id();
6766
let dep_kind = dep_kind_of(root);
@@ -85,7 +84,7 @@ impl UnusedDepState {
8584
.or_default()
8685
.entry(dep_kind)
8786
.or_default();
88-
state.needed_units += 1;
87+
*state.needed_units.get_or_insert_default() += 1;
8988
for dep in build_runner.unit_deps(root).iter() {
9089
trace!(
9190
" => {} (deps={})",
@@ -108,16 +107,26 @@ impl UnusedDepState {
108107

109108
pub fn record_unused_externs_for_unit(&mut self, unit: &Unit, unused_externs: Vec<String>) {
110109
let pkg_id = unit.pkg.package_id();
111-
let kind = dep_kind_of(unit);
112-
if let Some(state) = self.states.get_mut(&pkg_id).and_then(|s| s.get_mut(&kind)) {
113-
state
114-
.unused_externs
115-
.entry(unit.clone())
116-
.or_default()
117-
.extend(unused_externs.into_iter().map(|s| InternedString::new(&s)));
118-
}
110+
let dep_kind = dep_kind_of(unit);
111+
trace!(
112+
"pkg {} v{} ({dep_kind:?}): unused externs {unused_externs:?}",
113+
pkg_id.name(),
114+
pkg_id.version(),
115+
);
116+
let state = self
117+
.states
118+
.entry(pkg_id)
119+
.or_default()
120+
.entry(dep_kind)
121+
.or_default();
122+
state
123+
.unused_externs
124+
.entry(unit.clone())
125+
.or_default()
126+
.extend(unused_externs.into_iter().map(|s| InternedString::new(&s)));
119127
}
120128

129+
#[instrument(skip_all)]
121130
pub fn emit_unused_warnings(
122131
&self,
123132
warn_count: &mut usize,
@@ -146,6 +155,15 @@ impl UnusedDepState {
146155
);
147156

148157
if lint_level == LintLevel::Allow {
158+
for (dep_kind, state) in states.iter() {
159+
for ext in state.unused_externs.values().flatten() {
160+
debug!(
161+
"pkg {} v{} ({dep_kind:?}): ignoring unused extern `{ext}`, lint is allowed",
162+
pkg_id.name(),
163+
pkg_id.version(),
164+
);
165+
}
166+
}
149167
continue;
150168
}
151169

@@ -169,16 +187,29 @@ impl UnusedDepState {
169187
let manifest_path = rel_cwd_manifest_path(pkg.manifest_path(), build_runner.bcx.gctx);
170188
let mut lint_count = 0;
171189
for (dep_kind, state) in states.iter() {
172-
if state.unused_externs.len() != state.needed_units {
190+
let Some(needed_units) = state.needed_units else {
191+
// not one we care to report
192+
for ext in state.unused_externs.values().flatten() {
193+
debug!(
194+
"pkg {} v{} ({dep_kind:?}): ignoring unused extern `{ext}`, untracked dependent",
195+
pkg_id.name(),
196+
pkg_id.version(),
197+
);
198+
}
199+
continue;
200+
};
201+
if state.unused_externs.len() != needed_units {
173202
// Some compilations errored without printing the unused externs.
174203
// Don't print the warning in order to reduce false positive
175204
// spam during errors.
176-
trace!(
177-
"pkg {} v{} ({dep_kind:?}): ignoring unused deps due to {} outstanding units",
178-
pkg_id.name(),
179-
pkg_id.version(),
180-
state.needed_units
181-
);
205+
for ext in state.unused_externs.values().flatten() {
206+
debug!(
207+
"pkg {} v{} ({dep_kind:?}): ignoring unused extern `{ext}`, {} outstanding units",
208+
pkg_id.name(),
209+
pkg_id.version(),
210+
needed_units - state.unused_externs.len()
211+
);
212+
}
182213
continue;
183214
}
184215

@@ -205,11 +236,10 @@ impl UnusedDepState {
205236
};
206237
for dependency in dependency {
207238
if ignore.contains(&dependency.name_in_toml()) {
208-
trace!(
209-
"pkg {} v{} ({dep_kind:?}): extern {} is ignored",
239+
debug!(
240+
"pkg {} v{} ({dep_kind:?}): ignoring unused extern `{ext}`, requested in manifest",
210241
pkg_id.name(),
211242
pkg_id.version(),
212-
ext
213243
);
214244
continue;
215245
}
@@ -293,7 +323,7 @@ struct DependenciesState {
293323
///
294324
/// To avoid warning in cases where we didn't,
295325
/// e.g. if a [`Unit`] errored and didn't report unused externs.
296-
needed_units: usize,
326+
needed_units: Option<usize>,
297327
/// As reported by rustc
298328
unused_externs: IndexMap<Unit, Vec<InternedString>>,
299329
}

0 commit comments

Comments
 (0)