]> git.lizzy.rs Git - rust.git/commitdiff
Implement warning for unused dependencies.
authorJeremy Fitzhardinge <jeremy@goop.org>
Sun, 17 May 2020 08:48:01 +0000 (01:48 -0700)
committerJeremy Fitzhardinge <jeremy@goop.org>
Tue, 26 May 2020 05:47:55 +0000 (22:47 -0700)
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 #57274

17 files changed:
src/librustc_lint/lib.rs
src/librustc_metadata/creader.rs
src/librustc_session/lint/builtin.rs
src/test/ui/unused-crate-deps/auxiliary/bar.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/auxiliary/foo.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/libfib.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/libfib.stderr [new file with mode: 0644]
src/test/ui/unused-crate-deps/suppress.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/unused-aliases.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/unused-aliases.stderr [new file with mode: 0644]
src/test/ui/unused-crate-deps/use_extern_crate_2015.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/warn-attr.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/warn-attr.stderr [new file with mode: 0644]
src/test/ui/unused-crate-deps/warn-cmdline-static.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/warn-cmdline-static.stderr [new file with mode: 0644]
src/test/ui/unused-crate-deps/warn-cmdline.rs [new file with mode: 0644]
src/test/ui/unused-crate-deps/warn-cmdline.stderr [new file with mode: 0644]

index b791d313fc4f438a47e0e850da80401770ab3a6b..ee27342541c93178a4b4fcf432866cdc19c32a00 100644 (file)
@@ -276,6 +276,7 @@ macro_rules! register_passes {
         UNUSED_ALLOCATION,
         UNUSED_DOC_COMMENTS,
         UNUSED_EXTERN_CRATES,
+        UNUSED_CRATE_DEPENDENCIES,
         UNUSED_FEATURES,
         UNUSED_LABELS,
         UNUSED_PARENS,
index b0220ddd3c38efcc316ab86a27fb29705ca92aa3..db29e9538999a4276cb3c8a377065275c490a690 100644 (file)
@@ -5,6 +5,7 @@
 
 use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind};
 use rustc_ast::{ast, attr};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
@@ -18,6 +19,7 @@
 };
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{self, CrateType};
+use rustc_session::lint;
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
 use rustc_session::{CrateDisambiguator, Session};
@@ -49,6 +51,7 @@ pub struct CrateLoader<'a> {
     local_crate_name: Symbol,
     // Mutable output.
     cstore: CStore,
+    used_extern_options: FxHashSet<Symbol>,
 }
 
 pub enum LoadedMacro {
@@ -205,6 +208,7 @@ pub fn new(
                 allocator_kind: None,
                 has_global_allocator: false,
             },
+            used_extern_options: Default::default(),
         }
     }
 
@@ -445,6 +449,9 @@ fn resolve_crate<'b>(
         dep_kind: DepKind,
         dep: Option<(&'b CratePaths, &'b CrateDep)>,
     ) -> CrateNum {
+        if dep.is_none() {
+            self.used_extern_options.insert(name);
+        }
         self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
     }
 
@@ -839,6 +846,26 @@ fn inject_dependency_if(
         });
     }
 
