Skip to content

Commit 3a62eb7

Browse files
committed
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
1 parent 13371b5 commit 3a62eb7

File tree

6 files changed

+66
-19
lines changed

6 files changed

+66
-19
lines changed

compiler/rustc_errors/src/emitter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ pub trait Emitter {
196196
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
197197

198198
/// Emit list of unused externs
199-
fn emit_unused_externs(&mut self, _unused_externs: &[&str]) {}
199+
fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {}
200200

201201
/// Checks if should show explanations about "rustc --explain"
202202
fn should_show_explain(&self) -> bool {

compiler/rustc_errors/src/json.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ impl Emitter for JsonEmitter {
159159
}
160160
}
161161

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

338338
#[derive(Encodable)]
339-
struct UnusedExterns<'a, 'b> {
339+
struct UnusedExterns<'a, 'b, 'c> {
340+
/// The severity level of the unused dependencies lint
341+
lint_level: &'a str,
340342
/// List of unused externs by their names.
341-
unused_extern_names: &'a [&'b str],
343+
unused_extern_names: &'b [&'c str],
342344
}
343345

344346
impl Diagnostic {

compiler/rustc_errors/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,8 @@ impl Handler {
767767
self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
768768
}
769769

770-
pub fn emit_unused_externs(&self, unused_externs: &[&str]) {
771-
self.inner.borrow_mut().emit_unused_externs(unused_externs)
770+
pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) {
771+
self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs)
772772
}
773773

774774
pub fn delay_as_bug(&self, diagnostic: Diagnostic) {
@@ -845,8 +845,8 @@ impl HandlerInner {
845845
self.emitter.emit_artifact_notification(path, artifact_type);
846846
}
847847

848-
fn emit_unused_externs(&mut self, unused_externs: &[&str]) {
849-
self.emitter.emit_unused_externs(unused_externs);
848+
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
849+
self.emitter.emit_unused_externs(lint_level, unused_externs);
850850
}
851851

852852
fn treat_err_as_bug(&self) -> bool {

compiler/rustc_interface/src/passes.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_hir::definitions::Definitions;
1717
use rustc_hir::Crate;
1818
use rustc_index::vec::IndexVec;
1919
use rustc_lint::LintStore;
20+
use rustc_metadata::creader::CStore;
2021
use rustc_middle::arena::Arena;
2122
use rustc_middle::dep_graph::DepGraph;
2223
use rustc_middle::middle;
@@ -836,6 +837,12 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
836837
});
837838

838839
sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
840+
841+
let cstore = tcx
842+
.cstore_as_any()
843+
.downcast_ref::<CStore>()
844+
.expect("`tcx.cstore` is not a `CStore`");
845+
cstore.report_unused_deps(tcx);
839846
},
840847
{
841848
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {

compiler/rustc_metadata/src/creader.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ pub struct CStore {
4646
/// This map is used to verify we get no hash conflicts between
4747
/// `StableCrateId` values.
4848
stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
49+
50+
/// Unused externs of the crate
51+
unused_externs: Vec<Symbol>,
4952
}
5053

5154
pub struct CrateLoader<'a> {
@@ -190,6 +193,21 @@ impl CStore {
190193
crate fn has_global_allocator(&self) -> bool {
191194
self.has_global_allocator
192195
}
196+
197+
pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
198+
let level = tcx
199+
.lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID)
200+
.0;
201+
if level != lint::Level::Allow && tcx.sess.opts.json_unused_externs {
202+
let unused_externs =
203+
self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>();
204+
let unused_externs = unused_externs.iter().map(String::as_str).collect::<Vec<&str>>();
205+
tcx.sess
206+
.parse_sess
207+
.span_diagnostic
208+
.emit_unused_externs(level.as_str(), &unused_externs);
209+
}
210+
}
193211
}
194212

