Skip to content

Commit 0a89c03

Browse files
committed
Implement warning for unused dependencies.
This will print a diagnostic for crates which are mentioned as `--extern` arguments on the command line, but are never referenced from the source. This diagnostic is controlled by `-Wunused-crate-dependencies` or `#![warn(unused_crate_dependencies)]` and is "allow" by default. There are cases where certain crates need to be linked in but are not directly referenced - for example if they are providing symbols for C linkage. In this case the warning can be suppressed with `use needed_crate as _;`. Thanks to @petrochenkov for simplified core. Resolves issue rust-lang#57274
1 parent 4fb7144 commit 0a89c03

17 files changed

+188
-0
lines changed

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
272272
UNUSED_ALLOCATION,
273273
UNUSED_DOC_COMMENTS,
274274
UNUSED_EXTERN_CRATES,
275+
UNUSED_CRATE_DEPENDENCIES,
275276
UNUSED_FEATURES,
276277
UNUSED_LABELS,
277278
UNUSED_PARENS,

src/librustc_metadata/creader.rs

+29
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ use rustc::hir::map::Definitions;
77
use rustc::middle::cstore::DepKind;
88
use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
99
use rustc::session::config;
10+
use rustc::session::lint;
1011
use rustc::session::search_paths::PathKind;
1112
use rustc::session::{CrateDisambiguator, Session};
1213
use rustc::ty::TyCtxt;
1314
use rustc_ast::ast;
1415
use rustc_ast::attr;
1516
use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind};
17+
use rustc_data_structures::fx::FxHashSet;
1618
use rustc_data_structures::svh::Svh;
1719
use rustc_data_structures::sync::Lrc;
1820
use rustc_errors::struct_span_err;
@@ -47,6 +49,7 @@ pub struct CrateLoader<'a> {
4749
local_crate_name: Symbol,
4850
// Mutable output.
4951
cstore: CStore,
52+
used_extern_options: FxHashSet<Symbol>,
5053
}
5154

5255
pub enum LoadedMacro {
@@ -197,6 +200,7 @@ impl<'a> CrateLoader<'a> {
197200
allocator_kind: None,
198201
has_global_allocator: false,
199202
},
203+
used_extern_options: Default::default(),
200204
}
201205
}
202206

@@ -437,6 +441,9 @@ impl<'a> CrateLoader<'a> {
437441
dep_kind: DepKind,
438442
dep: Option<(&'b CratePaths, &'b CrateDep)>,
439443
) -> CrateNum {
444+
if dep.is_none() {
445+
self.used_extern_options.insert(name);
446+
}
440447
self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
441448
}
442449

@@ -830,6 +837,26 @@ impl<'a> CrateLoader<'a> {
830837
});
831838
}
832839

840+
fn report_unused_deps(&mut self, krate: &ast::Crate) {
841+
// Make a point span rather than covering the whole file
842+
let span = krate.span.shrink_to_lo();
843+
// Complain about anything left over
844+
for (name, _) in self.sess.opts.externs.iter() {
845+
if !self.used_extern_options.contains(&Symbol::intern(name)) {
846+
self.sess.parse_sess.buffer_lint(
847+
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
848+
span,
849+
ast::CRATE_NODE_ID,
850+
&format!(
851+
"external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
852+
name,
853+
self.local_crate_name,
854+
name),
855+
);
856+
}
857+
}
858+
}
859+
833860
pub fn postprocess(&mut self, krate: &ast::Crate) {
834861
self.inject_profiler_runtime();
835862
self.inject_allocator_crate(krate);
@@ -838,6 +865,8 @@ impl<'a> CrateLoader<'a> {
838865
if log_enabled!(log::Level::Info) {
839866
dump_crates(&self.cstore);
840867
}
868+
869+
self.report_unused_deps(krate);
841870
}
842871

843872
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,
@@ -505,6 +511,7 @@ declare_lint_pass! {
505511
UNCONDITIONAL_PANIC,
506512
UNUSED_IMPORTS,
507513
UNUSED_EXTERN_CRATES,
514+
UNUSED_CRATE_DEPENDENCIES,
508515
UNUSED_QUALIFICATIONS,
509516
UNKNOWN_LINTS,
510517
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)