Skip to content

Commit e38fdda

Browse files
authored
Rollup merge of #72342 - jsgf:warn-unused-deps, r=petrochenkov
Warn about unused crate deps Implements #57274 by adding -Wunused-crate-dependencies. This will warn about any `--extern` option on the command line which isn't referenced by the crate source either via `use` or `extern crate`. Crates which are added for some side effect but are otherwise unreferenced - such as for symbols they define - the warning can be suppressed with `use somecrate as _;`. If a crate has multiple aliases (eg using `foo = { package = "bar" }` in `Cargo.toml`), then it will warn about each unused alias. This does not consider crate added by some other means than `--extern`, including the standard library. It also doesn't consider any crate without `add_prelude` set (though I'm not sure about this). Unfortunately this probably [does not yet work well with Cargo](#57274 (comment)) as it will over-specify crates, causing spurious warnings. As a result, this lint is "allow" by default and must be explicitly enabled either via `#![warn(unused_crate_deps)]` or with `-Wunused-crate-deps`.
2 parents 0747f58 + ffa493a commit e38fdda

17 files changed

+188
-0
lines changed

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
276276
UNUSED_ALLOCATION,
277277
UNUSED_DOC_COMMENTS,
278278
UNUSED_EXTERN_CRATES,
279+
UNUSED_CRATE_DEPENDENCIES,
279280
UNUSED_FEATURES,
280281
UNUSED_LABELS,
281282
UNUSED_PARENS,

src/librustc_metadata/creader.rs

+29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob
55

66
use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind};
77
use rustc_ast::{ast, attr};
8+
use rustc_data_structures::fx::FxHashSet;
89
use rustc_data_structures::svh::Svh;
910
use rustc_data_structures::sync::Lrc;
1011
use rustc_errors::struct_span_err;
@@ -18,6 +19,7 @@ use rustc_middle::middle::cstore::{
1819
};
1920
use rustc_middle::ty::TyCtxt;
2021
use rustc_session::config::{self, CrateType};
22+
use rustc_session::lint;
2123
use rustc_session::output::validate_crate_name;
2224
use rustc_session::search_paths::PathKind;
2325
use rustc_session::{CrateDisambiguator, Session};
@@ -49,6 +51,7 @@ pub struct CrateLoader<'a> {
4951
local_crate_name: Symbol,
5052
// Mutable output.
5153
cstore: CStore,
54+
used_extern_options: FxHashSet<Symbol>,
5255
}
5356

5457
pub enum LoadedMacro {
@@ -205,6 +208,7 @@ impl<'a> CrateLoader<'a> {
205208
allocator_kind: None,
206209
has_global_allocator: false,
207210
},
211+
used_extern_options: Default::default(),
208212
}
209213
}
210214

@@ -445,6 +449,9 @@ impl<'a> CrateLoader<'a> {
445449
dep_kind: DepKind,
446450
dep: Option<(&'b CratePaths, &'b CrateDep)>,
447451
) -> CrateNum {
452+
if dep.is_none() {
453+
self.used_extern_options.insert(name);
454+
}
448455
self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
449456
}
450457

@@ -839,6 +846,26 @@ impl<'a> CrateLoader<'a> {
839846
});
840847
}
841848

