diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs
index 74c80a08b12ab..ee1799fad8e15 100644
--- a/src/liballoc/borrow.rs
+++ b/src/liballoc/borrow.rs
@@ -135,7 +135,7 @@ impl<T> ToOwned for T
 /// Another example showing how to keep `Cow` in a struct:
 ///
 /// ```
-/// use std::borrow::{Cow, ToOwned};
+/// use std::borrow::Cow;
 ///
 /// struct Items<'a, X: 'a> where [X]: ToOwned<Owned = Vec<X>> {
 ///     values: Cow<'a, [X]>,
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 753f10e6a0ad0..80dd51acc9eee 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -702,8 +702,6 @@ impl<T> RefCell<T> {
     /// Replaces the wrapped value with a new one computed from `f`, returning
     /// the old value, without deinitializing either one.
     ///
-    /// This function corresponds to [`std::mem::replace`](../mem/fn.replace.html).
-    ///
     /// # Panics
     ///
     /// Panics if the value is currently borrowed.
@@ -711,7 +709,6 @@ impl<T> RefCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(refcell_replace_swap)]
     /// use std::cell::RefCell;
     /// let cell = RefCell::new(5);
     /// let old_value = cell.replace_with(|&mut old| old + 1);
@@ -719,7 +716,7 @@ impl<T> RefCell<T> {
     /// assert_eq!(cell, RefCell::new(6));
     /// ```
     #[inline]
-    #[unstable(feature = "refcell_replace_swap", issue="43570")]
+    #[stable(feature = "refcell_replace_swap", since="1.35.0")]
     pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, f: F) -> T {
         let mut_borrow = &mut *self.borrow_mut();
         let replacement = f(mut_borrow);
@@ -1421,7 +1418,6 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 ///
 /// ```
 /// use std::cell::UnsafeCell;
-/// use std::marker::Sync;
 ///
 /// # #[allow(dead_code)]
 /// struct NotThreadSafe<T> {
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 2ed25a341021b..5e0dbb7ab2f12 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -16,7 +16,6 @@
 #![feature(pattern)]
 #![feature(range_is_empty)]
 #![feature(raw)]
-#![feature(refcell_replace_swap)]
 #![feature(slice_patterns)]
 #![feature(sort_internals)]
 #![feature(specialization)]
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index e905c3688518b..b87343b43c9f9 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -45,7 +45,6 @@
 #![feature(proc_macro_internals)]
 #![feature(optin_builtin_traits)]
 #![feature(range_is_empty)]
-#![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_attrs)]
 #![feature(slice_patterns)]
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 10a5c1479fa6a..2d8a2c6321fa8 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -483,6 +483,7 @@ pub enum BuiltinLintDiagnostics {
     UnknownCrateTypes(Span, String, String),
     UnusedImports(String, Vec<(Span, String)>),
     NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span },
+    RedundantImport(Vec<(Span, bool)>, ast::Ident),
 }
 
 impl BuiltinLintDiagnostics {
@@ -579,6 +580,15 @@ impl BuiltinLintDiagnostics {
                 db.span_label(outer_impl_trait_span, "outer `impl Trait`");
                 db.span_label(inner_impl_trait_span, "nested `impl Trait` here");
             }
+            BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
+                for (span, is_imported) in spans {
+                    let introduced = if is_imported { "imported" } else { "defined" };
+                    db.span_label(
+                        span,
+                        format!("the item `{}` is already {} here", ident, introduced)
+                    );
+                }
+            }
         }
     }
 }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 01e57273e54a1..4f630fe9a3911 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -707,7 +707,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 adjustment::Adjust::NeverToAny |
                 adjustment::Adjust::ReifyFnPointer |
                 adjustment::Adjust::UnsafeFnPointer |
-                adjustment::Adjust::ClosureFnPointer |
+                adjustment::Adjust::ClosureFnPointer(_) |
                 adjustment::Adjust::MutToConstPointer |
                 adjustment::Adjust::Unsize => {
                     // Creating a closure/fn-pointer or unsizing consumes
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 4b169dea06c7c..1a3fef18404e3 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -621,7 +621,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             adjustment::Adjust::NeverToAny |
             adjustment::Adjust::ReifyFnPointer |
             adjustment::Adjust::UnsafeFnPointer |
-            adjustment::Adjust::ClosureFnPointer |
+            adjustment::Adjust::ClosureFnPointer(_) |
             adjustment::Adjust::MutToConstPointer |
             adjustment::Adjust::Borrow(_) |
             adjustment::Adjust::Unsize => {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index d35ee1e57d5ce..7b419e306db60 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2247,8 +2247,9 @@ pub enum CastKind {
     /// Converts unique, zero-sized type for a fn to fn()
     ReifyFnPointer,
 
-    /// Converts non capturing closure to fn()
-    ClosureFnPointer,
+    /// Converts non capturing closure to fn() or unsafe fn().
+    /// It cannot convert a closure that requires unsafe.
+    ClosureFnPointer(hir::Unsafety),
 
     /// Converts safe fn() to unsafe fn()
     UnsafeFnPointer,
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index f9149ce0f6e6b..c2ef08c4c40fe 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -62,8 +62,9 @@ pub enum Adjust<'tcx> {
     /// Go from a safe fn pointer to an unsafe fn pointer.
     UnsafeFnPointer,
 
-    /// Go from a non-capturing closure to an fn pointer.
-    ClosureFnPointer,
+    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
+    /// It cannot convert a closure that requires unsafe.
+    ClosureFnPointer(hir::Unsafety),
 
     /// Go from a mut raw pointer to a const raw pointer.
     MutToConstPointer,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index ea003ba1ac701..77330c7a9d1b2 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2441,7 +2441,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// type with the same signature. Detuples and so forth -- so
     /// e.g., if we have a sig with `Fn<(u32, i32)>` then you would get
     /// a `fn(u32, i32)`.
-    pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
+    /// `unsafety` determines the unsafety of the `fn` type. If you pass
+    /// `hir::Unsafety::Unsafe` in the previous example, then you would get
+    /// an `unsafe fn (u32, i32)`.
+    /// It cannot convert a closure that requires unsafe.
+    pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>, unsafety: hir::Unsafety) -> Ty<'tcx> {
         let converted_sig = sig.map_bound(|s| {
             let params_iter = match s.inputs()[0].sty {
                 ty::Tuple(params) => {
@@ -2453,7 +2457,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 params_iter,
                 s.output(),
                 s.c_variadic,
-                hir::Unsafety::Normal,
+                unsafety,
                 abi::Abi::Rust,
             )
         });
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 7d2b21b9aecda..e01b50113b9fe 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -913,11 +913,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                             }
 
                             return Ok(tcx.intern_layout(LayoutDetails {
-                                variants: Variants::NicheFilling {
-                                    dataful_variant: i,
-                                    niche_variants,
-                                    niche: niche_scalar,
-                                    niche_start,
+                                variants: Variants::Multiple {
+                                    discr: niche_scalar,
+                                    discr_kind: DiscriminantKind::Niche {
+                                        dataful_variant: i,
+                                        niche_variants,
+                                        niche_start,
+                                    },
                                     variants: st,
                                 },
                                 fields: FieldPlacement::Arbitrary {
@@ -1137,8 +1139,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
 
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Tagged {
-                        tag,
+                    variants: Variants::Multiple {
+                        discr: tag,
+                        discr_kind: DiscriminantKind::Tag,
                         variants: layout_variants,
                     },
                     fields: FieldPlacement::Arbitrary {
@@ -1293,8 +1296,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
             }
 
-            Variants::NicheFilling { .. } |
-            Variants::Tagged { .. } => {
+            Variants::Multiple { ref discr, ref discr_kind, .. } => {
                 debug!("print-type-size `{:#?}` adt general variants def {}",
                        layout.ty, adt_def.variants.len());
                 let variant_infos: Vec<_> =
@@ -1306,8 +1308,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                                            layout.for_variant(self, i))
                     })
                     .collect();
-                record(adt_kind.into(), adt_packed, match layout.variants {
-                    Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
+                record(adt_kind.into(), adt_packed, match discr_kind {
+                    DiscriminantKind::Tag => Some(discr.value.size(self)),
                     _ => None
                 }, variant_infos);
             }
@@ -1627,8 +1629,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                 })
             }
 
-            Variants::NicheFilling { ref variants, .. } |
-            Variants::Tagged { ref variants, .. } => {
+            Variants::Multiple { ref variants, .. } => {
                 &variants[variant_index]
             }
         };
@@ -1735,8 +1736,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                     }
 
                     // Discriminant field for enums (where applicable).
-                    Variants::Tagged { tag: ref discr, .. } |
-                    Variants::NicheFilling { niche: ref discr, .. } => {
+                    Variants::Multiple { ref discr, .. } => {
                         assert_eq!(i, 0);
                         let layout = LayoutDetails::scalar(cx, discr.clone());
                         return MaybeResult::from_ok(TyLayout {
@@ -1881,26 +1881,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
             Single { index } => {
                 index.hash_stable(hcx, hasher);
             }
-            Tagged {
-                ref tag,
+            Multiple {
+                ref discr,
+                ref discr_kind,
                 ref variants,
             } => {
-                tag.hash_stable(hcx, hasher);
+                discr.hash_stable(hcx, hasher);
+                discr_kind.hash_stable(hcx, hasher);
                 variants.hash_stable(hcx, hasher);
             }
-            NicheFilling {
+        }
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use crate::ty::layout::DiscriminantKind::*;
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            Tag => {}
+            Niche {
                 dataful_variant,
                 ref niche_variants,
-                ref niche,
                 niche_start,
-                ref variants,
             } => {
                 dataful_variant.hash_stable(hcx, hasher);
                 niche_variants.start().hash_stable(hcx, hasher);
                 niche_variants.end().hash_stable(hcx, hasher);
-                niche.hash_stable(hcx, hasher);
                 niche_start.hash_stable(hcx, hasher);
-                variants.hash_stable(hcx, hasher);
             }
         }
     }
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 1b4c36b8b06c3..05d80f9203f14 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -777,7 +777,6 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
                                                  value: &V)
                                                  -> Result<(), E::Error>
     {
-        use crate::ty::codec::TyEncoder;
         let start_pos = self.position();
 
         tag.encode(self)?;
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index cbdda73269282..4f1fda3f4e534 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -630,8 +630,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> {
                 Some(ty::adjustment::Adjust::ReifyFnPointer),
             ty::adjustment::Adjust::UnsafeFnPointer =>
                 Some(ty::adjustment::Adjust::UnsafeFnPointer),
-            ty::adjustment::Adjust::ClosureFnPointer =>
-                Some(ty::adjustment::Adjust::ClosureFnPointer),
+            ty::adjustment::Adjust::ClosureFnPointer(unsafety) =>
+                Some(ty::adjustment::Adjust::ClosureFnPointer(unsafety)),
             ty::adjustment::Adjust::MutToConstPointer =>
                 Some(ty::adjustment::Adjust::MutToConstPointer),
             ty::adjustment::Adjust::Unsize =>
@@ -1187,7 +1187,7 @@ EnumTypeFoldableImpl! {
         (ty::adjustment::Adjust::NeverToAny),
         (ty::adjustment::Adjust::ReifyFnPointer),
         (ty::adjustment::Adjust::UnsafeFnPointer),
-        (ty::adjustment::Adjust::ClosureFnPointer),
+        (ty::adjustment::Adjust::ClosureFnPointer)(a),
         (ty::adjustment::Adjust::MutToConstPointer),
         (ty::adjustment::Adjust::Unsize),
         (ty::adjustment::Adjust::Deref)(a),
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 71e7535313f77..77fa34e74dd70 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -77,9 +77,15 @@ pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     if cx.sess().instrument_mcount() {
         // Similar to `clang -pg` behavior. Handled by the
         // `post-inline-ee-instrument` LLVM pass.
+
+        // The function name varies on platforms.
+        // See test/CodeGen/mcount.c in clang.
+        let mcount_name = CString::new(
+            cx.sess().target.target.options.target_mcount.as_str().as_bytes()).unwrap();
+
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
-            const_cstr!("instrument-function-entry-inlined"), const_cstr!("mcount"));
+            const_cstr!("instrument-function-entry-inlined"), &mcount_name);
     }
 }
 
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index fc79e868fb4bf..f6956bd5736eb 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -372,7 +372,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     // Returns a Value of the "eh_unwind_resume" lang item if one is defined,
     // otherwise declares it as an external function.
     fn eh_unwind_resume(&self) -> &'ll Value {
-        use crate::attributes;
         let unwresume = &self.eh_unwind_resume;
         if let Some(llfn) = unwresume.get() {
             return llfn;
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index e50839cd5983c..e549b120da979 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -1246,7 +1246,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     }
                 ]
             }
-            layout::Variants::Tagged { ref variants, .. } => {
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ref variants,
+                ..
+            } => {
                 let discriminant_info = if fallback {
                     RegularDiscriminant(self.discriminant_type_metadata
                                         .expect(""))
@@ -1288,12 +1292,14 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     }
                 }).collect()
             }
-            layout::Variants::NicheFilling {
-                ref niche_variants,
-                niche_start,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche {
+                    ref niche_variants,
+                    niche_start,
+                    dataful_variant,
+                },
+                ref discr,
                 ref variants,
-                dataful_variant,
-                ref niche,
             } => {
                 if fallback {
                     let variant = self.layout.for_variant(cx, dataful_variant);
@@ -1380,7 +1386,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                             let value = (i.as_u32() as u128)
                                 .wrapping_sub(niche_variants.start().as_u32() as u128)
                                 .wrapping_add(niche_start);
-                            let value = truncate(value, niche.value.size(cx));
+                            let value = truncate(value, discr.value.size(cx));
+                            // NOTE(eddyb) do *NOT* remove this assert, until
+                            // we pass the full 128-bit value to LLVM, otherwise
+                            // truncation will be silent and remain undetected.
+                            assert_eq!(value as u64 as u128, value);
                             Some(value as u64)
                         };
 
@@ -1597,8 +1607,11 @@ fn prepare_enum_metadata(
     let layout = cx.layout_of(enum_type);
 
     match (&layout.abi, &layout.variants) {
-        (&layout::Abi::Scalar(_), &layout::Variants::Tagged {ref tag, .. }) =>
-            return FinalMetadata(discriminant_type_metadata(tag.value)),
+        (&layout::Abi::Scalar(_), &layout::Variants::Multiple {
+            discr_kind: layout::DiscriminantKind::Tag,
+            ref discr,
+            ..
+        }) => return FinalMetadata(discriminant_type_metadata(discr.value)),
         _ => {}
     }
 
@@ -1610,9 +1623,16 @@ fn prepare_enum_metadata(
     if use_enum_fallback(cx) {
         let discriminant_type_metadata = match layout.variants {
             layout::Variants::Single { .. } |
-            layout::Variants::NicheFilling { .. } => None,
-            layout::Variants::Tagged { ref tag, .. } => {
-                Some(discriminant_type_metadata(tag.value))
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche { .. },
+                ..
+            } => None,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ref discr,
+                ..
+            } => {
+                Some(discriminant_type_metadata(discr.value))
             }
         };
 
@@ -1647,16 +1667,20 @@ fn prepare_enum_metadata(
         );
     }
 
-    let discriminator_metadata = match &layout.variants {
+    let discriminator_metadata = match layout.variants {
         // A single-variant enum has no discriminant.
-        &layout::Variants::Single { .. } => None,
+        layout::Variants::Single { .. } => None,
 
-        &layout::Variants::NicheFilling { ref niche, .. } => {
+        layout::Variants::Multiple {
+            discr_kind: layout::DiscriminantKind::Niche { .. },
+            ref discr,
+            ..
+        } => {
             // Find the integer type of the correct size.
-            let size = niche.value.size(cx);
-            let align = niche.value.align(cx);
+            let size = discr.value.size(cx);
+            let align = discr.value.align(cx);
 
-            let discr_type = match niche.value {
+            let discr_type = match discr.value {
                 layout::Int(t, _) => t,
                 layout::Float(layout::FloatTy::F32) => Integer::I32,
                 layout::Float(layout::FloatTy::F64) => Integer::I64,
@@ -1679,8 +1703,12 @@ fn prepare_enum_metadata(
             }
         },
 
-        &layout::Variants::Tagged { ref tag, .. } => {
-            let discr_type = tag.value.to_ty(cx.tcx);
+        layout::Variants::Multiple {
+            discr_kind: layout::DiscriminantKind::Tag,
+            ref discr,
+            ..
+        } => {
+            let discr_type = discr.value.to_ty(cx.tcx);
             let (size, align) = cx.size_and_align_of(discr_type);
 
             let discr_metadata = basic_type_metadata(cx, discr_type);
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index fb5624d56078e..020447608eebe 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -452,7 +452,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
 
             _ => {
                 let mut data_variant = match self.variants {
-                    layout::Variants::NicheFilling { dataful_variant, .. } => {
+                    layout::Variants::Multiple {
+                        discr_kind: layout::DiscriminantKind::Niche {
+                            dataful_variant,
+                            ..
+                        },
+                        ..
+                    } => {
                         // Only the niche itself is always initialized,
                         // so only check for a pointer at its offset.
                         //
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index bf2afbbabab96..9ed7e26729f53 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -216,37 +216,36 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
         if self.layout.abi.is_uninhabited() {
             return bx.cx().const_undef(cast_to);
         }
-        match self.layout.variants {
+        let (discr_scalar, discr_kind) = match self.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = self.layout.ty.ty_adt_def().map_or(
                     index.as_u32() as u128,
                     |def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
                 return bx.cx().const_uint_big(cast_to, discr_val);
             }
-            layout::Variants::Tagged { .. } |
-            layout::Variants::NicheFilling { .. } => {},
-        }
+            layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
+                (discr, discr_kind)
+            }
+        };
 
         let discr = self.project_field(bx, 0);
         let lldiscr = bx.load_operand(discr).immediate();
-        match self.layout.variants {
-            layout::Variants::Single { .. } => bug!(),
-            layout::Variants::Tagged { ref tag, .. } => {
-                let signed = match tag.value {
+        match *discr_kind {
+            layout::DiscriminantKind::Tag => {
+                let signed = match discr_scalar.value {
                     // We use `i1` for bytes that are always `0` or `1`,
                     // e.g., `#[repr(i8)] enum E { A, B }`, but we can't
                     // let LLVM interpret the `i1` as signed, because
                     // then `i1 1` (i.e., E::B) is effectively `i8 -1`.
-                    layout::Int(_, signed) => !tag.is_bool() && signed,
+                    layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
                     _ => false
                 };
                 bx.intcast(lldiscr, cast_to, signed)
             }
-            layout::Variants::NicheFilling {
+            layout::DiscriminantKind::Niche {
                 dataful_variant,
                 ref niche_variants,
                 niche_start,
-                ..
             } => {
                 let niche_llty = bx.cx().immediate_backend_type(discr.layout);
                 if niche_variants.start() == niche_variants.end() {
@@ -291,7 +290,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
             layout::Variants::Single { index } => {
                 assert_eq!(index, variant_index);
             }
-            layout::Variants::Tagged { .. } => {
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ..
+            } => {
                 let ptr = self.project_field(bx, 0);
                 let to = self.layout.ty.ty_adt_def().unwrap()
                     .discriminant_for_variant(bx.tcx(), variant_index)
@@ -301,10 +303,12 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
                     ptr.llval,
                     ptr.align);
             }
-            layout::Variants::NicheFilling {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche {
+                    dataful_variant,
+                    ref niche_variants,
+                    niche_start,
+                },
                 ..
             } => {
                 if variant_index != dataful_variant {
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 7a31c5b3950e0..53640284a2ca9 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -193,7 +193,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             }
                         }
                     }
-                    mir::CastKind::ClosureFnPointer => {
+                    mir::CastKind::ClosureFnPointer(_) => {
                         match operand.layout.ty.sty {
                             ty::Closure(def_id, substs) => {
                                 let instance = monomorphize::resolve_closure(
@@ -282,8 +282,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     });
                                 }
                             }
-                            layout::Variants::Tagged { .. } |
-                            layout::Variants::NicheFilling { .. } => {},
+                            layout::Variants::Multiple { .. } => {},
                         }
                         let llval = operand.immediate();
 
@@ -732,7 +731,6 @@ fn cast_int_to_float<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
         // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
         // and for everything else LLVM's uitofp works just fine.
         use rustc_apfloat::ieee::Single;
-        use rustc_apfloat::Float;
         const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
                                             << (Single::MAX_EXP - Single::PRECISION as i16);
         let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs
index 7fb2cb9d39362..efc18d401c082 100644
--- a/src/librustc_codegen_ssa/traits/type_.rs
+++ b/src/librustc_codegen_ssa/traits/type_.rs
@@ -77,7 +77,6 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
     }
 
     fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
-        use syntax_pos::DUMMY_SP;
         if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
             return false;
         }
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 6b4b437930d26..ebbc5a3d3a340 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -155,7 +155,7 @@ impl CodeSuggestion {
     /// Returns the assembled code suggestions and whether they should be shown with an underline.
     pub fn splice_lines(&self, cm: &SourceMapperDyn)
                         -> Vec<(String, Vec<SubstitutionPart>)> {
-        use syntax_pos::{CharPos, Loc, Pos};
+        use syntax_pos::{CharPos, Pos};
 
         fn push_trailing(buf: &mut String,
                          line_opt: Option<&Cow<'_, str>>,
diff --git a/src/librustc_interface/profile/mod.rs b/src/librustc_interface/profile/mod.rs
index d0c8dff207083..2e71d46f4154c 100644
--- a/src/librustc_interface/profile/mod.rs
+++ b/src/librustc_interface/profile/mod.rs
@@ -62,7 +62,6 @@ fn total_duration(traces: &[trace::Rec]) -> Duration {
 fn profile_queries_thread(r: Receiver<ProfileQueriesMsg>) {
     use self::trace::*;
     use std::fs::File;
-    use std::time::{Instant};
 
     let mut profq_msgs: Vec<ProfileQueriesMsg> = vec![];
     let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] };
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 4ad1a00afe97c..494a9bb73ed4b 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -842,51 +842,56 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
             let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
             let t = cx.tcx.type_of(item_def_id);
             let ty = cx.tcx.erase_regions(&t);
-            match cx.layout_of(ty) {
-                Ok(layout) => {
-                    let variants = &layout.variants;
-                    if let layout::Variants::Tagged { ref variants, ref tag, .. } = variants {
-                        let discr_size = tag.value.size(&cx.tcx).bytes();
-
-                        debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
-                               t, layout.size.bytes(), layout);
-
-                        let (largest, slargest, largest_index) = enum_definition.variants
-                            .iter()
-                            .zip(variants)
-                            .map(|(variant, variant_layout)| {
-                                // Subtract the size of the enum discriminant.
-                                let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
-
-                                debug!("- variant `{}` is {} bytes large",
-                                       variant.node.ident,
-                                       bytes);
-                                bytes
-                            })
-                            .enumerate()
-                            .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
-                                (size, l, idx)
-                            } else if size > s {
-                                (l, size, li)
-                            } else {
-                                (l, s, li)
-                            });
-
-                        // We only warn if the largest variant is at least thrice as large as
-                        // the second-largest.
-                        if largest > slargest * 3 && slargest > 0 {
-                            cx.span_lint(VARIANT_SIZE_DIFFERENCES,
-                                            enum_definition.variants[largest_index].span,
-                                            &format!("enum variant is more than three times \
-                                                      larger ({} bytes) than the next largest",
-                                                     largest));
-                        }
-                    }
-                }
+            let layout = match cx.layout_of(ty) {
+                Ok(layout) => layout,
                 Err(ty::layout::LayoutError::Unknown(_)) => return,
                 Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
                     bug!("failed to get layout for `{}`: {}", t, err);
                 }
+            };
+            let (variants, tag) = match layout.variants {
+                layout::Variants::Multiple {
+                    discr_kind: layout::DiscriminantKind::Tag,
+                    ref discr,
+                    ref variants,
+                } => (variants, discr),
+                _ => return,
+            };
+
+            let discr_size = tag.value.size(&cx.tcx).bytes();
+
+            debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
+                   t, layout.size.bytes(), layout);
+
+            let (largest, slargest, largest_index) = enum_definition.variants
+                .iter()
+                .zip(variants)
+                .map(|(variant, variant_layout)| {
+                    // Subtract the size of the enum discriminant.
+                    let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
+
+                    debug!("- variant `{}` is {} bytes large",
+                           variant.node.ident,
+                           bytes);
+                    bytes
+                })
+                .enumerate()
+                .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
+                    (size, l, idx)
+                } else if size > s {
+                    (l, size, li)
+                } else {
+                    (l, s, li)
+                });
+
+            // We only warn if the largest variant is at least thrice as large as
+            // the second-largest.
+            if largest > slargest * 3 && slargest > 0 {
+                cx.span_lint(VARIANT_SIZE_DIFFERENCES,
+                                enum_definition.variants[largest_index].span,
+                                &format!("enum variant is more than three times \
+                                          larger ({} bytes) than the next largest",
+                                         largest));
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index a3561515aaa31..3b559b28f1235 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -1999,14 +1999,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         }
                     }
 
-                    CastKind::ClosureFnPointer => {
+                    CastKind::ClosureFnPointer(unsafety) => {
                         let sig = match op.ty(mir, tcx).sty {
                             ty::Closure(def_id, substs) => {
                                 substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
                             }
                             _ => bug!(),
                         };
-                        let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig);
+                        let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig, *unsafety);
 
                         if let Err(terr) = self.eq_types(
                             ty_fn_ptr_from,
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 9e12a7e6fa931..84f74484e606f 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -162,9 +162,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let source = unpack!(block = this.as_operand(block, scope, source));
                 block.and(Rvalue::Cast(CastKind::UnsafeFnPointer, source, expr.ty))
             }
-            ExprKind::ClosureFnPointer { source } => {
+            ExprKind::ClosureFnPointer { source, unsafety } => {
                 let source = unpack!(block = this.as_operand(block, scope, source));
-                block.and(Rvalue::Cast(CastKind::ClosureFnPointer, source, expr.ty))
+                block.and(Rvalue::Cast(CastKind::ClosureFnPointer(unsafety), source, expr.ty))
             }
             ExprKind::MutToConstPointer { source } => {
                 let source = unpack!(block = this.as_operand(block, scope, source));
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index e4f92f81e9ff6..91113dc2271be 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -81,8 +81,8 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Adjust::UnsafeFnPointer => {
             ExprKind::UnsafeFnPointer { source: expr.to_ref() }
         }
-        Adjust::ClosureFnPointer => {
-            ExprKind::ClosureFnPointer { source: expr.to_ref() }
+        Adjust::ClosureFnPointer(unsafety) => {
+            ExprKind::ClosureFnPointer { source: expr.to_ref(), unsafety }
         }
         Adjust::NeverToAny => {
             ExprKind::NeverToAny { source: expr.to_ref() }
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 3a38876bb6802..a661649db0fd4 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -185,6 +185,7 @@ pub enum ExprKind<'tcx> {
     },
     ClosureFnPointer {
         source: ExprRef<'tcx>,
+        unsafety: hir::Unsafety,
     },
     UnsafeFnPointer {
         source: ExprRef<'tcx>,
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 6c532fce57f0e..622cf00ed86e7 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -427,7 +427,6 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
                 let mut kind = match (lo, hi) {
                     (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
-                        use std::cmp::Ordering;
                         let cmp = compare_const_vals(
                             self.tcx,
                             lo,
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 003c2182d0b45..fe719bff250a8 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -64,8 +64,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                                     dest);
                             }
                         }
-                        layout::Variants::Tagged { .. } |
-                        layout::Variants::NicheFilling { .. } => {},
+                        layout::Variants::Multiple { .. } => {},
                     }
 
                     let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
@@ -105,7 +104,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                 }
             }
 
-            ClosureFnPointer => {
+            ClosureFnPointer(_) => {
                 // The src operand does not matter, just its type
                 match src.layout.ty.sty {
                     ty::Closure(def_id, substs) => {
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 15b6d5c914d20..38a9371b92723 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -610,25 +610,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
     ) -> EvalResult<'tcx, (u128, VariantIdx)> {
         trace!("read_discriminant_value {:#?}", rval.layout);
 
-        match rval.layout.variants {
+        let discr_kind = match rval.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = rval.layout.ty.ty_adt_def().map_or(
                     index.as_u32() as u128,
                     |def| def.discriminant_for_variant(*self.tcx, index).val);
                 return Ok((discr_val, index));
             }
-            layout::Variants::Tagged { .. } |
-            layout::Variants::NicheFilling { .. } => {},
-        }
+            layout::Variants::Multiple { ref discr_kind, .. } => discr_kind,
+        };
+
         // read raw discriminant value
         let discr_op = self.operand_field(rval, 0)?;
         let discr_val = self.read_immediate(discr_op)?;
         let raw_discr = discr_val.to_scalar_or_undef();
         trace!("discr value: {:?}", raw_discr);
         // post-process
-        Ok(match rval.layout.variants {
-            layout::Variants::Single { .. } => bug!(),
-            layout::Variants::Tagged { .. } => {
+        Ok(match *discr_kind {
+            layout::DiscriminantKind::Tag => {
                 let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
                     Ok(raw_discr) => raw_discr,
                     Err(_) => return err!(InvalidDiscriminant(raw_discr.erase_tag())),
@@ -657,11 +656,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                     .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
                 (real_discr, index.0)
             },
-            layout::Variants::NicheFilling {
+            layout::DiscriminantKind::Niche {
                 dataful_variant,
                 ref niche_variants,
                 niche_start,
-                ..
             } => {
                 let variants_start = niche_variants.start().as_u32() as u128;
                 let variants_end = niche_variants.end().as_u32() as u128;
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index ca93007788e03..488f81d8f740e 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -331,8 +331,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
         val: ImmTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::mir::UnOp::*;
-        use rustc_apfloat::ieee::{Single, Double};
-        use rustc_apfloat::Float;
 
         let layout = val.layout;
         let val = val.to_scalar()?;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 82b92acdb764c..4d51772d5ea14 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -958,7 +958,11 @@ where
             layout::Variants::Single { index } => {
                 assert_eq!(index, variant_index);
             }
-            layout::Variants::Tagged { ref tag, .. } => {
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ref discr,
+                ..
+            } => {
                 let adt_def = dest.layout.ty.ty_adt_def().unwrap();
                 assert!(variant_index.as_usize() < adt_def.variants.len());
                 let discr_val = adt_def
@@ -968,16 +972,18 @@ where
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
                 // representation
-                let size = tag.value.size(self);
+                let size = discr.value.size(self);
                 let discr_val = truncate(discr_val, size);
 
                 let discr_dest = self.place_field(dest, 0)?;
                 self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
             }
-            layout::Variants::NicheFilling {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche {
+                    dataful_variant,
+                    ref niche_variants,
+                    niche_start,
+                },
                 ..
             } => {
                 assert!(
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index 90d4fff421837..05343ac66d966 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -241,8 +241,7 @@ macro_rules! make_value_visitor {
                 // If this is a multi-variant layout, we have find the right one and proceed with
                 // that.
                 match v.layout().variants {
-                    layout::Variants::NicheFilling { .. } |
-                    layout::Variants::Tagged { .. } => {
+                    layout::Variants::Multiple { .. } => {
                         let op = v.to_op(self.ecx())?;
                         let idx = self.ecx().read_discriminant(op)?.1;
                         let inner = v.project_downcast(self.ecx(), idx)?;
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 0e8ab2ba2a5a2..45b346b641362 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -563,7 +563,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                 );
                 visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
             }
-            mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => {
+            mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer(_), ref operand, _) => {
                 let source_ty = operand.ty(self.mir, self.tcx);
                 let source_ty = self.tcx.subst_and_normalize_erasing_regions(
                     self.param_substs,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 0b9ad85e6b1c7..9bd5fce31f1a2 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1105,7 +1105,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
             Rvalue::CheckedBinaryOp(..) |
             Rvalue::Cast(CastKind::ReifyFnPointer, ..) |
             Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
-            Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
+            Rvalue::Cast(CastKind::ClosureFnPointer(_), ..) |
             Rvalue::Cast(CastKind::Unsize, ..) |
             Rvalue::Cast(CastKind::MutToConstPointer, ..) |
             Rvalue::Discriminant(..) |
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 8742c5d759c8f..87459571b529c 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -156,7 +156,7 @@ fn check_rvalue(
             check_operand(tcx, mir, operand, span)
         }
         Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
-        Rvalue::Cast(CastKind::ClosureFnPointer, _, _) |
+        Rvalue::Cast(CastKind::ClosureFnPointer(_), _, _) |
         Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
             span,
             "function pointer casts are not allowed in const fn".into(),
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index a0a0d7be1b95d..7c37c38f2d741 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -586,7 +586,7 @@ fn check_adjustments<'a, 'tcx>(
             Adjust::NeverToAny |
             Adjust::ReifyFnPointer |
             Adjust::UnsafeFnPointer |
-            Adjust::ClosureFnPointer |
+            Adjust::ClosureFnPointer(_) |
             Adjust::MutToConstPointer |
             Adjust::Borrow(_) |
             Adjust::Unsize => {}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index ab3d87fafdac7..3703ea08b6253 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1738,7 +1738,6 @@ impl<'a> Resolver<'a> {
     /// just that an error occurred.
     pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
         -> Result<hir::Path, ()> {
-        use std::iter;
         let mut errored = false;
 
         let path = if path_str.starts_with("::") {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index c2d2bd753c82e..7ea07f5e0cbcb 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -7,6 +7,7 @@ use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyErro
 use crate::{Resolver, Segment};
 use crate::{names_to_string, module_to_string};
 use crate::{resolve_error, ResolutionError, Suggestion};
+use crate::ModuleKind;
 use crate::macros::ParentScope;
 
 use errors::Applicability;
@@ -14,7 +15,11 @@ use errors::Applicability;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc::ty;
 use rustc::lint::builtin::BuiltinLintDiagnostics;
-use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
+use rustc::lint::builtin::{
+    DUPLICATE_MACRO_EXPORTS,
+    PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+    UNUSED_IMPORTS,
+};
 use rustc::hir::def_id::{CrateNum, DefId};
 use rustc::hir::def::*;
 use rustc::session::DiagnosticMessageId;
@@ -1227,10 +1232,97 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             import[ns] = Some(PathResolution::new(def));
         });
 
+        self.check_for_redundant_imports(
+            ident,
+            directive,
+            source_bindings,
+            target_bindings,
+            target,
+        );
+
         debug!("(resolving single import) successfully resolved import");
         None
     }
 
+    fn check_for_redundant_imports(
+        &mut self,
+        ident: Ident,
+        directive: &'b ImportDirective<'b>,
+        source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
+        target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
+        target: Ident,
+    ) {
+        // Skip if the import was produced by a macro.
+        if directive.parent_scope.expansion != Mark::root() {
+            return;
+        }
+
+        // Skip if we are inside a named module (in contrast to an anonymous
+        // module defined by a block).
+        if let ModuleKind::Def(_, _) = directive.parent_scope.module.kind {
+            return;
+        }
+
+        let mut is_redundant = PerNS {
+            value_ns: None,
+            type_ns: None,
+            macro_ns: None,
+        };
+
+        let mut redundant_span = PerNS {
+            value_ns: None,
+            type_ns: None,
+            macro_ns: None,
+        };
+
+        self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
+            if binding.def() == Def::Err {
+                return;
+            }
+
+            let orig_blacklisted_binding = mem::replace(
+                &mut this.blacklisted_binding,
+                target_bindings[ns].get()
+            );
+
+            match this.early_resolve_ident_in_lexical_scope(
+                target,
+                ScopeSet::Import(ns),
+                &directive.parent_scope,
+                false,
+                false,
+                directive.span,
+            ) {
+                Ok(other_binding) => {
+                    is_redundant[ns] = Some(
+                        binding.def() == other_binding.def()
+                        && !other_binding.is_ambiguity()
+                    );
+                    redundant_span[ns] =
+                        Some((other_binding.span, other_binding.is_import()));
+                }
+                Err(_) => is_redundant[ns] = Some(false)
+            }
+
+            this.blacklisted_binding = orig_blacklisted_binding;
+        });
+
+        if !is_redundant.is_empty() &&
+            is_redundant.present_items().all(|is_redundant| is_redundant)
+        {
+            self.session.buffer_lint_with_diagnostic(
+                UNUSED_IMPORTS,
+                directive.id,
+                directive.span,
+                &format!("the item `{}` is imported redundantly", ident),
+                BuiltinLintDiagnostics::RedundantImport(
+                    redundant_span.present_items().collect(),
+                    ident,
+                ),
+            );
+        }
+    }
+
     fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
         let module = match directive.imported_module.get().unwrap() {
             ModuleOrUniformRoot::Module(module) => module,
diff --git a/src/librustc_target/abi/call/x86_64.rs b/src/librustc_target/abi/call/x86_64.rs
index 680e529b108e0..b68c70224c95e 100644
--- a/src/librustc_target/abi/call/x86_64.rs
+++ b/src/librustc_target/abi/call/x86_64.rs
@@ -61,8 +61,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &ArgType<'a, Ty>)
                         }
                         return Ok(());
                     }
-                    abi::Variants::Tagged { .. } |
-                    abi::Variants::NicheFilling { .. } => return Err(Memory),
+                    abi::Variants::Multiple { .. } => return Err(Memory),
                 }
             }
 
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 8b96a8c1658b2..235b530a7ef2f 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -828,15 +828,22 @@ pub enum Variants {
         index: VariantIdx,
     },
 
-    /// General-case enums: for each case there is a struct, and they all have
-    /// all space reserved for the tag, and their first field starts
-    /// at a non-0 offset, after where the tag would go.
-    Tagged {
-        tag: Scalar,
+    /// Enums with more than one inhabited variant: for each case there is
+    /// a struct, and they all have space reserved for the discriminant,
+    /// which is the sole field of the enum layout.
+    Multiple {
+        discr: Scalar,
+        discr_kind: DiscriminantKind,
         variants: IndexVec<VariantIdx, LayoutDetails>,
     },
+}
+
+#[derive(PartialEq, Eq, Hash, Debug)]
+pub enum DiscriminantKind {
+    /// Integer tag holding the discriminant value itself.
+    Tag,
 
-    /// Multiple cases distinguished by a niche (values invalid for a type):
+    /// Niche (values invalid for a type) encoding the discriminant:
     /// the variant `dataful_variant` contains a niche at an arbitrary
     /// offset (field 0 of the enum), which for a variant with discriminant
     /// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
@@ -844,13 +851,11 @@ pub enum Variants {
     /// For example, `Option<(usize, &T)>`  is represented such that
     /// `None` has a null pointer for the second tuple field, and
     /// `Some` is the identity function (with a non-null reference).
-    NicheFilling {
+    Niche {
         dataful_variant: VariantIdx,
         niche_variants: RangeInclusive<VariantIdx>,
-        niche: Scalar,
         niche_start: u128,
-        variants: IndexVec<VariantIdx, LayoutDetails>,
-    }
+    },
 }
 
 #[derive(PartialEq, Eq, Hash, Debug)]
diff --git a/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs b/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs
index e772d8b532cb0..b9d36c09f1636 100644
--- a/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}_mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/aarch64_unknown_linux_musl.rs b/src/librustc_target/spec/aarch64_unknown_linux_musl.rs
index 8123ee82ed524..968e82ca39fbe 100644
--- a/src/librustc_target/spec/aarch64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/aarch64_unknown_linux_musl.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}_mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/aarch64_unknown_netbsd.rs b/src/librustc_target/spec/aarch64_unknown_netbsd.rs
index 47ae08ade9a6b..455cbebb91e28 100644
--- a/src/librustc_target/spec/aarch64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/aarch64_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
@@ -16,6 +16,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "__mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
index f291818ba80f5..2f835420148fe 100644
--- a/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
@@ -18,6 +18,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             features: "+strict-align,+v6".to_string(),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
index 32b509d9721ef..cd4b2e1c92252 100644
--- a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
@@ -18,6 +18,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             features: "+strict-align,+v6,+vfp2".to_string(),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabi.rs b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
index 7637577e7e848..606c3f1906031 100644
--- a/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
@@ -23,6 +23,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
index 9def151b3ef29..d22156bc328e0 100644
--- a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
@@ -23,6 +23,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}mcount".to_string(),
             .. base
         },
     })
diff --git a/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
index 7cd4b14cdebc8..e7da24843cc05 100644
--- a/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
@@ -19,6 +19,7 @@ pub fn target() -> TargetResult {
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
index 15f614827718b..ea586f42c269e 100644
--- a/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
@@ -19,6 +19,7 @@ pub fn target() -> TargetResult {
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
index 74915b942ea4f..dae5c8c3d7504 100644
--- a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
@@ -22,6 +22,7 @@ pub fn target() -> TargetResult {
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}mcount".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv6_unknown_freebsd.rs b/src/librustc_target/spec/armv6_unknown_freebsd.rs
index 39886a16a7403..a90590a39e75e 100644
--- a/src/librustc_target/spec/armv6_unknown_freebsd.rs
+++ b/src/librustc_target/spec/armv6_unknown_freebsd.rs
@@ -18,6 +18,7 @@ pub fn target() -> TargetResult {
             features: "+v6,+vfp2".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
index e460b6c574a26..b056776bdfb8b 100644
--- a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
+++ b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
@@ -18,6 +18,7 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             features: "+v6,+vfp2".to_string(),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "__mcount".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
index a6c7fb537c785..c03f4b544ed0b 100644
--- a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
@@ -19,6 +19,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "\u{1}mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/armv7_unknown_freebsd.rs b/src/librustc_target/spec/armv7_unknown_freebsd.rs
index ba63fd2bf053f..ca7ab474bef88 100644
--- a/src/librustc_target/spec/armv7_unknown_freebsd.rs
+++ b/src/librustc_target/spec/armv7_unknown_freebsd.rs
@@ -18,6 +18,7 @@ pub fn target() -> TargetResult {
             features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
index f16215433c766..f0952cccb2087 100644
--- a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
@@ -23,6 +23,7 @@ pub fn target() -> TargetResult {
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
index 45a26966b716b..a9974f6b80c93 100644
--- a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
@@ -26,6 +26,7 @@ pub fn target() -> TargetResult {
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "\u{1}mcount".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
index 44e2636e9188e..e2d55e9317b76 100644
--- a/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
@@ -19,6 +19,7 @@ pub fn target() -> TargetResult {
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
+            target_mcount: "__mcount".to_string(),
             .. base
         }
     })
diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index c8a61296d33d2..58c59cc872846 100644
--- a/src/librustc_target/spec/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
@@ -19,6 +19,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "\u{1}mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/i686_unknown_netbsd.rs b/src/librustc_target/spec/i686_unknown_netbsd.rs
index e8a9f29ea5f4c..99130e93dad61 100644
--- a/src/librustc_target/spec/i686_unknown_netbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
@@ -18,6 +18,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "__mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs
index 3b38e64050f3b..b2ea8a6f38814 100644
--- a/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs
+++ b/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips64r2".to_string(),
             features: "+mips64r2".to_string(),
             max_atomic_width: Some(64),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs
index 0f6cd86d616d8..48aea4a39b0a4 100644
--- a/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs
+++ b/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips64r2".to_string(),
             features: "+mips64r2".to_string(),
             max_atomic_width: Some(64),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mips_unknown_linux_gnu.rs b/src/librustc_target/spec/mips_unknown_linux_gnu.rs
index b4d29c5fbeaf4..e360abdb38d3f 100644
--- a/src/librustc_target/spec/mips_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/mips_unknown_linux_gnu.rs
@@ -16,6 +16,7 @@ pub fn target() -> TargetResult {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
             max_atomic_width: Some(32),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mips_unknown_linux_musl.rs b/src/librustc_target/spec/mips_unknown_linux_musl.rs
index c56c6e3822959..3f5428de95074 100644
--- a/src/librustc_target/spec/mips_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/mips_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/mips_unknown_linux_uclibc.rs b/src/librustc_target/spec/mips_unknown_linux_uclibc.rs
index cb02769c7dfe4..8116b8c9cc840 100644
--- a/src/librustc_target/spec/mips_unknown_linux_uclibc.rs
+++ b/src/librustc_target/spec/mips_unknown_linux_uclibc.rs
@@ -16,6 +16,7 @@ pub fn target() -> TargetResult {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+soft-float".to_string(),
             max_atomic_width: Some(32),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs
index ed49ddd49937f..7e9d8cd942a23 100644
--- a/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
             max_atomic_width: Some(32),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mipsel_unknown_linux_musl.rs b/src/librustc_target/spec/mipsel_unknown_linux_musl.rs
index bcc49cf5ffe4f..56ad2940feba8 100644
--- a/src/librustc_target/spec/mipsel_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/mipsel_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs b/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs
index 205f328a24cec..a8152011efa79 100644
--- a/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs
+++ b/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+soft-float".to_string(),
             max_atomic_width: Some(32),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs
index f47291458492e..36b83c63fca28 100644
--- a/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -16,6 +16,7 @@ pub fn target() -> TargetResult {
             cpu: "mips32r6".to_string(),
             features: "+mips32r6".to_string(),
             max_atomic_width: Some(32),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs
index f4f98d33571f0..717ae3f1d20e1 100644
--- a/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/mipsisa32r6el_unknown_linux_gnu.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips32r6".to_string(),
             features: "+mips32r6".to_string(),
             max_atomic_width: Some(32),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
index 7faed3adc79cc..3f7d233e55fbc 100644
--- a/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/src/librustc_target/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips64r6".to_string(),
             features: "+mips64r6".to_string(),
             max_atomic_width: Some(64),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
index 58a814a759eb8..4f41b8323a99a 100644
--- a/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/src/librustc_target/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
             cpu: "mips64r6".to_string(),
             features: "+mips64r6".to_string(),
             max_atomic_width: Some(64),
+            target_mcount: "_mcount".to_string(),
 
             ..super::linux_base::opts()
         },
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index d049bb91f290a..46fefd78f4519 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -761,7 +761,10 @@ pub struct TargetOptions {
     /// to opt out. The default is "aliases".
     ///
     /// Workaround for: https://github.com/rust-lang/rust/issues/57356
-    pub merge_functions: MergeFunctions
+    pub merge_functions: MergeFunctions,
+
+    /// Use platform dependent mcount function
+    pub target_mcount: String
 }
 
 impl Default for TargetOptions {
@@ -845,6 +848,7 @@ impl Default for TargetOptions {
             simd_types_indirect: true,
             override_export_symbols: None,
             merge_functions: MergeFunctions::Aliases,
+            target_mcount: "mcount".to_string(),
         }
     }
 }
@@ -1150,6 +1154,7 @@ impl Target {
         key!(simd_types_indirect, bool);
         key!(override_export_symbols, opt_list);
         key!(merge_functions, MergeFunctions)?;
+        key!(target_mcount);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1364,6 +1369,7 @@ impl ToJson for Target {
         target_option_val!(simd_types_indirect);
         target_option_val!(override_export_symbols);
         target_option_val!(merge_functions);
+        target_option_val!(target_mcount);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
diff --git a/src/librustc_target/spec/powerpc64_unknown_freebsd.rs b/src/librustc_target/spec/powerpc64_unknown_freebsd.rs
index 360876b9ff557..fc881db6b0906 100644
--- a/src/librustc_target/spec/powerpc64_unknown_freebsd.rs
+++ b/src/librustc_target/spec/powerpc64_unknown_freebsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs
index c16db7583f32b..89e68ab306200 100644
--- a/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult, RelroLevel};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult, RelroLevel};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
@@ -21,6 +21,9 @@ pub fn target() -> TargetResult {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs b/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs
index ac0b7431f91a4..be91dc44b9357 100644
--- a/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs
index 038b925a28692..784e3b090943c 100644
--- a/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs b/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs
index 57103345f0a0c..a3cf47fc5e082 100644
--- a/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs
index 38a801d5ab507..ff52fbc179b16 100644
--- a/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
@@ -16,6 +16,9 @@ pub fn target() -> TargetResult {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs b/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs
index 675b2c749d648..1868c42be39d2 100644
--- a/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
@@ -16,6 +16,9 @@ pub fn target() -> TargetResult {
         target_env: "gnu".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc_unknown_linux_musl.rs b/src/librustc_target/spec/powerpc_unknown_linux_musl.rs
index 240443aa98db4..1ad2201092c3f 100644
--- a/src/librustc_target/spec/powerpc_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/powerpc_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
@@ -16,6 +16,9 @@ pub fn target() -> TargetResult {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "_mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/powerpc_unknown_netbsd.rs b/src/librustc_target/spec/powerpc_unknown_netbsd.rs
index 10e7089cf1c4c..6cc3a6c2ef3f2 100644
--- a/src/librustc_target/spec/powerpc_unknown_netbsd.rs
+++ b/src/librustc_target/spec/powerpc_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
@@ -16,6 +16,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "__mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/sparc64_unknown_netbsd.rs b/src/librustc_target/spec/sparc64_unknown_netbsd.rs
index 78d53e69e8b52..09d1debef41e9 100644
--- a/src/librustc_target/spec/sparc64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/sparc64_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
@@ -17,6 +17,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "__mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs
index 0911ce06c13d7..c54181741b3cc 100644
--- a/src/librustc_target/spec/x86_64_apple_darwin.rs
+++ b/src/librustc_target/spec/x86_64_apple_darwin.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
@@ -19,6 +19,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "\u{1}mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
index a2c706c4c7232..f6861f2a68727 100644
--- a/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
@@ -24,6 +24,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "rumprun".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "__mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_target/spec/x86_64_unknown_netbsd.rs b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
index ffc4f1d5c49b7..6f4ab4995b5dc 100644
--- a/src/librustc_target/spec/x86_64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
@@ -18,6 +18,9 @@ pub fn target() -> TargetResult {
         target_env: String::new(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
-        options: base,
+        options: TargetOptions {
+            target_mcount: "__mcount".to_string(),
+            .. base
+        },
     })
 }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index ac8b639edbfa3..c470bc09e8cd0 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -225,7 +225,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             }
             ty::Closure(def_id_a, substs_a) => {
                 // Non-capturing closures are coercible to
-                // function pointers
+                // function pointers or unsafe function pointers.
+                // It cannot convert closures that require unsafe.
                 self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
             }
             _ => {
@@ -714,16 +715,19 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
 
         let hir_id_a = self.tcx.hir().as_local_hir_id(def_id_a).unwrap();
         match b.sty {
-            ty::FnPtr(_) if self.tcx.with_freevars(hir_id_a, |v| v.is_empty()) => {
+            ty::FnPtr(fn_ty) if self.tcx.with_freevars(hir_id_a, |v| v.is_empty()) => {
                 // We coerce the closure, which has fn type
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                 // to
                 //     `fn(arg0,arg1,...) -> _`
+                // or
+                //     `unsafe fn(arg0,arg1,...) -> _`
                 let sig = self.closure_sig(def_id_a, substs_a);
-                let pointer_ty = self.tcx.coerce_closure_fn_ty(sig);
+                let unsafety = fn_ty.unsafety();
+                let pointer_ty = self.tcx.coerce_closure_fn_ty(sig, unsafety);
                 debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
                        a, b, pointer_ty);
-                self.unify_and(pointer_ty, b, simple(Adjust::ClosureFnPointer))
+                self.unify_and(pointer_ty, b, simple(Adjust::ClosureFnPointer(unsafety)))
             }
             _ => self.unify_and(a, b, identity),
         }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 920270b5473cf..3579810b8d75f 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -420,9 +420,6 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
     def_id: DefId,
     return_ty: Option<Ty<'tcx>>,
 ) {
-    use ty::subst::Subst;
-    use rustc::ty::TypeFoldable;
-
     let predicates = fcx.tcx.predicates_of(def_id);
 
     let generics = tcx.generics_of(def_id);
@@ -1010,8 +1007,6 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>(
     span: Span,
     id: hir::HirId)
 {
-    use rustc::ty::TypeFoldable;
-
     let empty_env = ty::ParamEnv::empty();
 
     let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id);
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index cc90044573ce5..1fa16352b867a 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -64,7 +64,6 @@ This API is completely unstable and subject to change.
 #![feature(crate_visibility_modifier)]
 #![feature(exhaustive_patterns)]
 #![feature(nll)]
-#![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(never_type)]
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 9220d2feed2d2..f7e8cdeaeca89 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1069,8 +1069,6 @@ themePicker.onblur = handleThemeButtonsBlur;
     }
 
     if cx.shared.include_sources {
-        use std::path::Component;
-
         let mut hierarchy = Hierarchy::new(OsString::new());
         for source in cx.shared.local_sources.iter()
                                              .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root)
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index f1d4d8470b2a5..0bbc7c5c4b223 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -371,8 +371,7 @@ pub fn make_test(s: &str,
     // Uses libsyntax to parse the doctest and find if there's a main fn and the extern
     // crate already is included.
     let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| {
-        use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
-        use crate::syntax_pos::FileName;
+        use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping};
         use errors::emitter::EmitterWriter;
         use errors::Handler;
 
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 89051030f6683..081fff0562b16 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -197,7 +197,6 @@ pub trait Error: Debug + Display {
     fn source(&self) -> Option<&(dyn Error + 'static)> { None }
 
     /// Gets the `TypeId` of `self`
-    #[doc(hidden)]
     #[stable(feature = "error_type_id", since = "1.34.0")]
     fn type_id(&self) -> TypeId where Self: 'static {
         TypeId::of::<Self>()
diff --git a/src/test/codegen/instrument-mcount.rs b/src/test/codegen/instrument-mcount.rs
new file mode 100644
index 0000000000000..c72d09f7a03d2
--- /dev/null
+++ b/src/test/codegen/instrument-mcount.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+// compile-flags: -Z instrument-mcount
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} "instrument-function-entry-inlined"="{{.*}}mcount{{.*}}" "no-frame-pointer-elim"="true"
+pub fn foo() {}
diff --git a/src/test/compile-fail/coerce-unsafe-closure-to-unsafe-fn-ptr.rs b/src/test/compile-fail/coerce-unsafe-closure-to-unsafe-fn-ptr.rs
new file mode 100644
index 0000000000000..36777693faba0
--- /dev/null
+++ b/src/test/compile-fail/coerce-unsafe-closure-to-unsafe-fn-ptr.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); };
+    //~^ ERROR E0133
+    let _: unsafe fn() = || unsafe { ::std::pin::Pin::new_unchecked(&0_u8); }; // OK
+}
diff --git a/src/test/run-pass/binding/match-arm-statics.rs b/src/test/run-pass/binding/match-arm-statics.rs
index 359c39211588c..5f7e357eeb2a9 100644
--- a/src/test/run-pass/binding/match-arm-statics.rs
+++ b/src/test/run-pass/binding/match-arm-statics.rs
@@ -45,8 +45,6 @@ pub mod glfw {
 }
 
 fn issue_6533() {
-    use glfw;
-
     fn action_to_str(state: glfw::InputState) -> &'static str {
         use glfw::{RELEASE, PRESS, REPEAT};
         match state {
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index 56222fa46f7c9..8c17b01e2bd89 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -238,7 +238,6 @@ pub fn main() {
 // Basic test to make sure that we can invoke the `write!` macro with an
 // fmt::Write instance.
 fn test_write() {
-    use std::fmt::Write;
     let mut buf = String::new();
     write!(&mut buf, "{}", 3);
     {
@@ -267,7 +266,6 @@ fn test_print() {
 // Just make sure that the macros are defined, there's not really a lot that we
 // can do with them just yet (to test the output)
 fn test_format_args() {
-    use std::fmt::Write;
     let mut buf = String::new();
     {
         let w = &mut buf;
diff --git a/src/test/run-pass/invalid_const_promotion.rs b/src/test/run-pass/invalid_const_promotion.rs
index 1524373895d9b..2775aac015615 100644
--- a/src/test/run-pass/invalid_const_promotion.rs
+++ b/src/test/run-pass/invalid_const_promotion.rs
@@ -25,7 +25,6 @@ fn foo() {
 #[cfg(unix)]
 fn check_status(status: std::process::ExitStatus)
 {
-    use libc;
     use std::os::unix::process::ExitStatusExt;
 
     assert!(status.signal() == Some(libc::SIGILL)
diff --git a/src/test/run-pass/issues/issue-38556.rs b/src/test/run-pass/issues/issue-38556.rs
index 0cc247f5b9ca5..63fd9db08ff2f 100644
--- a/src/test/run-pass/issues/issue-38556.rs
+++ b/src/test/run-pass/issues/issue-38556.rs
@@ -9,6 +9,5 @@ macro_rules! reexport {
 reexport!();
 
 fn main() {
-    use Bar;
     fn f(_: Bar) {}
 }
diff --git a/src/test/run-pass/issues/issue-39367.rs b/src/test/run-pass/issues/issue-39367.rs
index bd92224bce161..484cd782a09df 100644
--- a/src/test/run-pass/issues/issue-39367.rs
+++ b/src/test/run-pass/issues/issue-39367.rs
@@ -15,7 +15,6 @@ fn arena() -> &'static ArenaSet<Vec<u8>> {
         fn require_sync<T: Sync>(_: &T) { }
         unsafe fn __stability() -> &'static ArenaSet<Vec<u8>> {
             use std::mem::transmute;
-            use std::boxed::Box;
             static mut DATA: *const ArenaSet<Vec<u8>> = 0 as *const ArenaSet<Vec<u8>>;
 
             static mut ONCE: Once = ONCE_INIT;
diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs
index 72d6d6806229e..9f868d6e5c3e4 100644
--- a/src/test/run-pass/out-of-stack.rs
+++ b/src/test/run-pass/out-of-stack.rs
@@ -36,7 +36,6 @@ fn loud_recurse() {
 #[cfg(unix)]
 fn check_status(status: std::process::ExitStatus)
 {
-    use libc;
     use std::os::unix::process::ExitStatusExt;
 
     assert!(!status.success());
diff --git a/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs b/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs
index 15449a6b83e2e..566b3581046d9 100644
--- a/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs
+++ b/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs
@@ -4,6 +4,8 @@
 // compile-flags:--extern xcrate
 // edition:2018
 
+#![allow(unused_imports)]
+
 use xcrate::Z;
 
 fn f() {
diff --git a/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs b/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs
index ca47d9736f63c..626e1ae71bc2f 100644
--- a/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs
+++ b/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs
@@ -28,7 +28,6 @@ where T : Convert<U>
 }
 
 fn main() {
-    use std::default::Default;
     // T = i16, U = u32
     test(22_i16, Default::default(),  2, 4);
 
diff --git a/src/test/run-pass/typeck-closure-to-unsafe-fn-ptr.rs b/src/test/run-pass/typeck-closure-to-unsafe-fn-ptr.rs
new file mode 100644
index 0000000000000..fe15b912d6029
--- /dev/null
+++ b/src/test/run-pass/typeck-closure-to-unsafe-fn-ptr.rs
@@ -0,0 +1,7 @@
+unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () {
+    func()
+}
+
+pub fn main() {
+    unsafe { call_unsafe(|| {}); }
+}
diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs
index 7ce7e29e87235..ae4de92ff7488 100644
--- a/src/test/run-pass/weird-exprs.rs
+++ b/src/test/run-pass/weird-exprs.rs
@@ -127,6 +127,21 @@ fn punch_card() -> impl std::fmt::Debug {
     ..=.. ..=..    .. ..=..=..    ..=..=.. ..    .. ..=.. ..
 }
 
+fn r#match() {
+    let val = match match match match match () {
+        () => ()
+    } {
+        () => ()
+    } {
+        () => ()
+    } {
+        () => ()
+    } {
+        () => ()
+    };
+    assert_eq!(val, ());
+}
+
 pub fn main() {
     strange();
     funny();
@@ -142,4 +157,5 @@ pub fn main() {
     union();
     special_characters();
     punch_card();
+    r#match();
 }
diff --git a/src/test/ui/lint/lint-unused-imports.rs b/src/test/ui/lint/lint-unused-imports.rs
index 9c5b206203c1d..4754d8880763a 100644
--- a/src/test/ui/lint/lint-unused-imports.rs
+++ b/src/test/ui/lint/lint-unused-imports.rs
@@ -66,6 +66,7 @@ mod bar {
 
 fn g() {
     use self::g; //~ ERROR unused import: `self::g`
+    //~^ ERROR the item `g` is imported redundantly
     fn f() {
         self::g();
     }
@@ -75,6 +76,7 @@ fn g() {
 #[allow(unused_variables)]
 fn h() {
     use test2::foo; //~ ERROR unused import: `test2::foo`
+    //~^ ERROR the item `foo` is imported redundantly
     let foo = 0;
 }
 
diff --git a/src/test/ui/lint/lint-unused-imports.stderr b/src/test/ui/lint/lint-unused-imports.stderr
index f9a54f477f998..96d71a228a5f2 100644
--- a/src/test/ui/lint/lint-unused-imports.stderr
+++ b/src/test/ui/lint/lint-unused-imports.stderr
@@ -34,14 +34,36 @@ error: unused import: `foo::Square`
 LL |         use foo::Square;
    |             ^^^^^^^^^^^
 
+error: the item `g` is imported redundantly
+  --> $DIR/lint-unused-imports.rs:68:9
+   |
+LL | / fn g() {
+LL | |     use self::g;
+   | |         ^^^^^^^
+LL | |
+LL | |     fn f() {
+LL | |         self::g();
+LL | |     }
+LL | | }
+   | |_- the item `g` is already defined here
+
 error: unused import: `self::g`
   --> $DIR/lint-unused-imports.rs:68:9
    |
 LL |     use self::g;
    |         ^^^^^^^
 
+error: the item `foo` is imported redundantly
+  --> $DIR/lint-unused-imports.rs:78:9
+   |
+LL | use test2::{foo, bar};
+   |             --- the item `foo` is already imported here
+...
+LL |     use test2::foo;
+   |         ^^^^^^^^^^
+
 error: unused import: `test2::foo`
-  --> $DIR/lint-unused-imports.rs:77:9
+  --> $DIR/lint-unused-imports.rs:78:9
    |
 LL |     use test2::foo;
    |         ^^^^^^^^^^
@@ -52,5 +74,5 @@ error: unused import: `test::B2`
 LL | use test::B2;
    |     ^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/lint/use-redundant.rs b/src/test/ui/lint/use-redundant.rs
new file mode 100644
index 0000000000000..328f8232bafa8
--- /dev/null
+++ b/src/test/ui/lint/use-redundant.rs
@@ -0,0 +1,27 @@
+// compile-pass
+#![warn(unused_imports)]
+
+use crate::foo::Bar; //~ WARNING first import
+
+mod foo {
+    pub type Bar = i32;
+}
+
+fn baz() -> Bar {
+    3
+}
+
+mod m1 { pub struct S {} }
+mod m2 { pub struct S {} }
+
+use m1::*;
+use m2::*;
+
+fn main() {
+    use crate::foo::Bar; //~ WARNING redundant import
+    let _a: Bar = 3;
+    baz();
+
+    use m1::S; //~ WARNING redundant import
+    let _s = S {};
+}
diff --git a/src/test/ui/lint/use-redundant.stderr b/src/test/ui/lint/use-redundant.stderr
new file mode 100644
index 0000000000000..fbd9f81f18f8a
--- /dev/null
+++ b/src/test/ui/lint/use-redundant.stderr
@@ -0,0 +1,27 @@
+warning: unused import: `m1::*`
+  --> $DIR/use-redundant.rs:17:5
+   |
+LL | use m1::*;
+   |     ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/use-redundant.rs:2:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: unused import: `m2::*`
+  --> $DIR/use-redundant.rs:18:5
+   |
+LL | use m2::*;
+   |     ^^^^^
+
+warning: the item `Bar` is imported redundantly
+  --> $DIR/use-redundant.rs:21:9
+   |
+LL | use crate::foo::Bar;
+   |     --------------- the item `Bar` is already imported here
+...
+LL |     use crate::foo::Bar;
+   |         ^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs
index 1e53c2d1daca4..2c388cf3713b0 100644
--- a/src/test/ui/rust-2018/future-proofing-locals.rs
+++ b/src/test/ui/rust-2018/future-proofing-locals.rs
@@ -1,6 +1,7 @@
 // edition:2018
 
 #![allow(non_camel_case_types)]
+#![allow(unused_imports)]
 
 mod T {
     pub struct U;
diff --git a/src/test/ui/rust-2018/future-proofing-locals.stderr b/src/test/ui/rust-2018/future-proofing-locals.stderr
index 4d666d22afed1..7021489a6ddcf 100644
--- a/src/test/ui/rust-2018/future-proofing-locals.stderr
+++ b/src/test/ui/rust-2018/future-proofing-locals.stderr
@@ -1,53 +1,53 @@
 error: imports cannot refer to type parameters
-  --> $DIR/future-proofing-locals.rs:13:9
+  --> $DIR/future-proofing-locals.rs:14:9
    |
 LL |     use T as _;
    |         ^
 
 error: imports cannot refer to type parameters
-  --> $DIR/future-proofing-locals.rs:14:9
+  --> $DIR/future-proofing-locals.rs:15:9
    |
 LL |     use T::U;
    |         ^
 
 error: imports cannot refer to type parameters
-  --> $DIR/future-proofing-locals.rs:15:9
+  --> $DIR/future-proofing-locals.rs:16:9
    |
 LL |     use T::*;
    |         ^
 
 error: imports cannot refer to type parameters
-  --> $DIR/future-proofing-locals.rs:19:9
+  --> $DIR/future-proofing-locals.rs:20:9
    |
 LL |     use T;
    |         ^
 
 error: imports cannot refer to local variables
-  --> $DIR/future-proofing-locals.rs:25:9
+  --> $DIR/future-proofing-locals.rs:26:9
    |
 LL |     use x as _;
    |         ^
 
 error: imports cannot refer to local variables
-  --> $DIR/future-proofing-locals.rs:31:9
+  --> $DIR/future-proofing-locals.rs:32:9
    |
 LL |     use x;
    |         ^
 
 error: imports cannot refer to local variables
-  --> $DIR/future-proofing-locals.rs:37:17
+  --> $DIR/future-proofing-locals.rs:38:17
    |
 LL |             use x;
    |                 ^
 
 error: imports cannot refer to type parameters
-  --> $DIR/future-proofing-locals.rs:45:10
+  --> $DIR/future-proofing-locals.rs:46:10
    |
 LL |     use {T as _, x};
    |          ^
 
 error: imports cannot refer to local variables
-  --> $DIR/future-proofing-locals.rs:45:18
+  --> $DIR/future-proofing-locals.rs:46:18
    |
 LL |     use {T as _, x};
    |                  ^