UNUSED_ALLOCATION,
UNUSED_DOC_COMMENTS,
UNUSED_EXTERN_CRATES,
+ UNUSED_CRATE_DEPENDENCIES,
UNUSED_FEATURES,
UNUSED_LABELS,
UNUSED_PARENS,
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;
};
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};
local_crate_name: Symbol,
// Mutable output.
cstore: CStore,
+ used_extern_options: FxHashSet<Symbol>,
}
pub enum LoadedMacro {
allocator_kind: None,
has_global_allocator: false,
},
+ used_extern_options: Default::default(),
}
}
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())
}
});
}
+ 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);
if log_enabled!(log::Level::Info) {
dump_crates(&self.cstore);
}
+
+ self.report_unused_deps(krate);
}
pub fn process_extern_crate(
"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,
--- /dev/null
+pub const BAR: &str = "bar";
--- /dev/null
+// edition:2018
+// aux-crate:bar=bar.rs
+
+pub const FOO: &str = "foo";
+pub use bar::BAR;
--- /dev/null
+// 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
+}
--- /dev/null
+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
+
--- /dev/null
+// Suppress by using crate
+
+// edition:2018
+// check-pass
+// aux-crate:bar=bar.rs
+
+#![warn(unused_crate_dependencies)]
+
+use bar as _;
+
+fn main() {}
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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() {}
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+
--- /dev/null
+// 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
--- /dev/null
+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
+