849+
fn report_unused_deps(&mut self, krate: &ast::Crate) {
850+
// Make a point span rather than covering the whole file
851+
let span = krate.span.shrink_to_lo();
852+
// Complain about anything left over
853+
for (name, _) in self.sess.opts.externs.iter() {
854+
if !self.used_extern_options.contains(&Symbol::intern(name)) {
855+
self.sess.parse_sess.buffer_lint(
856+
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
857+
span,
858+
ast::CRATE_NODE_ID,
859+
&format!(
860+
"external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
861+
name,
862+
self.local_crate_name,
863+
name),
864+
);
865+
}
866+
}
867+
}
868+
842869
pub fn postprocess(&mut self, krate: &ast::Crate) {
843870
self.inject_profiler_runtime();
844871
self.inject_allocator_crate(krate);
@@ -847,6 +874,8 @@ impl<'a> CrateLoader<'a> {
847874
if log_enabled!(log::Level::Info) {
848875
dump_crates(&self.cstore);
849876
}
877+
878+
self.report_unused_deps(krate);
850879
}
851880

852881
pub fn process_extern_crate(

src/librustc_session/lint/builtin.rs

+7
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ declare_lint! {
7171
"extern crates that are never used"
7272
}
7373

74+
declare_lint! {
75+
pub UNUSED_CRATE_DEPENDENCIES,
76+
Allow,
77+
"crate dependencies that are never used"
78+
}
79+
7480
declare_lint! {
7581
pub UNUSED_QUALIFICATIONS,
7682
Allow,
@@ -529,6 +535,7 @@ declare_lint_pass! {
529535
UNCONDITIONAL_PANIC,
530536
UNUSED_IMPORTS,
531537
UNUSED_EXTERN_CRATES,
538+
UNUSED_CRATE_DEPENDENCIES,
532539
UNUSED_QUALIFICATIONS,
533540
UNKNOWN_LINTS,
534541
UNUSED_VARIABLES,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub const BAR: &str = "bar";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// edition:2018
2+
// aux-crate:bar=bar.rs
3+
4+
pub const FOO: &str = "foo";
5+
pub use bar::BAR;
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Test warnings for a library crate
2+
3+
// check-pass
4+
// aux-crate:bar=bar.rs
5+
// compile-flags:--crate-type lib -Wunused-crate-dependencies
6+
7+
pub fn fib(n: u32) -> Vec<u32> {
8+
//~^ WARNING external crate `bar` unused in
9+
let mut prev = 0;
10+
let mut cur = 1;
11+
let mut v = vec![];
12+
13+
for _ in 0..n {
14+
v.push(prev);
15+
let n = prev + cur;
16+
prev = cur;
17+
cur = n;
18+
}
19+
20+
v
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
warning: external crate `bar` unused in `libfib`: remove the dependency or add `use bar as _;`
2+
--> $DIR/libfib.rs:7:1
3+
|
4+
LL | pub fn fib(n: u32) -> Vec<u32> {
5+
| ^
6+
|
7+
= note: requested on the command line with `-W unused-crate-dependencies`
8+
9+
warning: 1 warning emitted
10+
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Suppress by using crate
2+
3+
// edition:2018
4+
// check-pass
5+
// aux-crate:bar=bar.rs
6+
7+
#![warn(unused_crate_dependencies)]
8+
9+
use bar as _;
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Warn about unused aliased for the crate
2+
3+
// edition:2018
4+
// check-pass
5+
// aux-crate:bar=bar.rs
6+
// aux-crate:barbar=bar.rs
7+
8+
#![warn(unused_crate_dependencies)]
9+
//~^ WARNING external crate `barbar` unused in
10+
11+
use bar as _;
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: external crate `barbar` unused in `unused_aliases`: remove the dependency or add `use barbar as _;`
2+
--> $DIR/unused-aliases.rs:8:1
3+
|
4+
LL | #![warn(unused_crate_dependencies)]
5+
| ^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unused-aliases.rs:8:9
9+
|
10+
LL | #![warn(unused_crate_dependencies)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
warning: 1 warning emitted
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Suppress by using crate
2+
3+
// edition:2015
4+
// check-pass
5+
// aux-crate:bar=bar.rs
6+
7+
#![warn(unused_crate_dependencies)]
8+
9+
extern crate bar;
10+
11+
fn main() {
12+
println!("bar {}", bar::BAR);
13+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Check for unused crate dep, no path
2+
3+
// edition:2018
4+
// check-pass
5+
// aux-crate:bar=bar.rs
6+
7+
#![warn(unused_crate_dependencies)]
8+
//~^ WARNING external crate `bar` unused in
9+
10+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: external crate `bar` unused in `warn_attr`: remove the dependency or add `use bar as _;`
2+
--> $DIR/warn-attr.rs:7:1
3+
|
4+
LL | #![warn(unused_crate_dependencies)]
5+
| ^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/warn-attr.rs:7:9
9+
|
10+
LL | #![warn(unused_crate_dependencies)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
warning: 1 warning emitted
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Check for unused crate dep, no path
2+
3+
// edition:2018
4+
// check-pass
5+
// compile-flags: -Wunused-crate-dependencies
6+
// aux-crate:bar=bar.rs
7+
// no-prefer-dynamic
8+
9+
fn main() {}
10+
//~^ WARNING external crate `bar` unused in
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
warning: external crate `bar` unused in `warn_cmdline_static`: remove the dependency or add `use bar as _;`
2+
--> $DIR/warn-cmdline-static.rs:9:1
3+
|
4+
LL | fn main() {}
5+
| ^
6+
|
7+
= note: requested on the command line with `-W unused-crate-dependencies`
8+
9+
warning: 1 warning emitted
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Check for unused crate dep, no path
2+
3+
// edition:2018
4+
// check-pass
5+
// compile-flags: -Wunused-crate-dependencies
6+
// aux-crate:bar=bar.rs
7+
8+
fn main() {}
9+
//~^ WARNING external crate `bar` unused in
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
warning: external crate `bar` unused in `warn_cmdline`: remove the dependency or add `use bar as _;`
2+
--> $DIR/warn-cmdline.rs:8:1
3+
|
4+
LL | fn main() {}
5+
| ^
6+
|
7+
= note: requested on the command line with `-W unused-crate-dependencies`
8+
9+
warning: 1 warning emitted
10+

0 commit comments

Comments
 (0)