+    fn report_unused_deps(&mut self, krate: &ast::Crate) {
+        // Make a point span rather than covering the whole file
+        let span = krate.span.shrink_to_lo();
+        // Complain about anything left over
+        for (name, _) in self.sess.opts.externs.iter() {
+            if !self.used_extern_options.contains(&Symbol::intern(name)) {
+                self.sess.parse_sess.buffer_lint(
+                    lint::builtin::UNUSED_CRATE_DEPENDENCIES,
+                    span,
+                    ast::CRATE_NODE_ID,
+                    &format!(
+                        "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
+                        name,
+                        self.local_crate_name,
+                        name),
+                );
+            }
+        }
+    }
+
     pub fn postprocess(&mut self, krate: &ast::Crate) {
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
@@ -847,6 +874,8 @@ pub fn postprocess(&mut self, krate: &ast::Crate) {
         if log_enabled!(log::Level::Info) {
             dump_crates(&self.cstore);
         }
+
+        self.report_unused_deps(krate);
     }
 
     pub fn process_extern_crate(
index 3d03e46683ed5a138c61196ae236404df7eea561..66d89087991819645d239cf5586b4bb15efbff7e 100644 (file)
     "extern crates that are never used"
 }
 
+declare_lint! {
+    pub UNUSED_CRATE_DEPENDENCIES,
+    Allow,
+    "crate dependencies that are never used"
+}
+
 declare_lint! {
     pub UNUSED_QUALIFICATIONS,
     Allow,
         UNCONDITIONAL_PANIC,
         UNUSED_IMPORTS,
         UNUSED_EXTERN_CRATES,
+        UNUSED_CRATE_DEPENDENCIES,
         UNUSED_QUALIFICATIONS,
         UNKNOWN_LINTS,
         UNUSED_VARIABLES,
diff --git a/src/test/ui/unused-crate-deps/auxiliary/bar.rs b/src/test/ui/unused-crate-deps/auxiliary/bar.rs
new file mode 100644 (file)
index 0000000..1d3824e
--- /dev/null
@@ -0,0 +1 @@
+pub const BAR: &str = "bar";
diff --git a/src/test/ui/unused-crate-deps/auxiliary/foo.rs b/src/test/ui/unused-crate-deps/auxiliary/foo.rs
new file mode 100644 (file)
index 0000000..0ef03eb
--- /dev/null
@@ -0,0 +1,5 @@
+// edition:2018
+// aux-crate:bar=bar.rs
+
+pub const FOO: &str = "foo";
+pub use bar::BAR;
diff --git a/src/test/ui/unused-crate-deps/libfib.rs b/src/test/ui/unused-crate-deps/libfib.rs
new file mode 100644 (file)
index 0000000..c1545dc
--- /dev/null
@@ -0,0 +1,21 @@
+// Test warnings for a library crate
+
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--crate-type lib -Wunused-crate-dependencies
+
+pub fn fib(n: u32) -> Vec<u32> {
+//~^ WARNING external crate `bar` unused in
+let mut prev = 0;
+    let mut cur = 1;
+    let mut v = vec![];
+
+    for _ in 0..n {
+        v.push(prev);
+        let n = prev + cur;
+        prev = cur;
+        cur = n;
+    }
+
+    v
+}
diff --git a/src/test/ui/unused-crate-deps/libfib.stderr b/src/test/ui/unused-crate-deps/libfib.stderr
new file mode 100644 (file)
index 0000000..1583312
--- /dev/null
@@ -0,0 +1,10 @@
+warning: external crate `bar` unused in `libfib`: remove the dependency or add `use bar as _;`
+  --> $DIR/libfib.rs:7:1
+   |
+LL | pub fn fib(n: u32) -> Vec<u32> {
+   | ^
+   |
+   = note: requested on the command line with `-W unused-crate-dependencies`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/unused-crate-deps/suppress.rs b/src/test/ui/unused-crate-deps/suppress.rs
new file mode 100644 (file)
index 0000000..8904d04
--- /dev/null
@@ -0,0 +1,11 @@
+// Suppress by using crate
+
+// edition:2018
+// check-pass
+// aux-crate:bar=bar.rs
+
+#![warn(unused_crate_dependencies)]
+
+use bar as _;
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/unused-aliases.rs b/src/test/ui/unused-crate-deps/unused-aliases.rs
new file mode 100644 (file)
index 0000000..1b7cb9b
--- /dev/null
@@ -0,0 +1,13 @@
+// Warn about unused aliased for the crate
+
+// edition:2018
+// check-pass
+// aux-crate:bar=bar.rs
+// aux-crate:barbar=bar.rs
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `barbar` unused in
+
+use bar as _;
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/unused-aliases.stderr b/src/test/ui/unused-crate-deps/unused-aliases.stderr
new file mode 100644 (file)
index 0000000..c8c6c45
--- /dev/null
@@ -0,0 +1,14 @@
+warning: external crate `barbar` unused in `unused_aliases`: remove the dependency or add `use barbar as _;`
+  --> $DIR/unused-aliases.rs:8:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-aliases.rs:8:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/unused-crate-deps/use_extern_crate_2015.rs b/src/test/ui/unused-crate-deps/use_extern_crate_2015.rs
new file mode 100644 (file)
index 0000000..f15c87f
--- /dev/null
@@ -0,0 +1,13 @@
+// Suppress by using crate
+
+// edition:2015
+// check-pass
+// aux-crate:bar=bar.rs
+
+#![warn(unused_crate_dependencies)]
+
+extern crate bar;
+
+fn main() {
+    println!("bar {}", bar::BAR);
+}
diff --git a/src/test/ui/unused-crate-deps/warn-attr.rs b/src/test/ui/unused-crate-deps/warn-attr.rs
new file mode 100644 (file)
index 0000000..1acb307
--- /dev/null
@@ -0,0 +1,10 @@
+// Check for unused crate dep, no path
+
+// edition:2018
+// check-pass
+// aux-crate:bar=bar.rs
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `bar` unused in
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/warn-attr.stderr b/src/test/ui/unused-crate-deps/warn-attr.stderr
new file mode 100644 (file)
index 0000000..0d38315
--- /dev/null
@@ -0,0 +1,14 @@
+warning: external crate `bar` unused in `warn_attr`: remove the dependency or add `use bar as _;`
+  --> $DIR/warn-attr.rs:7:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/warn-attr.rs:7:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/unused-crate-deps/warn-cmdline-static.rs b/src/test/ui/unused-crate-deps/warn-cmdline-static.rs
new file mode 100644 (file)
index 0000000..c609529
--- /dev/null
@@ -0,0 +1,10 @@
+// Check for unused crate dep, no path
+
+// edition:2018
+// check-pass
+// compile-flags: -Wunused-crate-dependencies
+// aux-crate:bar=bar.rs
+// no-prefer-dynamic
+
+fn main() {}
+//~^ WARNING external crate `bar` unused in
diff --git a/src/test/ui/unused-crate-deps/warn-cmdline-static.stderr b/src/test/ui/unused-crate-deps/warn-cmdline-static.stderr
new file mode 100644 (file)
index 0000000..6595646
--- /dev/null
@@ -0,0 +1,10 @@
+warning: external crate `bar` unused in `warn_cmdline_static`: remove the dependency or add `use bar as _;`
+  --> $DIR/warn-cmdline-static.rs:9:1
+   |
+LL | fn main() {}
+   | ^
+   |
+   = note: requested on the command line with `-W unused-crate-dependencies`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/unused-crate-deps/warn-cmdline.rs b/src/test/ui/unused-crate-deps/warn-cmdline.rs
new file mode 100644 (file)
index 0000000..3bae61c
--- /dev/null
@@ -0,0 +1,9 @@
+// Check for unused crate dep, no path
+
+// edition:2018
+// check-pass
+// compile-flags: -Wunused-crate-dependencies
+// aux-crate:bar=bar.rs
+
+fn main() {}
+//~^ WARNING external crate `bar` unused in
diff --git a/src/test/ui/unused-crate-deps/warn-cmdline.stderr b/src/test/ui/unused-crate-deps/warn-cmdline.stderr
new file mode 100644 (file)
index 0000000..ea675ba
--- /dev/null
@@ -0,0 +1,10 @@
+warning: external crate `bar` unused in `warn_cmdline`: remove the dependency or add `use bar as _;`
+  --> $DIR/warn-cmdline.rs:8:1
+   |
+LL | fn main() {}
+   | ^
+   |
+   = note: requested on the command line with `-W unused-crate-dependencies`
+
+warning: 1 warning emitted
+