about summary refs log tree commit diff
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2020-08-10 01:57:35 +0200
committerest31 <MTest31@outlook.com>2021-03-08 08:18:46 +0100
commit3a62eb74db63f1b49d5e00c32192498abaf1640f (patch)
treec2a613beba8ecc96f290450a442fc654fb1549b9
parent13371b59ee918445ede03cebb741539db807e0e7 (diff)
downloadrust-3a62eb74db63f1b49d5e00c32192498abaf1640f.tar.gz
rust-3a62eb74db63f1b49d5e00c32192498abaf1640f.zip
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
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/json.rs10
-rw-r--r--compiler/rustc_errors/src/lib.rs8
-rw-r--r--compiler/rustc_interface/src/passes.rs7
-rw-r--r--compiler/rustc_metadata/src/creader.rs36
-rw-r--r--src/librustdoc/doctest.rs22
6 files changed, 66 insertions, 19 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index dbb71d52e49..2b6dec905f1 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -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 {
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index a1ab98f766e..8511b51e3bf 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -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 {
@@ -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 {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 5720e98abc8..533c32b32c6 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -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) {
@@ -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 {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 5217066bbef..717f4d5a3ba 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -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;
@@ -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, _)| {
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 7b34374032c..9e3f121378c 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -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> {
@@ -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> {
@@ -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(),
         }
@@ -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 => {
@@ -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,
@@ -931,9 +954,6 @@ 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) {
@@ -941,9 +961,9 @@ impl<'a> CrateLoader<'a> {
         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(
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 50cdf46ce4f..116b3aad61e 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -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);
         }
     }
@@ -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>,
 }
@@ -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);