From 7cec516ef9a60aec740725ca35050b5345d95818 Mon Sep 17 00:00:00 2001
From: Josh Triplett <josh@joshtriplett.org>
Date: Sat, 18 Aug 2018 16:20:25 -0700
Subject: [PATCH] Don't emit "unused extern crate" warnings for `extern crate
 foo as _;`

When importing a crate and renaming it to an underscore-prefixed name,
suppress "unused extern crate" warnings (but not idiom lints).
---
 src/librustc_typeck/check_unused.rs           | 33 +++++++++++--------
 .../ui/rfc-2166-underscore-imports/basic.rs   |  2 +-
 .../rfc-2166-underscore-imports/basic.stderr  | 12 -------
 3 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index d7aec1d62cdd6..fa152b386a825 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -133,19 +133,21 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
 
         // If the crate is fully unused, we suggest removing it altogether.
         // We do this in any edition.
-        if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
-            assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
-            let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
-            let id = tcx.hir.hir_to_node_id(hir_id);
-            let msg = "unused extern crate";
-            tcx.struct_span_lint_node(lint, id, span, msg)
-                .span_suggestion_short_with_applicability(
-                    span,
-                    "remove it",
-                    String::new(),
-                    Applicability::MachineApplicable)
-                .emit();
-            continue;
+        if extern_crate.warn_if_unused {
+            if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
+                assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
+                let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
+                let id = tcx.hir.hir_to_node_id(hir_id);
+                let msg = "unused extern crate";
+                tcx.struct_span_lint_node(lint, id, span, msg)
+                    .span_suggestion_short_with_applicability(
+                        span,
+                        "remove it",
+                        String::new(),
+                        Applicability::MachineApplicable)
+                    .emit();
+                continue;
+            }
         }
 
         // If we are not in Rust 2018 edition, then we don't make any further
@@ -202,6 +204,10 @@ struct ExternCrateToLint {
     /// crate_name`), and -- perhaps surprisingly -- this stores the
     /// *original* name (`item.name` will contain the new name)
     orig_name: Option<ast::Name>,
+
+    /// if `false`, the original name started with `_`, so we shouldn't lint
+    /// about it going unused (but we should still emit idiom lints).
+    warn_if_unused: bool,
 }
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
@@ -213,6 +219,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
                     def_id: extern_crate_def_id,
                     span: item.span,
                     orig_name,
+                    warn_if_unused: !item.name.as_str().starts_with('_'),
                 }
             );
         }
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs
index 89771be7bc84f..104bd9e166c79 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs
@@ -30,7 +30,7 @@ mod m {
 mod unused {
     use m::Tr1 as _; //~ WARN unused import
     use S as _; //~ WARN unused import
-    extern crate core as _; //~ WARN unused extern crate
+    extern crate core as _; // OK
 }
 
 mod outer {
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
index c12c74b50e264..2be0317019d3c 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.stderr
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr
@@ -16,15 +16,3 @@ warning: unused import: `S as _`
 LL |     use S as _; //~ WARN unused import
    |         ^^^^^^
 
-warning: unused extern crate
-  --> $DIR/basic.rs:33:5
-   |
-LL |     extern crate core as _; //~ WARN unused extern crate
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-   |
-note: lint level defined here
-  --> $DIR/basic.rs:14:25
-   |
-LL | #![warn(unused_imports, unused_extern_crates)]
-   |                         ^^^^^^^^^^^^^^^^^^^^
-