Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
est31 committed Mar 8, 2021
1 parent 13371b5 commit 3a62eb7
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 19 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/emitter.rs
Expand Up @@ -196,7 +196,7 @@ pub trait Emitter {
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}

/// 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"
fn should_show_explain(&self) -> bool {
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_errors/src/json.rs
Expand Up @@ -159,8 +159,8 @@ impl Emitter for JsonEmitter {
}
}

fn emit_unused_externs(&mut self, unused_externs: &[&str]) {
let data = UnusedExterns { unused_extern_names: unused_externs };
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
let data = UnusedExterns { lint_level, unused_extern_names: unused_externs };
let result = if self.pretty {
writeln!(&mut self.dst, "{}", as_pretty_json(&data))
} else {
Expand Down Expand Up @@ -336,9 +336,11 @@ struct FutureIncompatReport {
}

#[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.
unused_extern_names: &'a [&'b str],
unused_extern_names: &'b [&'c str],
}

impl Diagnostic {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_errors/src/lib.rs
Expand Up @@ -767,8 +767,8 @@ impl Handler {
self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
}

pub fn emit_unused_externs(&self, unused_externs: &[&str]) {
self.inner.borrow_mut().emit_unused_externs(unused_externs)
pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) {
self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs)
}

pub fn delay_as_bug(&self, diagnostic: Diagnostic) {
Expand Down Expand Up @@ -845,8 +845,8 @@ impl HandlerInner {
self.emitter.emit_artifact_notification(path, artifact_type);
}

fn emit_unused_externs(&mut self, unused_externs: &[&str]) {
self.emitter.emit_unused_externs(unused_externs);
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
self.emitter.emit_unused_externs(lint_level, unused_externs);
}

fn treat_err_as_bug(&self) -> bool {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_interface/src/passes.rs
Expand Up @@ -17,6 +17,7 @@ use rustc_hir::definitions::Definitions;
use rustc_hir::Crate;
use rustc_index::vec::IndexVec;
use rustc_lint::LintStore;
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::middle;
Expand Down Expand Up @@ -836,6 +837,12 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
});

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, _)| {
Expand Down
36 changes: 28 additions & 8 deletions compiler/rustc_metadata/src/creader.rs
Expand Up @@ -46,6 +46,9 @@ pub struct CStore {
/// This map is used to verify we get no hash conflicts between
/// `StableCrateId` values.
stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,

/// Unused externs of the crate
unused_externs: Vec<Symbol>,
}

pub struct CrateLoader<'a> {
Expand Down Expand Up @@ -190,6 +193,21 @@ impl CStore {
crate fn has_global_allocator(&self) -> bool {
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> {
Expand Down Expand Up @@ -217,6 +235,7 @@ impl<'a> CrateLoader<'a> {
allocator_kind: None,
has_global_allocator: false,
stable_crate_ids,
unused_externs: Vec::new(),
},
used_extern_options: Default::default(),
}
Expand Down Expand Up @@ -893,18 +912,23 @@ impl<'a> CrateLoader<'a> {
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();
let mut unused_externs = Vec::new();
// Complain about anything left over
for (name, entry) in self.sess.opts.externs.iter() {
if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
// Don't worry about pathless `--extern foo` sysroot references
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;
}

// 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) {
Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
None => {
Expand All @@ -918,7 +942,6 @@ impl<'a> CrateLoader<'a> {
)
}
};
unused_externs.push(name as &str);
self.sess.parse_sess.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
span,
Expand All @@ -931,19 +954,16 @@ impl<'a> CrateLoader<'a> {
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) {
self.inject_profiler_runtime(krate);
self.inject_allocator_crate(krate);
self.inject_panic_runtime(krate);

info!("{:?}", CrateDump(&self.cstore));

self.report_unused_deps(krate);

info!("{:?}", CrateDump(&self.cstore));
}

pub fn process_extern_crate(
Expand Down
22 changes: 20 additions & 2 deletions src/librustdoc/doctest.rs
Expand Up @@ -188,8 +188,23 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
.map(|v| (*v).clone())
.collect::<Vec<String>>();
unused_extern_names.sort();
let unused_extern_json =
serde_json::to_string(&UnusedExterns { unused_extern_names }).unwrap();
// Take the most severe lint level
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);
}
}
Expand Down Expand Up @@ -265,6 +280,8 @@ impl DirState {

#[derive(serde::Serialize, serde::Deserialize)]
struct UnusedExterns {
/// Lint level of the unused_crate_dependencies lint
lint_level: String,
/// List of unused externs by their names.
unused_extern_names: Vec<String>,
}
Expand Down Expand Up @@ -317,6 +334,7 @@ fn run_test(
compiler.arg("--error-format=json");
compiler.arg("--json").arg("unused-externs");
compiler.arg("-Z").arg("unstable-options");
compiler.arg("-W").arg("unused_crate_dependencies");
}
for lib_str in &options.lib_strs {
compiler.arg("-L").arg(&lib_str);
Expand Down

0 comments on commit 3a62eb7

Please sign in to comment.