195213
impl<'a> CrateLoader<'a> {
@@ -217,6 +235,7 @@ impl<'a> CrateLoader<'a> {
217235
allocator_kind: None,
218236
has_global_allocator: false,
219237
stable_crate_ids,
238+
unused_externs: Vec::new(),
220239
},
221240
used_extern_options: Default::default(),
222241
}
@@ -893,18 +912,23 @@ impl<'a> CrateLoader<'a> {
893912
fn report_unused_deps(&mut self, krate: &ast::Crate) {
894913
// Make a point span rather than covering the whole file
895914
let span = krate.span.shrink_to_lo();
896-
let mut unused_externs = Vec::new();
897915
// Complain about anything left over
898916
for (name, entry) in self.sess.opts.externs.iter() {
899917
if let ExternLocation::FoundInLibrarySearchDirectories = entry.location {
900918
// Don't worry about pathless `--extern foo` sysroot references
901919
continue;
902920
}
903-
if self.used_extern_options.contains(&Symbol::intern(name)) {
921+
let name_interned = Symbol::intern(name);
922+
if self.used_extern_options.contains(&name_interned) {
904923
continue;
905924
}
906925

907926
// Got a real unused --extern
927+
if self.sess.opts.json_unused_externs {
928+
self.cstore.unused_externs.push(name_interned);
929+
continue;
930+
}
931+
908932
let diag = match self.sess.opts.extern_dep_specs.get(name) {
909933
Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
910934
None => {
@@ -918,7 +942,6 @@ impl<'a> CrateLoader<'a> {
918942
)
919943
}
920944
};
921-
unused_externs.push(name as &str);
922945
self.sess.parse_sess.buffer_lint_with_diagnostic(
923946
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
924947
span,
@@ -931,19 +954,16 @@ impl<'a> CrateLoader<'a> {
931954
diag,
932955
);
933956
}
934-
if self.sess.opts.json_unused_externs {
935-
self.sess.parse_sess.span_diagnostic.emit_unused_externs(&unused_externs);
936-
}
937957
}
938958

939959
pub fn postprocess(&mut self, krate: &ast::Crate) {
940960
self.inject_profiler_runtime(krate);
941961
self.inject_allocator_crate(krate);
942962
self.inject_panic_runtime(krate);
943963

944-
info!("{:?}", CrateDump(&self.cstore));
945-
946964
self.report_unused_deps(krate);
965+
966+
info!("{:?}", CrateDump(&self.cstore));
947967
}
948968

949969
pub fn process_extern_crate(

src/librustdoc/doctest.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,23 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
188188
.map(|v| (*v).clone())
189189
.collect::<Vec<String>>();
190190
unused_extern_names.sort();
191-
let unused_extern_json =
192-
serde_json::to_string(&UnusedExterns { unused_extern_names }).unwrap();
191+
// Take the most severe lint level
192+
let lint_level = unused_extern_reports
193+
.iter()
194+
.map(|uexts| uexts.lint_level.as_str())
195+
.max_by_key(|v| match *v {
196+
"warn" => 1,
197+
"deny" => 2,
198+
"forbid" => 3,
199+
// The allow lint level is not expected,
200+
// as if allow is specified, no message
201+
// is to be emitted.
202+
v => unreachable!("Invalid lint level '{}'", v),
203+
})
204+
.unwrap_or("warn")
205+
.to_string();
206+
let uext = UnusedExterns { lint_level, unused_extern_names };
207+
let unused_extern_json = serde_json::to_string(&uext).unwrap();
193208
eprintln!("{}", unused_extern_json);
194209
}
195210
}
@@ -265,6 +280,8 @@ impl DirState {
265280

266281
#[derive(serde::Serialize, serde::Deserialize)]
267282
struct UnusedExterns {
283+
/// Lint level of the unused_crate_dependencies lint
284+
lint_level: String,
268285
/// List of unused externs by their names.
269286
unused_extern_names: Vec<String>,
270287
}
@@ -317,6 +334,7 @@ fn run_test(
317334
compiler.arg("--error-format=json");
318335
compiler.arg("--json").arg("unused-externs");
319336
compiler.arg("-Z").arg("unstable-options");
337+
compiler.arg("-W").arg("unused_crate_dependencies");
320338
}
321339
for lib_str in &options.lib_strs {
322340
compiler.arg("-L").arg(&lib_str);

0 commit comments

Comments
 (0)