Emit the lint level of the unused-crate-dependencies
Also, turn off the lint when the unused dependencies json flag is specified so that cargo doesn't have to supress the lint
This commit is contained in:
parent
13371b59ee
commit
3a62eb74db
6 changed files with 66 additions and 19 deletions
|
@ -196,7 +196,7 @@ pub trait Emitter {
|
||||||
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
|
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
|
||||||
|
|
||||||
/// Emit list of unused externs
|
/// Emit list of unused externs
|
||||||
fn emit_unused_externs(&mut self, _unused_externs: &[&str]) {}
|
fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {}
|
||||||
|
|
||||||
/// Checks if should show explanations about "rustc --explain"
|
/// Checks if should show explanations about "rustc --explain"
|
||||||
fn should_show_explain(&self) -> bool {
|
fn should_show_explain(&self) -> bool {
|
||||||
|
|
|
@ -159,8 +159,8 @@ impl Emitter for JsonEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unused_externs(&mut self, unused_externs: &[&str]) {
|
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
|
||||||
let data = UnusedExterns { unused_extern_names: unused_externs };
|
let data = UnusedExterns { lint_level, unused_extern_names: unused_externs };
|
||||||
let result = if self.pretty {
|
let result = if self.pretty {
|
||||||
writeln!(&mut self.dst, "{}", as_pretty_json(&data))
|
writeln!(&mut self.dst, "{}", as_pretty_json(&data))
|
||||||
} else {
|
} else {
|
||||||
|
@ -336,9 +336,11 @@ struct FutureIncompatReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encodable)]
|
#[derive(Encodable)]
|
||||||
struct UnusedExterns<'a, 'b> {
|
struct UnusedExterns<'a, 'b, 'c> {
|
||||||
|
/// The severity level of the unused dependencies lint
|
||||||
|
lint_level: &'a str,
|
||||||
/// List of unused externs by their names.
|
/// List of unused externs by their names.
|
||||||
unused_extern_names: &'a [&'b str],
|
unused_extern_names: &'b [&'c str],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Diagnostic {
|
impl Diagnostic {
|
||||||
|
|
|
@ -767,8 +767,8 @@ impl Handler {
|
||||||
self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
|
self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_unused_externs(&self, unused_externs: &[&str]) {
|
pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) {
|
||||||
self.inner.borrow_mut().emit_unused_externs(unused_externs)
|
self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delay_as_bug(&self, diagnostic: Diagnostic) {
|
pub fn delay_as_bug(&self, diagnostic: Diagnostic) {
|
||||||
|
@ -845,8 +845,8 @@ impl HandlerInner {
|
||||||
self.emitter.emit_artifact_notification(path, artifact_type);
|
self.emitter.emit_artifact_notification(path, artifact_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unused_externs(&mut self, unused_externs: &[&str]) {
|
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
|
||||||
self.emitter.emit_unused_externs(unused_externs);
|
self.emitter.emit_unused_externs(lint_level, unused_externs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn treat_err_as_bug(&self) -> bool {
|
fn treat_err_as_bug(&self) -> bool {
|
||||||
|
|
|
@ -17,6 +17,7 @@ use rustc_hir::definitions::Definitions;
|
||||||
use rustc_hir::Crate;
|
use rustc_hir::Crate;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_lint::LintStore;
|
use rustc_lint::LintStore;
|
||||||
|
use rustc_metadata::creader::CStore;
|
||||||
use rustc_middle::arena::Arena;
|
use rustc_middle::arena::Arena;
|
||||||
use rustc_middle::dep_graph::DepGraph;
|
use rustc_middle::dep_graph::DepGraph;
|
||||||
use rustc_middle::middle;
|
use rustc_middle::middle;
|
||||||
|
@ -836,6 +837,12 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
|
||||||
});
|
});
|
||||||
|
|
||||||
sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
|
sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
|
||||||
|
|
||||||
|
let cstore = tcx
|
||||||
|
.cstore_as_any()
|
||||||
|
.downcast_ref::<CStore>()
|
||||||
|
.expect("`tcx.cstore` is not a `CStore`");
|
||||||
|
cstore.report_unused_deps(tcx);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
||||||
|
|
|
@ -46,6 +46,9 @@ pub struct CStore {
|
||||||
/// This map is used to verify we get no hash conflicts between
|
/// This map is used to verify we get no hash conflicts between
|
||||||
/// `StableCrateId` values.
|
/// `StableCrateId` values.
|
||||||
stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
|
stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
|
||||||
|
|
||||||
|
/// Unused externs of the crate
|
||||||
|
unused_externs: Vec<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CrateLoader<'a> {
|
pub struct CrateLoader<'a> {
|
||||||
|
@ -190,6 +193,21 @@ impl CStore {
|
||||||
crate fn has_global_allocator(&self) -> bool {
|
crate fn has_global_allocator(&self) -> bool {
|
||||||
self.has_global_allocator
|
self.has_global_allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
|
||||||
|
let level = tcx
|
||||||
|
.lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID)
|
||||||
|
.0;
|
||||||
|
if level != lint::Level::Allow && tcx.sess.opts.json_unused_externs {
|
||||||
|
let unused_externs =
|
||||||
|
self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>();
|
||||||
|
let unused_externs = unused_externs.iter().map(String::as_str).collect::<Vec<&str>>();
|
||||||
|
tcx.sess
|
||||||
|
.parse_sess
|
||||||
|
.span_diagnostic
|
||||||
|
.emit_unused_externs(level.as_str(), &unused_externs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CrateLoader<'a> {
|
impl<'a> CrateLoader<'a> {
|
||||||
|
@ -217,6 +235,7 @@ impl<'a> CrateLoader<'a> {
|
||||||
allocator_kind: None,
|
allocator_kind: None,
|
||||||
has_global_allocator: false,
|
has_global_allocator: false,
|
||||||
stable_crate_ids,
|
stable_crate_ids,
|
||||||
|
unused_externs: Vec::new(),
|
||||||
},
|
},
|
||||||
used_extern_options: Default::default(),
|
used_extern_options: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -893,18 +912,23 @@ impl<'a> CrateLoader<'a> {
|
||||||
fn report_unused_deps(&mut self, krate: &ast::Crate) {
|
fn report_unused_deps(&mut self, krate: &ast::Crate) {
|
||||||
// Make a point span rather than covering the whole file
|
// Make a point span rather than covering the whole file
|
||||||
let span = krate.span.shrink_to_lo();
|
let span = krate.span.shrink_to_lo();
|
||||||
let mut unused_externs = Vec::new();
|
|
||||||
// Complain about anything left over
|
// Complain about anything left over
|
||||||
for (name, entry) in self.sess.opts.externs.iter() {
|
for (name, entry) in self.sess.opts.externs.iter() {
|
||||||
if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
|
if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
|
||||||
// Don't worry about pathless `--extern foo` sysroot references
|
// Don't worry about pathless `--extern foo` sysroot references
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if self.used_extern_options.contains(&Symbol::intern(name)) {
|
let name_interned = Symbol::intern(name);
|
||||||
|
if self.used_extern_options.contains(&name_interned) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Got a real unused --extern
|
// Got a real unused --extern
|
||||||
|
if self.sess.opts.json_unused_externs {
|
||||||
|
self.cstore.unused_externs.push(name_interned);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let diag = match self.sess.opts.extern_dep_specs.get(name) {
|
let diag = match self.sess.opts.extern_dep_specs.get(name) {
|
||||||
Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
|
Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
|
||||||
None => {
|
None => {
|
||||||
|
@ -918,7 +942,6 @@ impl<'a> CrateLoader<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
unused_externs.push(name as &str);
|
|
||||||
self.sess.parse_sess.buffer_lint_with_diagnostic(
|
self.sess.parse_sess.buffer_lint_with_diagnostic(
|
||||||
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
|
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
|
||||||
span,
|
span,
|
||||||
|
@ -931,9 +954,6 @@ impl<'a> CrateLoader<'a> {
|
||||||
diag,
|
diag,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if self.sess.opts.json_unused_externs {
|
|
||||||
self.sess.parse_sess.span_diagnostic.emit_unused_externs(&unused_externs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn postprocess(&mut self, krate: &ast::Crate) {
|
pub fn postprocess(&mut self, krate: &ast::Crate) {
|
||||||
|
@ -941,9 +961,9 @@ impl<'a> CrateLoader<'a> {
|
||||||
self.inject_allocator_crate(krate);
|
self.inject_allocator_crate(krate);
|
||||||
self.inject_panic_runtime(krate);
|
self.inject_panic_runtime(krate);
|
||||||
|
|
||||||
info!("{:?}", CrateDump(&self.cstore));
|
|
||||||
|
|
||||||
self.report_unused_deps(krate);
|
self.report_unused_deps(krate);
|
||||||
|
|
||||||
|
info!("{:?}", CrateDump(&self.cstore));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_extern_crate(
|
pub fn process_extern_crate(
|
||||||
|
|
|
@ -188,8 +188,23 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
|
||||||
.map(|v| (*v).clone())
|
.map(|v| (*v).clone())
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
unused_extern_names.sort();
|
unused_extern_names.sort();
|
||||||
let unused_extern_json =
|
// Take the most severe lint level
|
||||||
serde_json::to_string(&UnusedExterns { unused_extern_names }).unwrap();
|
let lint_level = unused_extern_reports
|
||||||
|
.iter()
|
||||||
|
.map(|uexts| uexts.lint_level.as_str())
|
||||||
|
.max_by_key(|v| match *v {
|
||||||
|
"warn" => 1,
|
||||||
|
"deny" => 2,
|
||||||
|
"forbid" => 3,
|
||||||
|
// The allow lint level is not expected,
|
||||||
|
// as if allow is specified, no message
|
||||||
|
// is to be emitted.
|
||||||
|
v => unreachable!("Invalid lint level '{}'", v),
|
||||||
|
})
|
||||||
|
.unwrap_or("warn")
|
||||||
|
.to_string();
|
||||||
|
let uext = UnusedExterns { lint_level, unused_extern_names };
|
||||||
|
let unused_extern_json = serde_json::to_string(&uext).unwrap();
|
||||||
eprintln!("{}", unused_extern_json);
|
eprintln!("{}", unused_extern_json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,6 +280,8 @@ impl DirState {
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
struct UnusedExterns {
|
struct UnusedExterns {
|
||||||
|
/// Lint level of the unused_crate_dependencies lint
|
||||||
|
lint_level: String,
|
||||||
/// List of unused externs by their names.
|
/// List of unused externs by their names.
|
||||||
unused_extern_names: Vec<String>,
|
unused_extern_names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
@ -317,6 +334,7 @@ fn run_test(
|
||||||
compiler.arg("--error-format=json");
|
compiler.arg("--error-format=json");
|
||||||
compiler.arg("--json").arg("unused-externs");
|
compiler.arg("--json").arg("unused-externs");
|
||||||
compiler.arg("-Z").arg("unstable-options");
|
compiler.arg("-Z").arg("unstable-options");
|
||||||
|
compiler.arg("-W").arg("unused_crate_dependencies");
|
||||||
}
|
}
|
||||||
for lib_str in &options.lib_strs {
|
for lib_str in &options.lib_strs {
|
||||||
compiler.arg("-L").arg(&lib_str);
|
compiler.arg("-L").arg(&lib_str);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue