about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-03-14 23:43:04 +0000
committerbors <bors@rust-lang.org>2018-03-14 23:43:04 +0000
commit5ebf74851d685f75abec7ef4e805f75fc301460c (patch)
tree226dc784417a299554cc1ce7748f51d49797a2de
parent521d91c6be76367d966df419677dd187f799b116 (diff)
parenta8a0c691914b72d1ca54057914b4cee2bd097ae3 (diff)
downloadrust-5ebf74851d685f75abec7ef4e805f75fc301460c.tar.gz
rust-5ebf74851d685f75abec7ef4e805f75fc301460c.zip
Auto merge of #47630 - canndrew:exhaustive-patterns, r=nikomatsakis
Stabilise feature(never_type). Introduce feature(exhaustive_patterns)

This stabilizes `!`, removing the feature gate as well as the old defaulting-to-`()` behavior. The pattern exhaustiveness checks which were covered by `feature(never_type)` have been moved behind a new `feature(exhaustive_patterns)` gate.
-rw-r--r--src/libcore/cmp.rs8
-rw-r--r--src/libcore/fmt/mod.rs4
-rw-r--r--src/libcore/lib.rs3
-rw-r--r--src/librustc/ich/impls_ty.rs3
-rw-r--r--src/librustc/infer/canonical.rs8
-rw-r--r--src/librustc/infer/outlives/bounds.rs2
-rw-r--r--src/librustc/infer/resolve.rs6
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc/lint/builtin.rs15
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/mir/tcx.rs7
-rw-r--r--src/librustc/traits/error_reporting.rs56
-rw-r--r--src/librustc/traits/fulfill.rs6
-rw-r--r--src/librustc/traits/mod.rs2
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs2
-rw-r--r--src/librustc/traits/select.rs55
-rw-r--r--src/librustc/traits/util.rs2
-rw-r--r--src/librustc/ty/context.rs21
-rw-r--r--src/librustc/ty/error.rs2
-rw-r--r--src/librustc/ty/fast_reject.rs2
-rw-r--r--src/librustc/ty/flags.rs5
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs2
-rw-r--r--src/librustc/ty/item_path.rs6
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/relate.rs5
-rw-r--r--src/librustc/ty/structural_impls.rs4
-rw-r--r--src/librustc/ty/sty.rs17
-rw-r--r--src/librustc/ty/util.rs13
-rw-r--r--src/librustc/ty/walk.rs2
-rw-r--r--src/librustc/ty/wf.rs2
-rw-r--r--src/librustc/util/ppaux.rs4
-rw-r--r--src/librustc_driver/test.rs10
-rw-r--r--src/librustc_lint/lib.rs15
-rw-r--r--src/librustc_lint/unused.rs2
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs2
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs2
-rw-r--r--src/librustc_mir/build/matches/simplify.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs10
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs2
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs4
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs2
-rw-r--r--src/librustc_mir/lib.rs3
-rw-r--r--src/librustc_mir/monomorphize/item.rs2
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs2
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_trans/abi.rs2
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs8
-rw-r--r--src/librustc_trans/debuginfo/mod.rs4
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs2
-rw-r--r--src/librustc_trans/mir/block.rs2
-rw-r--r--src/librustc_trans/mir/mod.rs2
-rw-r--r--src/librustc_trans/mir/rvalue.rs2
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/check/_match.rs4
-rw-r--r--src/librustc_typeck/check/cast.rs10
-rw-r--r--src/librustc_typeck/check/closure.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs21
-rw-r--r--src/librustc_typeck/check/compare_method.rs4
-rw-r--r--src/librustc_typeck/check/demand.rs2
-rw-r--r--src/librustc_typeck/check/dropck.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs49
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/coherence/builtin.rs2
-rw-r--r--src/librustc_typeck/lib.rs5
-rw-r--r--src/librustc_typeck/variance/constraints.rs2
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/libstd/error.rs2
-rw-r--r--src/libstd/lib.rs3
-rw-r--r--src/libstd/primitive_docs.rs11
-rw-r--r--src/libsyntax/feature_gate.rs8
-rw-r--r--src/test/compile-fail/call-fn-never-arg-wrong-type.rs2
-rw-r--r--src/test/compile-fail/coerce-to-bang-cast.rs6
-rw-r--r--src/test/compile-fail/coerce-to-bang.rs15
-rw-r--r--src/test/compile-fail/defaulted-never-note.rs (renamed from src/test/compile-fail/defaulted-unit-warning.rs)7
-rw-r--r--src/test/compile-fail/diverging-fn-tail-35849.rs4
-rw-r--r--src/test/compile-fail/inhabitedness-infinite-loop.rs2
-rw-r--r--src/test/compile-fail/loop-break-value.rs2
-rw-r--r--src/test/compile-fail/match-privately-empty.rs2
-rw-r--r--src/test/compile-fail/never-assign-dead-code.rs2
-rw-r--r--src/test/compile-fail/never-assign-wrong-type.rs1
-rw-r--r--src/test/compile-fail/recursive-types-are-not-uninhabited.rs2
-rw-r--r--src/test/compile-fail/uninhabited-irrefutable.rs2
-rw-r--r--src/test/compile-fail/uninhabited-patterns.rs2
-rw-r--r--src/test/compile-fail/unreachable-loop-patterns.rs2
-rw-r--r--src/test/compile-fail/unreachable-try-pattern.rs2
-rw-r--r--src/test/run-fail/adjust_never.rs2
-rw-r--r--src/test/run-fail/call-fn-never-arg.rs1
-rw-r--r--src/test/run-fail/cast-never.rs2
-rw-r--r--src/test/run-fail/never-associated-type.rs2
-rw-r--r--src/test/run-fail/never-type-arg.rs2
-rw-r--r--src/test/run-pass/diverging-fallback-control-flow.rs2
-rw-r--r--src/test/run-pass/empty-types-in-patterns.rs2
-rw-r--r--src/test/run-pass/impl-for-never.rs2
-rw-r--r--src/test/run-pass/issue-38972.rs25
-rw-r--r--src/test/run-pass/issue-44402.rs2
-rw-r--r--src/test/run-pass/loop-break-value.rs2
-rw-r--r--src/test/run-pass/mir_calls_to_shims.rs1
-rw-r--r--src/test/run-pass/never-result.rs2
-rw-r--r--src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs2
-rw-r--r--src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr4
-rw-r--r--src/test/ui/feature-gate-exhaustive-patterns.rs (renamed from src/test/run-pass/diverging-fn-tail-35849.rs)14
-rw-r--r--src/test/ui/feature-gate-exhaustive-patterns.stderr9
-rw-r--r--src/test/ui/feature-gate-never_type.rs28
-rw-r--r--src/test/ui/feature-gate-never_type.stderr43
-rw-r--r--src/test/ui/print_type_sizes/uninhabited.rs1
-rw-r--r--src/test/ui/reachable/expr_add.rs1
-rw-r--r--src/test/ui/reachable/expr_add.stderr4
-rw-r--r--src/test/ui/reachable/expr_array.rs3
-rw-r--r--src/test/ui/reachable/expr_array.stderr4
-rw-r--r--src/test/ui/reachable/expr_assign.rs1
-rw-r--r--src/test/ui/reachable/expr_assign.stderr6
-rw-r--r--src/test/ui/reachable/expr_block.rs1
-rw-r--r--src/test/ui/reachable/expr_block.stderr4
-rw-r--r--src/test/ui/reachable/expr_call.rs1
-rw-r--r--src/test/ui/reachable/expr_call.stderr4
-rw-r--r--src/test/ui/reachable/expr_cast.rs1
-rw-r--r--src/test/ui/reachable/expr_cast.stderr2
-rw-r--r--src/test/ui/reachable/expr_if.rs1
-rw-r--r--src/test/ui/reachable/expr_if.stderr2
-rw-r--r--src/test/ui/reachable/expr_loop.rs1
-rw-r--r--src/test/ui/reachable/expr_loop.stderr6
-rw-r--r--src/test/ui/reachable/expr_match.rs1
-rw-r--r--src/test/ui/reachable/expr_match.stderr6
-rw-r--r--src/test/ui/reachable/expr_method.rs1
-rw-r--r--src/test/ui/reachable/expr_method.stderr4
-rw-r--r--src/test/ui/reachable/expr_repeat.rs1
-rw-r--r--src/test/ui/reachable/expr_repeat.stderr2
-rw-r--r--src/test/ui/reachable/expr_return.rs1
-rw-r--r--src/test/ui/reachable/expr_return.stderr2
-rw-r--r--src/test/ui/reachable/expr_struct.rs1
-rw-r--r--src/test/ui/reachable/expr_struct.stderr8
-rw-r--r--src/test/ui/reachable/expr_tup.rs1
-rw-r--r--src/test/ui/reachable/expr_tup.stderr4
-rw-r--r--src/test/ui/reachable/expr_type.rs1
-rw-r--r--src/test/ui/reachable/expr_type.stderr2
-rw-r--r--src/test/ui/reachable/expr_unary.rs6
-rw-r--r--src/test/ui/reachable/expr_unary.stderr34
-rw-r--r--src/test/ui/reachable/expr_while.rs1
-rw-r--r--src/test/ui/reachable/expr_while.stderr6
147 files changed, 295 insertions, 547 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 6602643dc51..67445daa436 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -882,24 +882,24 @@ mod impls {
 
     ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-    #[unstable(feature = "never_type", issue = "35121")]
+    #[stable(feature = "never_type", since = "1.26.0")]
     impl PartialEq for ! {
         fn eq(&self, _: &!) -> bool {
             *self
         }
     }
 
-    #[unstable(feature = "never_type", issue = "35121")]
+    #[stable(feature = "never_type", since = "1.26.0")]
     impl Eq for ! {}
 
-    #[unstable(feature = "never_type", issue = "35121")]
+    #[stable(feature = "never_type", since = "1.26.0")]
     impl PartialOrd for ! {
         fn partial_cmp(&self, _: &!) -> Option<Ordering> {
             *self
         }
     }
 
-    #[unstable(feature = "never_type", issue = "35121")]
+    #[stable(feature = "never_type", since = "1.26.0")]
     impl Ord for ! {
         fn cmp(&self, _: &!) -> Ordering {
             *self
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 13db6d5d659..67126b496e2 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -1711,14 +1711,14 @@ macro_rules! fmt_refs {
 
 fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
 
-#[unstable(feature = "never_type", issue = "35121")]
+#[stable(feature = "never_type", since = "1.26.0")]
 impl Debug for ! {
     fn fmt(&self, _: &mut Formatter) -> Result {
         *self
     }
 }
 
-#[unstable(feature = "never_type", issue = "35121")]
+#[stable(feature = "never_type", since = "1.26.0")]
 impl Display for ! {
     fn fmt(&self, _: &mut Formatter) -> Result {
         *self
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index cefcc5ff03f..a947c9f0b7c 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -85,7 +85,7 @@
 #![feature(iterator_repeat_with)]
 #![feature(lang_items)]
 #![feature(link_llvm_intrinsics)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(no_core)]
 #![feature(on_unimplemented)]
 #![feature(optin_builtin_traits)]
@@ -103,6 +103,7 @@
 #![feature(unwind_attributes)]
 
 #![cfg_attr(stage0, allow(unused_attributes))]
+#![cfg_attr(stage0, feature(never_type))]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 4eb4f0edafe..bb3051b546e 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -886,9 +886,8 @@ for ty::TypeVariants<'gcx>
             TyGeneratorWitness(types) => {
                 types.hash_stable(hcx, hasher)
             }
-            TyTuple(inner_tys, from_diverging_type_var) => {
+            TyTuple(inner_tys) => {
                 inner_tys.hash_stable(hcx, hasher);
-                from_diverging_type_var.hash_stable(hcx, hasher);
             }
             TyProjection(ref projection_ty) => {
                 projection_ty.hash_stable(hcx, hasher);
diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs
index 9519baa3ff7..4e0cf59e8a7 100644
--- a/src/librustc/infer/canonical.rs
+++ b/src/librustc/infer/canonical.rs
@@ -609,12 +609,6 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
                 bug!("encountered a canonical type during canonicalization")
             }
 
-            // Replace a `()` that "would've fallen back" to `!` with just `()`.
-            ty::TyTuple(ref tys, true) => {
-                assert!(tys.is_empty());
-                self.tcx().mk_nil()
-            }
-
             ty::TyClosure(..)
             | ty::TyGenerator(..)
             | ty::TyGeneratorWitness(..)
@@ -634,7 +628,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
             | ty::TyFnPtr(_)
             | ty::TyDynamic(..)
             | ty::TyNever
-            | ty::TyTuple(_, false)
+            | ty::TyTuple(..)
             | ty::TyProjection(..)
             | ty::TyForeign(..)
             | ty::TyParam(..)
diff --git a/src/librustc/infer/outlives/bounds.rs b/src/librustc/infer/outlives/bounds.rs
index abb35d24d79..8bb3f4158ff 100644
--- a/src/librustc/infer/outlives/bounds.rs
+++ b/src/librustc/infer/outlives/bounds.rs
@@ -151,7 +151,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         // get solved *here*.
         match fulfill_cx.select_all_or_error(self) {
             Ok(()) => (),
-            Err(errors) => self.report_fulfillment_errors(&errors, None),
+            Err(errors) => self.report_fulfillment_errors(&errors, None, false),
         }
 
         implied_bounds
diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs
index 5e70c0ce368..77b722c5695 100644
--- a/src/librustc/infer/resolve.rs
+++ b/src/librustc/infer/resolve.rs
@@ -173,12 +173,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx>
                 ty::TyInfer(_) => {
                     bug!("Unexpected type in full type resolver: {:?}", t);
                 }
-                ty::TyTuple(tys, true) => {
-                    // Un-default defaulted tuples - we are going to a
-                    // different infcx, and the default will just cause
-                    // pollution.
-                    self.tcx().intern_tup(tys, false)
-                }
                 _ => {
                     t.super_fold_with(self)
                 }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 77b3a87c0ed..51882385b2e 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -60,7 +60,7 @@
 #![feature(match_default_bindings)]
 #![feature(macro_lifetime_matcher)]
 #![feature(macro_vis_matcher)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(non_exhaustive)]
 #![feature(nonzero)]
 #![feature(proc_macro_internals)]
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 8e1f76c5018..b4ed9c269bd 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -152,13 +152,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
-    Deny,
-    "attempt to resolve a trait on an expression whose type cannot be inferred but which \
-     currently defaults to ()"
-}
-
-declare_lint! {
     pub SAFE_EXTERN_STATICS,
     Deny,
     "safe access to extern statics was erroneously allowed"
@@ -238,12 +231,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    pub COERCE_NEVER,
-    Deny,
-    "detect coercion to !"
-}
-
-declare_lint! {
     pub SINGLE_USE_LIFETIME,
     Allow,
    "detects single use lifetimes"
@@ -304,7 +291,6 @@ impl LintPass for HardwiredLints {
             INVALID_TYPE_PARAM_DEFAULT,
             CONST_ERR,
             RENAMED_AND_REMOVED_LINTS,
-            RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
             SAFE_EXTERN_STATICS,
             SAFE_PACKED_BORROWS,
             PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -318,7 +304,6 @@ impl LintPass for HardwiredLints {
             DEPRECATED,
             UNUSED_UNSAFE,
             UNUSED_MUT,
-            COERCE_NEVER,
             SINGLE_USE_LIFETIME,
             TYVAR_BEHIND_RAW_POINTER,
             ELIDED_LIFETIME_IN_PATH,
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 30d63b8443e..6bf0c5d1ba3 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1298,7 +1298,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
           PatKind::Tuple(ref subpats, ddpos) => {
             // (p1, ..., pN)
             let expected_len = match self.pat_ty(&pat)?.sty {
-                ty::TyTuple(ref tys, _) => tys.len(),
+                ty::TyTuple(ref tys) => tys.len(),
                 ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index d779ccd1736..20902d91110 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -155,7 +155,7 @@ impl<'tcx> Rvalue<'tcx> {
                 let lhs_ty = lhs.ty(local_decls, tcx);
                 let rhs_ty = rhs.ty(local_decls, tcx);
                 let ty = op.ty(tcx, lhs_ty, rhs_ty);
-                tcx.intern_tup(&[ty, tcx.types.bool], false)
+                tcx.intern_tup(&[ty, tcx.types.bool])
             }
             Rvalue::UnaryOp(UnOp::Not, ref operand) |
             Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
@@ -178,10 +178,7 @@ impl<'tcx> Rvalue<'tcx> {
                         tcx.mk_array(ty, ops.len() as u64)
                     }
                     AggregateKind::Tuple => {
-                        tcx.mk_tup(
-                            ops.iter().map(|op| op.ty(local_decls, tcx)),
-                            false
-                        )
+                        tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx)))
                     }
                     AggregateKind::Adt(def, _, substs, _) => {
                         tcx.type_of(def.did).subst(tcx, substs)
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b8455b97fa4..206a4bf6689 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -47,7 +47,8 @@ use syntax_pos::{DUMMY_SP, Span};
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_fulfillment_errors(&self,
                                      errors: &Vec<FulfillmentError<'tcx>>,
-                                     body_id: Option<hir::BodyId>) {
+                                     body_id: Option<hir::BodyId>,
+                                     fallback_has_occurred: bool) {
         #[derive(Debug)]
         struct ErrorDescriptor<'tcx> {
             predicate: ty::Predicate<'tcx>,
@@ -107,7 +108,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
         for (error, suppressed) in errors.iter().zip(is_suppressed) {
             if !suppressed {
-                self.report_fulfillment_error(error, body_id);
+                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
             }
         }
     }
@@ -151,11 +152,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
-                                body_id: Option<hir::BodyId>) {
+                                body_id: Option<hir::BodyId>,
+                                fallback_has_occurred: bool) {
         debug!("report_fulfillment_errors({:?})", error);
         match error.code {
             FulfillmentErrorCode::CodeSelectionError(ref e) => {
-                self.report_selection_error(&error.obligation, e);
+                self.report_selection_error(&error.obligation, e, fallback_has_occurred);
             }
             FulfillmentErrorCode::CodeProjectionError(ref e) => {
                 self.report_projection_error(&error.obligation, e);
@@ -533,7 +535,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
     pub fn report_selection_error(&self,
                                   obligation: &PredicateObligation<'tcx>,
-                                  error: &SelectionError<'tcx>)
+                                  error: &SelectionError<'tcx>,
+                                  fallback_has_occurred: bool)
     {
         let span = obligation.cause.span;
 
@@ -619,6 +622,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                             self.report_similar_impl_candidates(impl_candidates, &mut err);
                         }
 
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occured, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
+                                {
+                                    let trait_ref = &mut trait_pred.trait_ref;
+                                    let never_substs = trait_ref.substs;
+                                    let mut unit_substs = Vec::with_capacity(never_substs.len());
+                                    unit_substs.push(self.tcx.mk_nil().into());
+                                    unit_substs.extend(&never_substs[1..]);
+                                    trait_ref.substs = self.tcx.intern_substs(&unit_substs);
+                                }
+                                trait_pred
+                            });
+                            let unit_obligation = Obligation {
+                                predicate: ty::Predicate::Trait(predicate),
+                                .. obligation.clone()
+                            };
+                            let mut selcx = SelectionContext::new(self);
+                            if selcx.evaluate_obligation(&unit_obligation) {
+                                err.note("the trait is implemented for `()`. \
+                                         Possibly this error has been caused by changes to \
+                                         Rust's type-inference algorithm \
+                                         (see: https://github.com/rust-lang/rust/issues/48950 \
+                                         for more info). Consider whether you meant to use the \
+                                         type `()` here instead.");
+                            }
+                        }
+
                         err
                     }
 
@@ -729,14 +765,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 }).map(|sp| self.tcx.sess.codemap().def_span(sp)); // the sp could be an fn def
 
                 let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
-                    ty::TyTuple(ref tys, _) => tys.iter()
+                    ty::TyTuple(ref tys) => tys.iter()
                         .map(|_| ArgKind::empty()).collect::<Vec<_>>(),
                     _ => vec![ArgKind::empty()],
                 };
                 let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
-                    ty::TyTuple(ref tys, _) => tys.iter()
+                    ty::TyTuple(ref tys) => tys.iter()
                         .map(|t| match t.sty {
-                            ty::TypeVariants::TyTuple(ref tys, _) => ArgKind::Tuple(
+                            ty::TypeVariants::TyTuple(ref tys) => ArgKind::Tuple(
                                 Some(span),
                                 tys.iter()
                                     .map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
@@ -986,7 +1022,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
                                                trait_ref: &ty::TraitRef<'tcx>) -> String {
             let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::TyTuple(inputs, _) = inputs.sty {
+            let sig = if let ty::TyTuple(inputs) = inputs.sty {
                 tcx.mk_fn_sig(
                     inputs.iter().map(|&x| x),
                     tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
@@ -1422,7 +1458,7 @@ impl ArgKind {
     /// argument. This has no name (`_`) and no source spans..
     pub fn from_expected_ty(t: Ty<'_>) -> ArgKind {
         match t.sty {
-            ty::TyTuple(ref tys, _) => ArgKind::Tuple(
+            ty::TyTuple(ref tys) => ArgKind::Tuple(
                 None,
                 tys.iter()
                    .map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index bb2c7977f26..150a2ead9e9 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -330,11 +330,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
             if data.is_global() {
                 // no type variables present, can use evaluation for better caching.
                 // FIXME: consider caching errors too.
-                if
-                    // make defaulted unit go through the slow path for better warnings,
-                    // please remove this when the warnings are removed.
-                    !trait_obligation.predicate.skip_binder().self_ty().is_defaulted_unit() &&
-                    selcx.evaluate_obligation_conservatively(&obligation) {
+                if selcx.evaluate_obligation_conservatively(&obligation) {
                     debug!("selecting trait `{:?}` at depth {} evaluated to holds",
                            data, obligation.recursion_depth);
                     return Ok(Some(vec![]))
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index a2a5aa246cf..bd8f99780f9 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -580,7 +580,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ) {
             Ok(predicates) => predicates,
             Err(errors) => {
-                infcx.report_fulfillment_errors(&errors, None);
+                infcx.report_fulfillment_errors(&errors, None, false);
                 // An unnormalized env is better than nothing.
                 return elaborated_env;
             }
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 0fe4daa36ed..1caab6fd89e 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -236,7 +236,7 @@ fn trivial_dropck_outlives<'cx, 'tcx>(tcx: TyCtxt<'cx, '_, 'tcx>, ty: Ty<'tcx>)
 
         // (T1..Tn) and closures have same properties as T1..Tn --
         // check if *any* of those are trivial.
-        ty::TyTuple(ref tys, _) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)),
+        ty::TyTuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)),
         ty::TyClosure(def_id, ref substs) => substs
             .upvar_tys(def_id, tcx)
             .all(|t| trivial_dropck_outlives(tcx, t)),
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index f2f54dcedfd..4db81cf1dec 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -53,7 +53,6 @@ use std::mem;
 use std::rc::Rc;
 use syntax::abi::Abi;
 use hir;
-use lint;
 use util::nodemap::{FxHashMap, FxHashSet};
 
 
@@ -526,54 +525,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         debug!("select({:?})", obligation);
         assert!(!obligation.predicate.has_escaping_regions());
 
-        let tcx = self.tcx();
-
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
         let ret = match self.candidate_from_obligation(&stack)? {
             None => None,
             Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?)
         };
 
-        // Test whether this is a `()` which was produced by defaulting a
-        // diverging type variable with `!` disabled. If so, we may need
-        // to raise a warning.
-        if obligation.predicate.skip_binder().self_ty().is_defaulted_unit() {
-            let mut raise_warning = true;
-            // Don't raise a warning if the trait is implemented for ! and only
-            // permits a trivial implementation for !. This stops us warning
-            // about (for example) `(): Clone` becoming `!: Clone` because such
-            // a switch can't cause code to stop compiling or execute
-            // differently.
-            let mut never_obligation = obligation.clone();
-            let def_id = never_obligation.predicate.skip_binder().trait_ref.def_id;
-            never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| {
-                // Swap out () with ! so we can check if the trait is impld for !
-                {
-                    let trait_ref = &mut trait_pred.trait_ref;
-                    let unit_substs = trait_ref.substs;
-                    let mut never_substs = Vec::with_capacity(unit_substs.len());
-                    never_substs.push(tcx.types.never.into());
-                    never_substs.extend(&unit_substs[1..]);
-                    trait_ref.substs = tcx.intern_substs(&never_substs);
-                }
-                trait_pred
-            });
-            if let Ok(Some(..)) = self.select(&never_obligation) {
-                if !tcx.trait_relevant_for_never(def_id) {
-                    // The trait is also implemented for ! and the resulting
-                    // implementation cannot actually be invoked in any way.
-                    raise_warning = false;
-                }
-            }
-
-            if raise_warning {
-                tcx.lint_node(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
-                              obligation.cause.body_id,
-                              obligation.cause.span,
-                              &format!("code relies on type inference rules which are likely \
-                                        to change"));
-            }
-        }
         Ok(ret)
     }
 
@@ -1929,7 +1886,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             // (.., T) -> (.., U).
-            (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => {
+            (&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => {
                 tys_a.len() == tys_b.len()
             }
 
@@ -2068,7 +2025,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never,
 
-            ty::TyTuple(tys, _) => {
+            ty::TyTuple(tys) => {
                 Where(ty::Binder(tys.last().into_iter().cloned().collect()))
             }
 
@@ -2122,7 +2079,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 Where(ty::Binder(vec![element_ty]))
             }
 
-            ty::TyTuple(tys, _) => {
+            ty::TyTuple(tys) => {
                 // (*) binder moved here
                 Where(ty::Binder(tys.to_vec()))
             }
@@ -2215,7 +2172,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 vec![element_ty]
             }
 
-            ty::TyTuple(ref tys, _) => {
+            ty::TyTuple(ref tys) => {
                 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
                 tys.to_vec()
             }
@@ -3004,7 +2961,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             // (.., T) -> (.., U).
-            (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => {
+            (&ty::TyTuple(tys_a), &ty::TyTuple(tys_b)) => {
                 assert_eq!(tys_a.len(), tys_b.len());
 
                 // The last field of the tuple has to exist.
@@ -3017,7 +2974,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
                 // Check that the source tuple with the target's
                 // last element is equal to the target.
-                let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false);
+                let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)));
                 let InferOk { obligations, .. } =
                     self.infcx.at(&obligation.cause, obligation.param_env)
                               .eq(target, new_tuple)
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index c562f2cd48d..8f7a2405747 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -503,7 +503,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let arguments_tuple = match tuple_arguments {
             TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
             TupleArgumentsFlag::Yes =>
-                self.intern_tup(sig.skip_binder().inputs(), false),
+                self.intern_tup(sig.skip_binder().inputs()),
         };
         let trait_ref = ty::TraitRef {
             def_id: fn_trait_def_id,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 9a687028b58..fd3465f59eb 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2014,7 +2014,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
         let converted_sig = sig.map_bound(|s| {
             let params_iter = match s.inputs()[0].sty {
-                ty::TyTuple(params, _) => {
+                ty::TyTuple(params) => {
                     params.into_iter().cloned()
                 }
                 _ => bug!(),
@@ -2134,25 +2134,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.mk_ty(TySlice(ty))
     }
 
-    pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> {
-        self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))
+    pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
+        self.mk_ty(TyTuple(self.intern_type_list(ts)))
     }
 
-    pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I,
-                                                     defaulted: bool) -> I::Output {
-        iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)))
+    pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
+        iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
     }
 
     pub fn mk_nil(self) -> Ty<'tcx> {
-        self.intern_tup(&[], false)
-    }
-
-    pub fn mk_diverging_default(self) -> Ty<'tcx> {
-        if self.features().never_type {
-            self.types.never
-        } else {
-            self.intern_tup(&[], true)
-        }
+        self.intern_tup(&[])
     }
 
     pub fn mk_bool(self) -> Ty<'tcx> {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 8a0253ed2f1..eb392418647 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -177,7 +177,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
         match self.sty {
             ty::TyBool | ty::TyChar | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
-            ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
+            ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
 
             ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
             ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 93d8a4d979d..6533a7440ac 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -97,7 +97,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
         }
         ty::TyNever => Some(NeverSimplifiedType),
-        ty::TyTuple(ref tys, _) => {
+        ty::TyTuple(ref tys) => {
             Some(TupleSimplifiedType(tys.len()))
         }
         ty::TyFnPtr(ref f) => {
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index cae64fd4c95..086fc66c70f 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -179,10 +179,7 @@ impl FlagComputation {
                 self.add_ty(m.ty);
             }
 
-            &ty::TyTuple(ref ts, is_default) => {
-                if is_default {
-                    self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX);
-                }
+            &ty::TyTuple(ref ts) => {
                 self.add_tys(&ts[..]);
             }
 
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 3e653cf126a..325f8575fd0 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -256,7 +256,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
             },
 
             TyNever => DefIdForest::full(tcx),
-            TyTuple(ref tys, _) => {
+            TyTuple(ref tys) => {
                 DefIdForest::union(tcx, tys.iter().map(|ty| {
                     ty.uninhabited_from(visited, tcx)
                 }))
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index fefd11eecf4..1f23b0a27e3 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -355,9 +355,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
         ty::TyRawPtr(mt) |
         ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty),
 
-        ty::TyTuple(ref tys, _) => tys.iter()
-                                      .filter_map(|ty| characteristic_def_id_of_type(ty))
-                                      .next(),
+        ty::TyTuple(ref tys) => tys.iter()
+                                   .filter_map(|ty| characteristic_def_id_of_type(ty))
+                                   .next(),
 
         ty::TyFnDef(def_id, _) |
         ty::TyClosure(def_id, _) |
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 04353d2ece1..3a3f10cb87d 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1318,7 +1318,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     StructKind::AlwaysSized)?
             }
 
-            ty::TyTuple(tys, _) => {
+            ty::TyTuple(tys) => {
                 let kind = if tys.len() == 0 {
                     StructKind::AlwaysSized
                 } else {
@@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TyLayout<'tcx> {
                 substs.field_tys(def_id, tcx).nth(i).unwrap()
             }
 
-            ty::TyTuple(tys, _) => tys[i],
+            ty::TyTuple(tys) => tys[i],
 
             // SIMD vector types.
             ty::TyAdt(def, ..) if def.repr.simd() => {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index fc1d26b0e09..09b11a36352 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2046,7 +2046,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 vec![ty]
             }
 
-            TyTuple(ref tys, _) => {
+            TyTuple(ref tys) => {
                 match tys.last() {
                     None => vec![],
                     Some(ty) => self.sized_constraint_for_ty(tcx, ty)
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 72e7d16b64d..36eb3e3f94c 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -529,11 +529,10 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_slice(t))
         }
 
-        (&ty::TyTuple(as_, a_defaulted), &ty::TyTuple(bs, b_defaulted)) =>
+        (&ty::TyTuple(as_), &ty::TyTuple(bs)) =>
         {
             if as_.len() == bs.len() {
-                let defaulted = a_defaulted || b_defaulted;
-                Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)), defaulted)?)
+                Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
             } else if !(as_.is_empty() || bs.is_empty()) {
                 Err(TypeError::TupleSize(
                     expected_found(relation, &as_.len(), &bs.len())))
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 0627bcdfb0e..c9a69d5405c 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -869,7 +869,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
             ty::TyDynamic(ref trait_ty, ref region) =>
                 ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
-            ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
+            ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
             ty::TyFnDef(def_id, substs) => {
                 ty::TyFnDef(def_id, substs.fold_with(folder))
             }
@@ -908,7 +908,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyAdt(_, substs) => substs.visit_with(visitor),
             ty::TyDynamic(ref trait_ty, ref reg) =>
                 trait_ty.visit_with(visitor) || reg.visit_with(visitor),
-            ty::TyTuple(ts, _) => ts.visit_with(visitor),
+            ty::TyTuple(ts) => ts.visit_with(visitor),
             ty::TyFnDef(_, substs) => substs.visit_with(visitor),
             ty::TyFnPtr(ref f) => f.visit_with(visitor),
             ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 109422564c8..ae053d7f4f5 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -148,11 +148,7 @@ pub enum TypeVariants<'tcx> {
     TyNever,
 
     /// A tuple type.  For example, `(i32, bool)`.
-    /// The bool indicates whether this is a unit tuple and was created by
-    /// defaulting a diverging type variable with feature(never_type) disabled.
-    /// It's only purpose is for raising future-compatibility warnings for when
-    /// diverging type variables start defaulting to ! instead of ().
-    TyTuple(&'tcx Slice<Ty<'tcx>>, bool),
+    TyTuple(&'tcx Slice<Ty<'tcx>>),
 
     /// The projection of an associated type.  For example,
     /// `<T as Trait<..>>::N`.
@@ -1274,7 +1270,7 @@ impl RegionKind {
 impl<'a, 'gcx, 'tcx> TyS<'tcx> {
     pub fn is_nil(&self) -> bool {
         match self.sty {
-            TyTuple(ref tys, _) => tys.is_empty(),
+            TyTuple(ref tys) => tys.is_empty(),
             _ => false,
         }
     }
@@ -1286,15 +1282,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         }
     }
 
-    /// Test whether this is a `()` which was produced by defaulting a
-    /// diverging type variable with feature(never_type) disabled.
-    pub fn is_defaulted_unit(&self) -> bool {
-        match self.sty {
-            TyTuple(_, true) => true,
-            _ => false,
-        }
-    }
-
     pub fn is_primitive(&self) -> bool {
         match self.sty {
             TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 753f89d8cd2..91d460a96f7 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -269,7 +269,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 // Don't use `non_enum_variant`, this may be a univariant enum.
                 adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
             }
-            (&TyTuple(ref v, _), None) => v.get(i).cloned(),
+            (&TyTuple(ref v), None) => v.get(i).cloned(),
             _ => None,
         }
     }
@@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     }
                 }
 
-                ty::TyTuple(tys, _) => {
+                ty::TyTuple(tys) => {
                     if let Some((&last_ty, _)) = tys.split_last() {
                         ty = last_ty;
                     } else {
@@ -344,7 +344,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                         break;
                     }
                 },
-                (&TyTuple(a_tys, _), &TyTuple(b_tys, _))
+                (&TyTuple(a_tys), &TyTuple(b_tys))
                         if a_tys.len() == b_tys.len() => {
                     if let Some(a_last) = a_tys.last() {
                         a = a_last;
@@ -709,9 +709,8 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
             TyGeneratorWitness(tys) => {
                 self.hash(tys.skip_binder().len());
             }
-            TyTuple(tys, defaulted) => {
+            TyTuple(tys) => {
                 self.hash(tys.len());
-                self.hash(defaulted);
             }
             TyParam(p) => {
                 self.hash(p.idx);
@@ -838,7 +837,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
             -> Representability
         {
             match ty.sty {
-                TyTuple(ref ts, _) => {
+                TyTuple(ref ts) => {
                     // Find non representable
                     fold_repr(ts.iter().map(|ty| {
                         is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
@@ -1106,7 +1105,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // state transformation pass
         ty::TyGenerator(..) => true,
 
-        ty::TyTuple(ref tys, _) => tys.iter().cloned().any(needs_drop),
+        ty::TyTuple(ref tys) => tys.iter().cloned().any(needs_drop),
 
         // unions don't have destructors regardless of the child types
         ty::TyAdt(def, _) if def.is_union() => false,
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index 722fdfe773a..46c048e839b 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -125,7 +125,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyGeneratorWitness(ts) => {
             stack.extend(ts.skip_binder().iter().cloned().rev());
         }
-        ty::TyTuple(ts, _) => {
+        ty::TyTuple(ts) => {
             stack.extend(ts.iter().cloned().rev());
         }
         ty::TyFnDef(_, substs) => {
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 49ae79ae9c9..f05d56c9d83 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -275,7 +275,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                     self.compute_const(len);
                 }
 
-                ty::TyTuple(ref tys, _) => {
+                ty::TyTuple(ref tys) => {
                     if let Some((_last, rest)) = tys.split_last() {
                         for elem in rest {
                             self.require_sized(elem, traits::TupleElem);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index efa53c775ae..2c3ee1ec285 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -340,7 +340,7 @@ impl PrintContext {
 
         if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
             let projection_ty = projections[0].ty;
-            if let TyTuple(ref args, _) = substs.type_at(1).sty {
+            if let TyTuple(ref args) = substs.type_at(1).sty {
                 return self.fn_sig(f, args, false, projection_ty);
             }
         }
@@ -1013,7 +1013,7 @@ define_print! {
                     tm.print(f, cx)
                 }
                 TyNever => write!(f, "!"),
-                TyTuple(ref tys, _) => {
+                TyTuple(ref tys) => {
                     write!(f, "(")?;
                     let mut tys = tys.iter();
                     if let Some(&ty) = tys.next() {
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index fb48f900be5..97577008377 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -298,7 +298,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
     }
 
     pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx.tcx.intern_tup(&[ty1, ty2], false)
+        self.infcx.tcx.intern_tup(&[ty1, ty2])
     }
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
@@ -604,8 +604,8 @@ fn walk_ty() {
         let tcx = env.infcx.tcx;
         let int_ty = tcx.types.isize;
         let usize_ty = tcx.types.usize;
-        let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty], false);
-        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty], false);
+        let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty]);
+        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty]);
         let walked: Vec<_> = tup2_ty.walk().collect();
         assert_eq!(walked,
                    [tup2_ty, tup1_ty, int_ty, usize_ty, int_ty, usize_ty, tup1_ty, int_ty,
@@ -619,8 +619,8 @@ fn walk_ty_skip_subtree() {
         let tcx = env.infcx.tcx;
         let int_ty = tcx.types.isize;
         let usize_ty = tcx.types.usize;
-        let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty], false);
-        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty], false);
+        let tup1_ty = tcx.intern_tup(&[int_ty, usize_ty, int_ty, usize_ty]);
+        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, usize_ty]);
 
         // types we expect to see (in order), plus a boolean saying
         // whether to skip the subtree.
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 779aa3a9037..8b86c905489 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -32,6 +32,7 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(never_type))]
 
 #[macro_use]
 extern crate syntax;
@@ -235,11 +236,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             epoch: None,
         },
         FutureIncompatibleInfo {
-            id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
-            reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
-            epoch: None,
-        },
-        FutureIncompatibleInfo {
             id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
             reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
             epoch: None,
@@ -275,11 +271,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             epoch: None,
         },
         FutureIncompatibleInfo {
-            id: LintId::of(COERCE_NEVER),
-            reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
-            epoch: None,
-        },
-        FutureIncompatibleInfo {
             id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
             reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
             epoch: Some(Epoch::Epoch2018),
@@ -315,4 +306,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
         "converted into hard error, see https://github.com/rust-lang/rust/issues/36892");
     store.register_removed("extra_requirement_in_impl",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/37166");
+    store.register_removed("coerce_never",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/48950");
+    store.register_removed("resolve_trait_on_defaulted_unit",
+        "converted into hard error, see https://github.com/rust-lang/rust/issues/48950");
 }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 6ab3172c4fe..d777f6f19b0 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
 
         let t = cx.tables.expr_ty(&expr);
         let ty_warned = match t.sty {
-            ty::TyTuple(ref tys, _) if tys.is_empty() => return,
+            ty::TyTuple(ref tys) if tys.is_empty() => return,
             ty::TyNever => return,
             ty::TyAdt(def, _) => {
                 if def.variants.is_empty() {
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 84ba1367450..56371d809b2 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -789,7 +789,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 } else {
                     format!("{}", def.non_enum_variant().fields[field.index()].name)
                 },
-                ty::TyTuple(_, _) => format!("{}", field.index()),
+                ty::TyTuple(_) => format!("{}", field.index()),
                 ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => {
                     self.describe_field_from_ty(&tnm.ty, field)
                 }
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 06e6be5cd56..022831b5a92 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -542,7 +542,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         }),
                     };
                 }
-                ty::TyTuple(tys, _) => {
+                ty::TyTuple(tys) => {
                     return match tys.get(field.index()) {
                         Some(&ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 668172749fe..afd33858139 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -635,7 +635,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
                         let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap();
                         assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
                         let inputs = match tuplized_inputs[0].sty {
-                            ty::TyTuple(inputs, _) => inputs,
+                            ty::TyTuple(inputs) => inputs,
                             _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]),
                         };
 
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 1a9064aab1b..b7f402f61a9 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -298,7 +298,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let source_info = self.source_info(span);
         let bool_ty = self.hir.bool_ty();
         if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() {
-            let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false);
+            let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]);
             let result_value = self.temp(result_tup, span);
 
             self.cfg.push_assign(block, source_info,
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index abea5583546..4e95ee6444d 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
                 let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
                     i == variant_index || {
-                        self.hir.tcx().features().never_type &&
+                        self.hir.tcx().features().exhaustive_patterns &&
                         self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
                     }
                 });
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index da25969bf11..62d1b43d625 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -227,7 +227,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
                 let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
                 let tupled_args = Expr {
-                    ty: cx.tcx.mk_tup(arg_tys, false),
+                    ty: cx.tcx.mk_tup(arg_tys),
                     temp_lifetime,
                     span: expr.span,
                     kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() },
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index a3295aac801..6f8b1f8e799 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -219,7 +219,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
     }
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
-        if self.tcx.features().never_type {
+        if self.tcx.features().exhaustive_patterns {
             self.tcx.is_ty_uninhabited_from(self.module, ty)
         } else {
             false
@@ -245,7 +245,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
                               substs: &'tcx ty::subst::Substs<'tcx>)
                               -> bool
     {
-        if self.tcx.features().never_type {
+        if self.tcx.features().exhaustive_patterns {
             self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
         } else {
             false
@@ -694,7 +694,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         // test for details.
         //
         // FIXME: currently the only way I know of something can
-        // be a privately-empty enum is when the never_type
+        // be a privately-empty enum is when the exhaustive_patterns
         // feature flag is not present, so this is only
         // needed for that case.
 
@@ -877,7 +877,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
 fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> u64 {
     debug!("constructor_arity({:#?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::TyTuple(ref fs, _) => fs.len() as u64,
+        ty::TyTuple(ref fs) => fs.len() as u64,
         ty::TySlice(..) | ty::TyArray(..) => match *ctor {
             Slice(length) => length,
             ConstantValue(_) => 0,
@@ -901,7 +901,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
 {
     debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(),
+        ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(),
         ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor {
             Slice(length) => (0..length).map(|_| ty).collect(),
             ConstantValue(_) => vec![],
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 69ed4e6064f..d924baaf005 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -222,7 +222,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             let pat_ty = self.tables.node_id_to_type(scrut.hir_id);
             let module = self.tcx.hir.get_module_parent(scrut.id);
             if inlined_arms.is_empty() {
-                let scrutinee_is_uninhabited = if self.tcx.features().never_type {
+                let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
                     self.tcx.is_ty_uninhabited_from(module, pat_ty)
                 } else {
                     self.conservative_is_uninhabited(pat_ty)
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 1774c95af0f..eb87d5b044b 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -449,7 +449,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             PatKind::Tuple(ref subpatterns, ddpos) => {
                 let ty = self.tables.node_id_to_type(pat.hir_id);
                 match ty.sty {
-                    ty::TyTuple(ref tys, _) => {
+                    ty::TyTuple(ref tys) => {
                         let subpatterns =
                             subpatterns.iter()
                                        .enumerate_and_adjust(tys.len(), ddpos)
@@ -879,7 +879,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                     subpatterns: adt_subpatterns(struct_var.fields.len(), None),
                 }
             }
-            ty::TyTuple(fields, _) => {
+            ty::TyTuple(fields) => {
                 PatternKind::Leaf {
                     subpatterns: adt_subpatterns(fields.len(), None),
                 }
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index be34b8705eb..851fac532e3 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -234,7 +234,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                     // Second argument must be a tuple matching the argument list of sig
                     let snd_ty = real_sig.inputs_and_output[1];
                     match snd_ty.sty {
-                        ty::TyTuple(tys, _) if sig.inputs().len() == tys.len() =>
+                        ty::TyTuple(tys) if sig.inputs().len() == tys.len() =>
                             if sig.inputs().iter().zip(tys).all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) {
                                 return Ok(true)
                             },
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index c31e95fd826..5510e219780 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -32,13 +32,14 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(inclusive_range)]
 #![feature(macro_vis_matcher)]
 #![feature(match_default_bindings)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(placement_in_syntax)]
 #![feature(collection_placement)]
 #![feature(nonzero)]
 #![feature(underscore_lifetimes)]
+#![cfg_attr(stage0, feature(never_type))]
 
 extern crate arena;
 #[macro_use]
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 10e2a84038d..c2f4359c008 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -281,7 +281,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
                 self.push_def_path(adt_def.did, output);
                 self.push_type_params(substs, iter::empty(), output);
             },
-            ty::TyTuple(component_types, _) => {
+            ty::TyTuple(component_types) => {
                 output.push('(');
                 for &component_type in component_types {
                     self.push_type_name(component_type, output);
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 62af09cc491..6a0f42c6dbb 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -312,7 +312,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 substs.upvar_tys(def_id, tcx)
             )
         }
-        ty::TyTuple(tys, _) => builder.tuple_like_shim(dest, src, tys.iter().cloned()),
+        ty::TyTuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()),
         _ => {
             bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty)
         }
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 6380d2a5c15..2dd805ccf9b 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -599,7 +599,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             assert!(args.next().is_none());
 
             let tuple = Place::Local(tuple);
-            let tuple_tys = if let ty::TyTuple(s, _) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
+            let tuple_tys = if let ty::TyTuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
                 s
             } else {
                 bug!("Closure arguments are not passed as a tuple");
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 94446a98e63..59a872a23b0 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1246,7 +1246,7 @@ impl MirPass for QualifyAndPromoteConstants {
                                               tcx.require_lang_item(lang_items::SyncTraitLangItem),
                                               cause);
                 if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                    infcx.report_fulfillment_errors(&err, None);
+                    infcx.report_fulfillment_errors(&err, None, false);
                 }
             });
         }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 3f5208dd2d4..e95126c8a1a 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -788,7 +788,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
                 self.open_drop_for_tuple(&tys)
             }
-            ty::TyTuple(tys, _) => {
+            ty::TyTuple(tys) => {
                 self.open_drop_for_tuple(tys)
             }
             ty::TyAdt(def, _) if def.is_box() => {
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 2274f3942bd..2a8cfe5cc06 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -184,7 +184,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety)
         }
 
-        ty::TyTuple(tys, _) => tys.iter()
+        ty::TyTuple(tys) => tys.iter()
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index c1dc8c6684a..4a98fff6af7 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -722,7 +722,7 @@ impl<'a, 'tcx> FnType<'tcx> {
             assert!(!sig.variadic && extra_args.is_empty());
 
             match sig.inputs().last().unwrap().sty {
-                ty::TyTuple(ref tupled_arguments, _) => {
+                ty::TyTuple(ref tupled_arguments) => {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
                     tupled_arguments
                 }
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 20cc57522b5..f3d95cf794b 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -362,7 +362,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     // return type
     signature_metadata.push(match signature.output().sty {
-        ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(),
+        ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
         _ => type_metadata(cx, signature.output(), span)
     });
 
@@ -533,7 +533,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::TyFloat(_) => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
-        ty::TyTuple(ref elements, _) if elements.is_empty() => {
+        ty::TyTuple(ref elements) if elements.is_empty() => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
         ty::TyArray(typ, _) |
@@ -621,7 +621,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                     usage_site_span).finalize(cx)
             }
         },
-        ty::TyTuple(ref elements, _) => {
+        ty::TyTuple(ref elements) => {
             prepare_tuple_metadata(cx,
                                    t,
                                    &elements[..],
@@ -731,7 +731,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     let (name, encoding) = match t.sty {
         ty::TyNever => ("!", DW_ATE_unsigned),
-        ty::TyTuple(ref elements, _) if elements.is_empty() =>
+        ty::TyTuple(ref elements) if elements.is_empty() =>
             ("()", DW_ATE_unsigned),
         ty::TyBool => ("bool", DW_ATE_boolean),
         ty::TyChar => ("char", DW_ATE_unsigned_char),
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index c13b91eb3b6..7664c88679e 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -312,7 +312,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         // Return type -- llvm::DIBuilder wants this at index 0
         signature.push(match sig.output().sty {
-            ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(),
+            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
             _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)
         });
 
@@ -351,7 +351,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         }
 
         if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
-            if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty {
+            if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
                 for &argument_type in args {
                     signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP));
                 }
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 211de95c96e..96ed4e88471 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -53,7 +53,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             push_item_name(cx, def.did, qualified, output);
             push_type_params(cx, substs, output);
         },
-        ty::TyTuple(component_types, _) => {
+        ty::TyTuple(component_types) => {
             output.push('(');
             for &component_type in component_types {
                 push_debuginfo_type_name(cx, component_type, true, output);
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 96c5bb3b91d..93bc89f0914 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -710,7 +710,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
             let layout = cx.layout_of(cx.tcx.intern_tup(&[
                 cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
                 cx.tcx.types.i32
-            ], false));
+            ]));
             let slot = PlaceRef::alloca(bx, layout, "personalityslot");
             self.personality_slot = Some(slot);
             slot
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 0533b04a0c1..11dabbeae74 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -448,7 +448,7 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
             let arg_ty = fx.monomorphize(&arg_decl.ty);
             let tupled_arg_tys = match arg_ty.sty {
-                ty::TyTuple(ref tys, _) => tys,
+                ty::TyTuple(ref tys) => tys,
                 _ => bug!("spread argument isn't a tuple?!")
             };
 
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index fa0514952d2..93702bfbbf3 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -399,7 +399,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                                                              lhs.immediate(), rhs.immediate(),
                                                              lhs.layout.ty);
                 let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
-                let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool], false);
+                let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool]);
                 let operand = OperandRef {
                     val: result,
                     layout: bx.cx.layout_of(operand_ty)
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 0df1225cf26..827ca79334c 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1050,7 +1050,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 tcx.types.never
             },
             hir::TyTup(ref fields) => {
-                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)), false)
+                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
             }
             hir::TyBareFn(ref bf) => {
                 require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index eb02c05fd39..379fd93ba2b 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -319,7 +319,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let mut expected_len = elements.len();
                 if ddpos.is_some() {
                     // Require known type only when `..` is present
-                    if let ty::TyTuple(ref tys, _) =
+                    if let ty::TyTuple(ref tys) =
                             self.structurally_resolved_type(pat.span, expected).sty {
                         expected_len = tys.len();
                     }
@@ -332,7 +332,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     ty::UniverseIndex::ROOT,
                     TypeVariableOrigin::TypeInference(pat.span)));
                 let element_tys = tcx.mk_type_list(element_tys_iter);
-                let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
+                let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
                 self.demand_eqtype(pat.span, expected, pat_ty);
                 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
                     self.check_pat_walk(elem, &element_tys[i], def_bm, true);
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 48bd7b14fc9..e4bad8349ea 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -38,7 +38,7 @@
 //! expression, `e as U2` is not necessarily so (in fact it will only be valid if
 //! `U1` coerces to `U2`).
 
-use super::{Diverges, FnCtxt};
+use super::FnCtxt;
 
 use errors::DiagnosticBuilder;
 use hir::def_id::DefId;
@@ -59,7 +59,6 @@ use util::common::ErrorReported;
 pub struct CastCheck<'tcx> {
     expr: &'tcx hir::Expr,
     expr_ty: Ty<'tcx>,
-    expr_diverges: Diverges,
     cast_ty: Ty<'tcx>,
     cast_span: Span,
     span: Span,
@@ -115,7 +114,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     }
                 }
             }
-            ty::TyTuple(fields, _) => match fields.last() {
+            ty::TyTuple(fields) => match fields.last() {
                 None => Some(PointerKind::Thin),
                 Some(f) => self.pointer_kind(f, span)?
             },
@@ -183,7 +182,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
     pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                expr: &'tcx hir::Expr,
                expr_ty: Ty<'tcx>,
-               expr_diverges: Diverges,
                cast_ty: Ty<'tcx>,
                cast_span: Span,
                span: Span)
@@ -191,7 +189,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
         let check = CastCheck {
             expr,
             expr_ty,
-            expr_diverges,
             cast_ty,
             cast_span,
             span,
@@ -437,7 +434,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                     let f = self.expr_ty.fn_sig(fcx.tcx);
                     let res = fcx.try_coerce(self.expr,
                                              self.expr_ty,
-                                             self.expr_diverges,
                                              fcx.tcx.mk_fn_ptr(f));
                     if !res.is_ok() {
                         return Err(CastError::NonScalar);
@@ -620,7 +616,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
     }
 
     fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool {
-        fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, self.cast_ty).is_ok()
+        fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty).is_ok()
     }
 }
 
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 72e4b726a22..562c0cb1b8d 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -140,7 +140,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // the `closures` table.
         let sig = bound_sig.map_bound(|sig| {
             self.tcx.mk_fn_sig(
-                iter::once(self.tcx.intern_tup(sig.inputs(), false)),
+                iter::once(self.tcx.intern_tup(sig.inputs())),
                 sig.output(),
                 sig.variadic,
                 sig.unsafety,
@@ -312,7 +312,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         );
 
         let input_tys = match arg_param_ty.sty {
-            ty::TyTuple(tys, _) => tys.into_iter(),
+            ty::TyTuple(tys) => tys.into_iter(),
             _ => {
                 return None;
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index abb0acd699c..269ee49f38e 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -66,7 +66,6 @@ use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer::{Coercion, InferResult, InferOk};
 use rustc::infer::type_variable::TypeVariableOrigin;
-use rustc::lint;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
@@ -572,7 +571,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
 
                 // Object safety violations or miscellaneous.
                 Err(err) => {
-                    self.report_selection_error(&obligation, &err);
+                    self.report_selection_error(&obligation, &err, false);
                     // Treat this like an obligation and follow through
                     // with the unsizing - the lack of a coercion should
                     // be silent, as it causes a type mismatch later.
@@ -752,27 +751,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn try_coerce(&self,
                       expr: &hir::Expr,
                       expr_ty: Ty<'tcx>,
-                      expr_diverges: Diverges,
                       target: Ty<'tcx>)
                       -> RelateResult<'tcx, Ty<'tcx>> {
         let source = self.resolve_type_vars_with_obligations(expr_ty);
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
-        // Special-ish case: we can coerce any type `T` into the `!`
-        // type, but only if the source expression diverges.
-        if target.is_never() && expr_diverges.always() {
-            debug!("permit coercion to `!` because expr diverges");
-            if self.can_eq(self.param_env, source, target).is_err() {
-                self.tcx.lint_node(
-                    lint::builtin::COERCE_NEVER,
-                    expr.id,
-                    expr.span,
-                    &format!("cannot coerce `{}` to !", source)
-                );
-                return Ok(target);
-            }
-        }
-
         let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
         let coerce = Coerce::new(self, cause);
         let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
@@ -1123,7 +1106,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
             if self.pushed == 0 {
                 // Special-case the first expression we are coercing.
                 // To be honest, I'm not entirely sure why we do this.
-                fcx.try_coerce(expression, expression_ty, expression_diverges, self.expected_ty)
+                fcx.try_coerce(expression, expression_ty, self.expected_ty)
             } else {
                 match self.expressions {
                     Expressions::Dynamic(ref exprs) =>
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index b6459b62410..60ac31ac8eb 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -334,7 +334,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None);
+            infcx.report_fulfillment_errors(errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -839,7 +839,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None);
+            infcx.report_fulfillment_errors(errors, None, false);
             return;
         }
 
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index d2702d0810e..634a7ee5699 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                               -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
         let expected = self.resolve_type_vars_with_obligations(expected);
 
-        let e = match self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
+        let e = match self.try_coerce(expr, checked_ty, expected) {
             Ok(ty) => return (ty, None),
             Err(e) => e
         };
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 67c9832cbf9..596381d7ea6 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -112,7 +112,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
 
         if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(errors, None);
+            infcx.report_fulfillment_errors(errors, None, false);
             return Err(ErrorReported);
         }
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 2e00040d99a..59cf8a0358e 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -87,7 +87,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(0)),
                                               param(0),
                                               param(0)],
-                                      tcx.intern_tup(&[param(0), tcx.types.bool], false)),
+                                      tcx.intern_tup(&[param(0), tcx.types.bool])),
             "load" => (1, vec![tcx.mk_imm_ptr(param(0))],
                        param(0)),
             "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)],
@@ -281,7 +281,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             "add_with_overflow" | "sub_with_overflow"  | "mul_with_overflow" =>
                 (1, vec![param(0), param(0)],
-                tcx.intern_tup(&[param(0), tcx.types.bool], false)),
+                tcx.intern_tup(&[param(0), tcx.types.bool])),
 
             "unchecked_div" | "unchecked_rem" =>
                 (1, vec![param(0), param(0)], param(0)),
@@ -441,7 +441,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>(
 
     match *expected {
         Void => match t.sty {
-            ty::TyTuple(ref v, _) if v.is_empty() => {},
+            ty::TyTuple(ref v) if v.is_empty() => {},
             _ => simple_error(&format!("`{}`", t), "()"),
         },
         // (The width we pass to LLVM doesn't concern the type checker.)
@@ -515,7 +515,7 @@ fn match_intrinsic_type_to_type<'a, 'tcx>(
         }
         Aggregate(_flatten, ref expected_contents) => {
             match t.sty {
-                ty::TyTuple(contents, _) => {
+                ty::TyTuple(contents) => {
                     if contents.len() != expected_contents.len() {
                         simple_error(&format!("tuple with length {}", contents.len()),
                                      &format!("tuple with length {}", expected_contents.len()));
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 48591998a1f..18de8d1bee7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -873,11 +873,12 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         // All type checking constraints were added, try to fallback unsolved variables.
-        fcx.select_obligations_where_possible();
+        fcx.select_obligations_where_possible(false);
+        let mut fallback_has_occurred = false;
         for ty in &fcx.unsolved_variables() {
-            fcx.fallback_if_possible(ty);
+            fallback_has_occurred |= fcx.fallback_if_possible(ty);
         }
-        fcx.select_obligations_where_possible();
+        fcx.select_obligations_where_possible(fallback_has_occurred);
 
         // Even though coercion casts provide type hints, we check casts after fallback for
         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
@@ -1837,7 +1838,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // possible. This can help substantially when there are
         // indirect dependencies that don't seem worth tracking
         // precisely.
-        self.select_obligations_where_possible();
+        self.select_obligations_where_possible(false);
         ty = self.resolve_type_vars_if_possible(&ty);
 
         debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
@@ -2154,18 +2155,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn resolve_generator_interiors(&self, def_id: DefId) {
         let mut generators = self.deferred_generator_interiors.borrow_mut();
         for (body_id, interior) in generators.drain(..) {
-            self.select_obligations_where_possible();
+            self.select_obligations_where_possible(false);
             generator_interior::resolve_interior(self, def_id, body_id, interior);
         }
     }
 
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
-    // Non-numerics get replaced with ! or () (depending on whether
-    // feature(never_type) is enabled), unconstrained ints with i32,
+    // Non-numerics get replaced with !, unconstrained ints with i32,
     // unconstrained floats with f64.
     // Fallback becomes very dubious if we have encountered type-checking errors.
     // In that case, fallback to TyError.
-    fn fallback_if_possible(&self, ty: Ty<'tcx>) {
+    // The return value indicates whether fallback has occured.
+    fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
         use rustc::ty::error::UnconstrainedNumeric::Neither;
         use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
 
@@ -2174,25 +2175,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             _ if self.is_tainted_by_errors() => self.tcx().types.err,
             UnconstrainedInt => self.tcx.types.i32,
             UnconstrainedFloat => self.tcx.types.f64,
-            Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(),
-            Neither => return
+            Neither if self.type_var_diverges(ty) => self.tcx.types.never,
+            Neither => return false,
         };
         debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback);
         self.demand_eqtype(syntax_pos::DUMMY_SP, ty, fallback);
+        true
     }
 
     fn select_all_obligations_or_error(&self) {
         debug!("select_all_obligations_or_error");
         if let Err(errors) = self.fulfillment_cx.borrow_mut().select_all_or_error(&self) {
-            self.report_fulfillment_errors(&errors, self.inh.body_id);
+            self.report_fulfillment_errors(&errors, self.inh.body_id, false);
         }
     }
 
     /// Select as many obligations as we can at present.
-    fn select_obligations_where_possible(&self) {
+    fn select_obligations_where_possible(&self, fallback_has_occurred: bool) {
         match self.fulfillment_cx.borrow_mut().select_where_possible(self) {
             Ok(()) => { }
-            Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
+            Err(errors) => {
+                self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
+            },
         }
     }
 
@@ -2438,7 +2442,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
             let err_inputs = match tuple_arguments {
                 DontTupleArguments => err_inputs,
-                TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)],
+                TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])],
             };
 
             self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr,
@@ -2531,16 +2535,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let formal_tys = if tuple_arguments == TupleArguments {
             let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
             match tuple_type.sty {
-                ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => {
+                ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
                     parameter_count_error(tcx.sess, sp, expr_sp, arg_types.len(), args.len(),
                                           "E0057", false, def_span, false);
                     expected_arg_tys = &[];
                     self.err_args(args.len())
                 }
-                ty::TyTuple(arg_types, _) => {
+                ty::TyTuple(arg_types) => {
                     expected_arg_tys = match expected_arg_tys.get(0) {
                         Some(&ty) => match ty.sty {
-                            ty::TyTuple(ref tys, _) => &tys,
+                            ty::TyTuple(ref tys) => &tys,
                             _ => &[]
                         },
                         None => &[]
@@ -2596,7 +2600,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             // an "opportunistic" vtable resolution of any trait bounds on
             // the call. This helps coercions.
             if check_closures {
-                self.select_obligations_where_possible();
+                self.select_obligations_where_possible(false);
             }
 
             // For variadic functions, we don't have a declared type for all of
@@ -3193,7 +3197,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         None
                     }
                 }
-                ty::TyTuple(ref v, _) => {
+                ty::TyTuple(ref v) => {
                     tuple_like = true;
                     v.get(idx.node).cloned()
                 }
@@ -3945,7 +3949,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let t_cast = self.resolve_type_vars_if_possible(&t_cast);
             let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
             let t_cast = self.resolve_type_vars_if_possible(&t_cast);
-            let diverges = self.diverges.get();
 
             // Eagerly check for some obvious errors.
             if t_expr.references_error() || t_cast.references_error() {
@@ -3953,7 +3956,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             } else {
                 // Defer other checks until we're done type checking.
                 let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
-                match cast::CastCheck::new(self, e, t_expr, diverges, t_cast, t.span, expr.span) {
+                match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
                     Ok(cast_check) => {
                         deferred_cast_checks.push(cast_check);
                         t_cast
@@ -4060,7 +4063,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let flds = expected.only_has_type(self).and_then(|ty| {
                 let ty = self.resolve_type_vars_with_obligations(ty);
                 match ty.sty {
-                    ty::TyTuple(ref flds, _) => Some(&flds[..]),
+                    ty::TyTuple(ref flds) => Some(&flds[..]),
                     _ => None
                 }
             });
@@ -4078,7 +4081,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 };
                 t
             });
-            let tuple = tcx.mk_tup(elt_ts_iter, false);
+            let tuple = tcx.mk_tup(elt_ts_iter);
             if tuple.references_error() {
                 tcx.types.err
             } else {
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 47a229cbd3b..eae692f4cda 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -479,7 +479,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         match method {
             Some(ok) => {
                 let method = self.register_infer_ok_obligations(ok);
-                self.select_obligations_where_possible();
+                self.select_obligations_where_possible(false);
 
                 Ok(method)
             }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 2f1c42bbef8..9493c36fe95 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Check that all transitive obligations are satisfied.
         if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&errors, None);
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
 
         // Finally, resolve all regions.
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index ea90c35cb8f..964c0021133 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -80,13 +80,14 @@ This API is completely unstable and subject to change.
 #![feature(crate_visibility_modifier)]
 #![feature(from_ref)]
 #![feature(match_default_bindings)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(option_filter)]
 #![feature(quote)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(i128_type)]
+#![cfg_attr(stage0, feature(never_type))]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -173,7 +174,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         match fulfill_cx.select_all_or_error(infcx) {
             Ok(()) => true,
             Err(errors) => {
-                infcx.report_fulfillment_errors(&errors, None);
+                infcx.report_fulfillment_errors(&errors, None, false);
                 false
             }
         }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 2a4e92034de..a24e501aba9 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -287,7 +287,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_mt(current, mt, variance);
             }
 
-            ty::TyTuple(subtys, _) => {
+            ty::TyTuple(subtys) => {
                 for &subty in subtys {
                     self.add_constraints_from_ty(current, subty, variance);
                 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index ff281a53ab7..904c24815cb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1322,7 +1322,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
         Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
             assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
-                ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(),
+                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
                     return PathParameters::AngleBracketed {
                         lifetimes,
@@ -1334,7 +1334,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
             let output = None;
             // FIXME(#20299) return type comes from a projection now
             // match types[1].sty {
-            //     ty::TyTuple(ref v, _) if v.is_empty() => None, // -> ()
+            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
             //     _ => Some(types[1].clean(cx))
             // };
             PathParameters::Parenthesized {
@@ -1377,7 +1377,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         // collect any late bound regions
         let mut late_bounds = vec![];
         for ty_s in self.input_types().skip(1) {
-            if let ty::TyTuple(ts, _) = ty_s.sty {
+            if let ty::TyTuple(ts) = ty_s.sty {
                 for &ty_s in ts {
                     if let ty::TyRef(ref reg, _) = ty_s.sty {
                         if let &ty::RegionKind::ReLateBound(..) = *reg {
@@ -2731,7 +2731,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     Never
                 }
             }
-            ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
+            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
 
             ty::TyProjection(ref data) => data.clean(cx),
 
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index eb5022ad577..f8dbe193fed 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -234,7 +234,7 @@ impl<'a> From<Cow<'a, str>> for Box<Error> {
     }
 }
 
-#[unstable(feature = "never_type", issue = "35121")]
+#[stable(feature = "never_type", since = "1.26.0")]
 impl Error for ! {
     fn description(&self) -> &str { *self }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index da15941374d..eea0e6b6752 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -282,7 +282,7 @@
 #![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(num_bits_bytes)]
 #![feature(old_wrapping)]
 #![feature(on_unimplemented)]
@@ -324,6 +324,7 @@
 #![feature(doc_spotlight)]
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
+#![cfg_attr(stage0, feature(never_type))]
 
 #![default_lib_allocator]
 
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 358aa2c37df..e6e6be2e453 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -79,7 +79,6 @@ mod prim_bool { }
 /// write:
 ///
 /// ```
-/// #![feature(never_type)]
 /// # fn foo() -> u32 {
 /// let x: ! = {
 ///     return 123
@@ -131,13 +130,15 @@ mod prim_bool { }
 /// [`Result<String, !>`] which we can unpack like this:
 ///
 /// ```ignore (string-from-str-error-type-is-not-never-yet)
+/// #[feature(exhaustive_patterns)]
 /// // NOTE: This does not work today!
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
-/// Since the [`Err`] variant contains a `!`, it can never occur. So we can exhaustively match on
-/// [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behaviour of `!` -
-/// it can be used to "delete" certain enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
+/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
+/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
+/// enum variants from generic types like `Result`.
 ///
 /// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
 /// [`Result<String, !>`]: result/enum.Result.html
@@ -154,7 +155,6 @@ mod prim_bool { }
 /// for example:
 ///
 /// ```
-/// # #![feature(never_type)]
 /// # use std::fmt;
 /// # trait Debug {
 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
@@ -192,7 +192,6 @@ mod prim_bool { }
 /// [`Default`]: default/trait.Default.html
 /// [`default()`]: default/trait.Default.html#tymethod.default
 ///
-#[unstable(feature = "never_type", issue = "35121")]
 mod prim_never { }
 
 #[doc(primitive = "char")]
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ec9a15d9f2b..91364fe6ed4 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -286,8 +286,8 @@ declare_features! (
     // Allows `impl Trait` in function arguments.
     (active, universal_impl_trait, "1.23.0", Some(34511), None),
 
-    // The `!` type
-    (active, never_type, "1.13.0", Some(35121), None),
+    // Allows exhaustive pattern matching on types that contain uninhabited types.
+    (active, exhaustive_patterns, "1.13.0", None, None),
 
     // Allows all literals in attribute lists and values of key-value pairs.
     (active, attr_literals, "1.13.0", Some(34981), None),
@@ -1566,10 +1566,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
                 self.check_abi(bare_fn_ty.abi, ty.span);
             }
-            ast::TyKind::Never => {
-                gate_feature_post!(&self, never_type, ty.span,
-                                   "The `!` type is experimental");
-            },
             ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
                 gate_feature_post!(&self, dyn_trait, ty.span,
                                    "`dyn Trait` syntax is unstable");
diff --git a/src/test/compile-fail/call-fn-never-arg-wrong-type.rs b/src/test/compile-fail/call-fn-never-arg-wrong-type.rs
index 583befed1e8..c2f157cd35c 100644
--- a/src/test/compile-fail/call-fn-never-arg-wrong-type.rs
+++ b/src/test/compile-fail/call-fn-never-arg-wrong-type.rs
@@ -10,8 +10,6 @@
 
 // Test that we can't pass other types for !
 
-#![feature(never_type)]
-
 fn foo(x: !) -> ! {
     x
 }
diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs
index 0d5bf6cd68c..5efb4dadc64 100644
--- a/src/test/compile-fail/coerce-to-bang-cast.rs
+++ b/src/test/compile-fail/coerce-to-bang-cast.rs
@@ -8,15 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
-
 fn foo(x: usize, y: !, z: usize) { }
 
-#[deny(coerce_never)]
 fn cast_a() {
     let y = {return; 22} as !;
-    //~^ ERROR cannot coerce `i32` to !
-    //~| hard error
+    //~^ ERROR non-primitive cast
 }
 
 fn cast_b() {
diff --git a/src/test/compile-fail/coerce-to-bang.rs b/src/test/compile-fail/coerce-to-bang.rs
index b804bb2981b..15049232a4d 100644
--- a/src/test/compile-fail/coerce-to-bang.rs
+++ b/src/test/compile-fail/coerce-to-bang.rs
@@ -8,18 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
-#![deny(coerce_never)]
-
 fn foo(x: usize, y: !, z: usize) { }
 
 fn call_foo_a() {
-    // FIXME(#40800) -- accepted because divergence happens **before**
-    // the coercion to `!`, but within same expression. Not clear that
-    // these are the rules we want.
     foo(return, 22, 44);
-    //~^ ERROR cannot coerce `{integer}` to !
-    //~| hard error
+    //~^ ERROR mismatched types
 }
 
 fn call_foo_b() {
@@ -39,8 +32,7 @@ fn call_foo_d() {
     let b = 22;
     let c = 44;
     foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
-    //~^ ERROR cannot coerce `{integer}` to !
-    //~| hard error
+    //~^ ERROR mismatched types
 }
 
 fn call_foo_e() {
@@ -80,8 +72,7 @@ fn tuple_a() {
 fn tuple_b() {
     // Divergence happens before coercion: OK
     let x: (usize, !, usize) = (return, 44, 66);
-    //~^ ERROR cannot coerce `{integer}` to !
-    //~| hard error
+    //~^ ERROR mismatched types
 }
 
 fn tuple_c() {
diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-never-note.rs
index 3f4e1cce548..798544f1649 100644
--- a/src/test/compile-fail/defaulted-unit-warning.rs
+++ b/src/test/compile-fail/defaulted-never-note.rs
@@ -25,14 +25,17 @@ trait ImplementedForUnitButNotNever {}
 impl ImplementedForUnitButNotNever for () {}
 
 fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+//~^ NOTE required by `foo`
 
 fn smeg() {
     let _x = return;
     foo(_x);
-    //~^ ERROR code relies on type
-    //~| WARNING previously accepted
+    //~^ ERROR the trait bound
+    //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
+    //~| NOTE the trait is implemented for `()`
 }
 
 fn main() {
     smeg();
 }
+
diff --git a/src/test/compile-fail/diverging-fn-tail-35849.rs b/src/test/compile-fail/diverging-fn-tail-35849.rs
index a91c000bbf7..9ef5159cb77 100644
--- a/src/test/compile-fail/diverging-fn-tail-35849.rs
+++ b/src/test/compile-fail/diverging-fn-tail-35849.rs
@@ -8,12 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[deny(coerce_never)]
 fn assert_sizeof() -> ! {
     unsafe {
         ::std::mem::transmute::<f64, [u8; 8]>(panic!())
-            //~^ ERROR cannot coerce `[u8; 8]` to !
-            //~| hard error
+            //~^ ERROR mismatched types
     }
 }
 
diff --git a/src/test/compile-fail/inhabitedness-infinite-loop.rs b/src/test/compile-fail/inhabitedness-infinite-loop.rs
index 91b85d7510a..b9741e0add6 100644
--- a/src/test/compile-fail/inhabitedness-infinite-loop.rs
+++ b/src/test/compile-fail/inhabitedness-infinite-loop.rs
@@ -10,7 +10,7 @@
 
 // error-pattern:reached recursion limit
 
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 
 struct Foo<'a, T: 'a> {
     ph: std::marker::PhantomData<T>,
diff --git a/src/test/compile-fail/loop-break-value.rs b/src/test/compile-fail/loop-break-value.rs
index 938f7fba2a0..5ef46bb27fd 100644
--- a/src/test/compile-fail/loop-break-value.rs
+++ b/src/test/compile-fail/loop-break-value.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
-
 fn main() {
     let val: ! = loop { break break; };
     //~^ ERROR mismatched types
diff --git a/src/test/compile-fail/match-privately-empty.rs b/src/test/compile-fail/match-privately-empty.rs
index 3affb1c03e9..e18c7d77ce3 100644
--- a/src/test/compile-fail/match-privately-empty.rs
+++ b/src/test/compile-fail/match-privately-empty.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 
 mod private {
     pub struct Private {
diff --git a/src/test/compile-fail/never-assign-dead-code.rs b/src/test/compile-fail/never-assign-dead-code.rs
index 1e0cc0f5357..4e987d1ddce 100644
--- a/src/test/compile-fail/never-assign-dead-code.rs
+++ b/src/test/compile-fail/never-assign-dead-code.rs
@@ -10,7 +10,7 @@
 
 // Test that an assignment of type ! makes the rest of the block dead code.
 
-#![feature(never_type, rustc_attrs)]
+#![feature(rustc_attrs)]
 #![warn(unused)]
 
 #[rustc_error]
diff --git a/src/test/compile-fail/never-assign-wrong-type.rs b/src/test/compile-fail/never-assign-wrong-type.rs
index c0dd2cab749..8c2de7d68d3 100644
--- a/src/test/compile-fail/never-assign-wrong-type.rs
+++ b/src/test/compile-fail/never-assign-wrong-type.rs
@@ -10,7 +10,6 @@
 
 // Test that we can't use another type in place of !
 
-#![feature(never_type)]
 #![deny(warnings)]
 
 fn main() {
diff --git a/src/test/compile-fail/recursive-types-are-not-uninhabited.rs b/src/test/compile-fail/recursive-types-are-not-uninhabited.rs
index f8d6c3de2ab..fa936697072 100644
--- a/src/test/compile-fail/recursive-types-are-not-uninhabited.rs
+++ b/src/test/compile-fail/recursive-types-are-not-uninhabited.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//#![feature(never_type)]
-
 struct R<'a> {
     r: &'a R<'a>,
 }
diff --git a/src/test/compile-fail/uninhabited-irrefutable.rs b/src/test/compile-fail/uninhabited-irrefutable.rs
index 4755fdd4fd5..72b0afa6bd3 100644
--- a/src/test/compile-fail/uninhabited-irrefutable.rs
+++ b/src/test/compile-fail/uninhabited-irrefutable.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 
 mod foo {
     pub struct SecretlyEmpty {
diff --git a/src/test/compile-fail/uninhabited-patterns.rs b/src/test/compile-fail/uninhabited-patterns.rs
index 4c894b0bdd3..9f943f08232 100644
--- a/src/test/compile-fail/uninhabited-patterns.rs
+++ b/src/test/compile-fail/uninhabited-patterns.rs
@@ -11,7 +11,7 @@
 #![feature(box_patterns)]
 #![feature(slice_patterns)]
 #![feature(box_syntax)]
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![deny(unreachable_patterns)]
 
 mod foo {
diff --git a/src/test/compile-fail/unreachable-loop-patterns.rs b/src/test/compile-fail/unreachable-loop-patterns.rs
index 6147692658f..dca79bdfb87 100644
--- a/src/test/compile-fail/unreachable-loop-patterns.rs
+++ b/src/test/compile-fail/unreachable-loop-patterns.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/compile-fail/unreachable-try-pattern.rs b/src/test/compile-fail/unreachable-try-pattern.rs
index 46ea4a06a3b..0caf7d51234 100644
--- a/src/test/compile-fail/unreachable-try-pattern.rs
+++ b/src/test/compile-fail/unreachable-try-pattern.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type, rustc_attrs)]
+#![feature(exhaustive_patterns, rustc_attrs)]
 #![warn(unreachable_code)]
 #![warn(unreachable_patterns)]
 
diff --git a/src/test/run-fail/adjust_never.rs b/src/test/run-fail/adjust_never.rs
index ccdb1ca15bb..7a4b5e59eeb 100644
--- a/src/test/run-fail/adjust_never.rs
+++ b/src/test/run-fail/adjust_never.rs
@@ -10,8 +10,6 @@
 
 // Test that a variable of type ! can coerce to another type.
 
-#![feature(never_type)]
-
 // error-pattern:explicit
 fn main() {
     let x: ! = panic!();
diff --git a/src/test/run-fail/call-fn-never-arg.rs b/src/test/run-fail/call-fn-never-arg.rs
index 95101e70db9..56454586bb9 100644
--- a/src/test/run-fail/call-fn-never-arg.rs
+++ b/src/test/run-fail/call-fn-never-arg.rs
@@ -12,7 +12,6 @@
 
 // error-pattern:wowzers!
 
-#![feature(never_type)]
 #![allow(unreachable_code)]
 
 fn foo(x: !) -> ! {
diff --git a/src/test/run-fail/cast-never.rs b/src/test/run-fail/cast-never.rs
index acd002494f4..0155332c51d 100644
--- a/src/test/run-fail/cast-never.rs
+++ b/src/test/run-fail/cast-never.rs
@@ -10,8 +10,6 @@
 
 // Test that we can explicitly cast ! to another type
 
-#![feature(never_type)]
-
 // error-pattern:explicit
 fn main() {
     let x: ! = panic!();
diff --git a/src/test/run-fail/never-associated-type.rs b/src/test/run-fail/never-associated-type.rs
index 345674f3f52..d9b8461a1d0 100644
--- a/src/test/run-fail/never-associated-type.rs
+++ b/src/test/run-fail/never-associated-type.rs
@@ -10,8 +10,6 @@
 
 // Test that we can use ! as an associated type.
 
-#![feature(never_type)]
-
 // error-pattern:kapow!
 
 trait Foo {
diff --git a/src/test/run-fail/never-type-arg.rs b/src/test/run-fail/never-type-arg.rs
index 826ca3a08c0..0fe10d43910 100644
--- a/src/test/run-fail/never-type-arg.rs
+++ b/src/test/run-fail/never-type-arg.rs
@@ -12,8 +12,6 @@
 
 // error-pattern:oh no!
 
-#![feature(never_type)]
-
 struct Wub;
 
 impl PartialEq<!> for Wub {
diff --git a/src/test/run-pass/diverging-fallback-control-flow.rs b/src/test/run-pass/diverging-fallback-control-flow.rs
index 723a98bcdfa..a96f98b9efd 100644
--- a/src/test/run-pass/diverging-fallback-control-flow.rs
+++ b/src/test/run-pass/diverging-fallback-control-flow.rs
@@ -14,8 +14,6 @@
 // These represent current behavior, but are pretty dubious.  I would
 // like to revisit these and potentially change them. --nmatsakis
 
-#![feature(never_type)]
-
 trait BadDefault {
     fn default() -> Self;
 }
diff --git a/src/test/run-pass/empty-types-in-patterns.rs b/src/test/run-pass/empty-types-in-patterns.rs
index 033b185a0ef..87db4401929 100644
--- a/src/test/run-pass/empty-types-in-patterns.rs
+++ b/src/test/run-pass/empty-types-in-patterns.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 #![feature(slice_patterns)]
 #![allow(unreachable_patterns)]
 #![allow(unreachable_code)]
diff --git a/src/test/run-pass/impl-for-never.rs b/src/test/run-pass/impl-for-never.rs
index 794f5969bff..cf54e1c3bd5 100644
--- a/src/test/run-pass/impl-for-never.rs
+++ b/src/test/run-pass/impl-for-never.rs
@@ -10,8 +10,6 @@
 
 // Test that we can call static methods on ! both directly and when it appears in a generic
 
-#![feature(never_type)]
-
 trait StringifyType {
     fn stringify_type() -> &'static str;
 }
diff --git a/src/test/run-pass/issue-38972.rs b/src/test/run-pass/issue-38972.rs
deleted file mode 100644
index d5df84e0fb0..00000000000
--- a/src/test/run-pass/issue-38972.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This issue tracks a regression (a new warning) without
-// feature(never_type). When we make that the default, please
-// remove this test.
-
-enum Foo { }
-
-fn make_foo() -> Option<Foo> { None }
-
-#[deny(warnings)]
-fn main() {
-    match make_foo() {
-        None => {},
-        Some(_) => {}
-    }
-}
diff --git a/src/test/run-pass/issue-44402.rs b/src/test/run-pass/issue-44402.rs
index 244aa65a3d5..a5a0a5a5794 100644
--- a/src/test/run-pass/issue-44402.rs
+++ b/src/test/run-pass/issue-44402.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
+#![feature(exhaustive_patterns)]
 
 // Regression test for inhabitedness check. The old
 // cache used to cause us to incorrectly decide
diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs
index 39053769b24..ffdd99ebf6e 100644
--- a/src/test/run-pass/loop-break-value.rs
+++ b/src/test/run-pass/loop-break-value.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
-
 #[allow(unused)]
 fn never_returns() {
     loop {
diff --git a/src/test/run-pass/mir_calls_to_shims.rs b/src/test/run-pass/mir_calls_to_shims.rs
index 9641ed28293..dda7a46f325 100644
--- a/src/test/run-pass/mir_calls_to_shims.rs
+++ b/src/test/run-pass/mir_calls_to_shims.rs
@@ -11,7 +11,6 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(fn_traits)]
-#![feature(never_type)]
 
 use std::panic;
 
diff --git a/src/test/run-pass/never-result.rs b/src/test/run-pass/never-result.rs
index 5c0af392f44..8aa2a13ed8c 100644
--- a/src/test/run-pass/never-result.rs
+++ b/src/test/run-pass/never-result.rs
@@ -10,8 +10,6 @@
 
 // Test that we can extract a ! through pattern matching then use it as several different types.
 
-#![feature(never_type)]
-
 fn main() {
     let x: Result<u32, !> = Ok(123);
     match x {
diff --git a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs
index 75b60aa8d10..052575de4c2 100644
--- a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs
+++ b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs
@@ -31,5 +31,5 @@ trait Add<RHS=Self> {
 fn ice<A>(a: A) {
     let r = loop {};
     r = r + a;
-    //~^ ERROR the trait bound `(): Add<A>` is not satisfied
+    //~^ ERROR the trait bound `!: Add<A>` is not satisfied
 }
diff --git a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr
index 7924ab74444..c22a645385a 100644
--- a/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr
+++ b/src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `(): Add<A>` is not satisfied
+error[E0277]: the trait bound `!: Add<A>` is not satisfied
   --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:33:11
    |
 LL |     r = r + a;
-   |           ^ the trait `Add<A>` is not implemented for `()`
+   |           ^ the trait `Add<A>` is not implemented for `!`
 
 error: aborting due to previous error
 
diff --git a/src/test/run-pass/diverging-fn-tail-35849.rs b/src/test/ui/feature-gate-exhaustive-patterns.rs
index dfd99bcc9fb..477dd1b38eb 100644
--- a/src/test/run-pass/diverging-fn-tail-35849.rs
+++ b/src/test/ui/feature-gate-exhaustive-patterns.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[allow(coerce_never)]
-fn assert_sizeof() -> ! {
-    unsafe {
-        ::std::mem::transmute::<f64, [u8; 8]>(panic!())
-    }
+fn foo() -> Result<u32, !> {
+    Ok(123)
+}
+
+fn main() {
+    let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding
 }
 
-fn main() { }
diff --git a/src/test/ui/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gate-exhaustive-patterns.stderr
new file mode 100644
index 00000000000..4afe5b5d5e0
--- /dev/null
+++ b/src/test/ui/feature-gate-exhaustive-patterns.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in local binding: `Err(_)` not covered
+  --> $DIR/feature-gate-exhaustive-patterns.rs:16:9
+   |
+LL |     let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding
+   |         ^^^^^^ pattern `Err(_)` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/feature-gate-never_type.rs b/src/test/ui/feature-gate-never_type.rs
deleted file mode 100644
index 11b9f412957..00000000000
--- a/src/test/ui/feature-gate-never_type.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that ! errors when used in illegal positions with feature(never_type) disabled
-
-trait Foo {
-    type Wub;
-}
-
-type Ma = (u32, !, i32); //~ ERROR type is experimental
-type Meeshka = Vec<!>; //~ ERROR type is experimental
-type Mow = &fn(!) -> !; //~ ERROR type is experimental
-type Skwoz = &mut !; //~ ERROR type is experimental
-
-impl Foo for Meeshka {
-    type Wub = !; //~ ERROR type is experimental
-}
-
-fn main() {
-}
-
diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr
deleted file mode 100644
index 187be6d8291..00000000000
--- a/src/test/ui/feature-gate-never_type.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0658]: The `!` type is experimental (see issue #35121)
-  --> $DIR/feature-gate-never_type.rs:17:17
-   |
-LL | type Ma = (u32, !, i32); //~ ERROR type is experimental
-   |                 ^
-   |
-   = help: add #![feature(never_type)] to the crate attributes to enable
-
-error[E0658]: The `!` type is experimental (see issue #35121)
-  --> $DIR/feature-gate-never_type.rs:18:20
-   |
-LL | type Meeshka = Vec<!>; //~ ERROR type is experimental
-   |                    ^
-   |
-   = help: add #![feature(never_type)] to the crate attributes to enable
-
-error[E0658]: The `!` type is experimental (see issue #35121)
-  --> $DIR/feature-gate-never_type.rs:19:16
-   |
-LL | type Mow = &fn(!) -> !; //~ ERROR type is experimental
-   |                ^
-   |
-   = help: add #![feature(never_type)] to the crate attributes to enable
-
-error[E0658]: The `!` type is experimental (see issue #35121)
-  --> $DIR/feature-gate-never_type.rs:20:19
-   |
-LL | type Skwoz = &mut !; //~ ERROR type is experimental
-   |                   ^
-   |
-   = help: add #![feature(never_type)] to the crate attributes to enable
-
-error[E0658]: The `!` type is experimental (see issue #35121)
-  --> $DIR/feature-gate-never_type.rs:23:16
-   |
-LL |     type Wub = !; //~ ERROR type is experimental
-   |                ^
-   |
-   = help: add #![feature(never_type)] to the crate attributes to enable
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs
index 4d0396903e5..7e8eff02c20 100644
--- a/src/test/ui/print_type_sizes/uninhabited.rs
+++ b/src/test/ui/print_type_sizes/uninhabited.rs
@@ -11,7 +11,6 @@
 // compile-flags: -Z print-type-sizes
 // must-compile-successfully
 
-#![feature(never_type)]
 #![feature(start)]
 
 #[start]
diff --git a/src/test/ui/reachable/expr_add.rs b/src/test/ui/reachable/expr_add.rs
index dd43c58de6d..3e39b75d8c0 100644
--- a/src/test/ui/reachable/expr_add.rs
+++ b/src/test/ui/reachable/expr_add.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
 #![allow(unused_variables)]
 #![deny(unreachable_code)]
 
diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr
index d3e1da0e718..f49a781ce33 100644
--- a/src/test/ui/reachable/expr_add.stderr
+++ b/src/test/ui/reachable/expr_add.stderr
@@ -1,11 +1,11 @@
 error: unreachable expression
-  --> $DIR/expr_add.rs:27:13
+  --> $DIR/expr_add.rs:26:13
    |
 LL |     let x = Foo + return; //~ ERROR unreachable
    |             ^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/expr_add.rs:13:9
+  --> $DIR/expr_add.rs:12:9
    |
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_array.rs b/src/test/ui/reachable/expr_array.rs
index 31229668796..323a5752e22 100644
--- a/src/test/ui/reachable/expr_array.rs
+++ b/src/test/ui/reachable/expr_array.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 fn a() {
@@ -21,7 +20,7 @@ fn a() {
 }
 
 fn b() {
-    // the `array is unreachable:
+    // the array is unreachable:
     let x: [usize; 2] = [22, return]; //~ ERROR unreachable
 }
 
diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr
index 3257514ea50..78ac76a6137 100644
--- a/src/test/ui/reachable/expr_array.stderr
+++ b/src/test/ui/reachable/expr_array.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_array.rs:20:34
+  --> $DIR/expr_array.rs:19:34
    |
 LL |     let x: [usize; 2] = [return, 22]; //~ ERROR unreachable
    |                                  ^^
@@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_array.rs:25:25
+  --> $DIR/expr_array.rs:24:25
    |
 LL |     let x: [usize; 2] = [22, return]; //~ ERROR unreachable
    |                         ^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_assign.rs b/src/test/ui/reachable/expr_assign.rs
index e6fb46a5bac..73083af34d9 100644
--- a/src/test/ui/reachable/expr_assign.rs
+++ b/src/test/ui/reachable/expr_assign.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn foo() {
     // No error here.
diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr
index 15dcf2c2401..628bfbf6217 100644
--- a/src/test/ui/reachable/expr_assign.stderr
+++ b/src/test/ui/reachable/expr_assign.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_assign.rs:20:5
+  --> $DIR/expr_assign.rs:19:5
    |
 LL |     x = return; //~ ERROR unreachable
    |     ^^^^^^^^^^
@@ -11,13 +11,13 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_assign.rs:30:14
+  --> $DIR/expr_assign.rs:29:14
    |
 LL |         *p = return; //~ ERROR unreachable
    |              ^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_assign.rs:36:15
+  --> $DIR/expr_assign.rs:35:15
    |
 LL |     *{return; &mut i} = 22; //~ ERROR unreachable
    |               ^^^^^^
diff --git a/src/test/ui/reachable/expr_block.rs b/src/test/ui/reachable/expr_block.rs
index 57b5d3cabce..93bce43f76d 100644
--- a/src/test/ui/reachable/expr_block.rs
+++ b/src/test/ui/reachable/expr_block.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn a() {
     // Here the tail expression is considered unreachable:
diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr
index a0cef6449f7..5f5696aadb3 100644
--- a/src/test/ui/reachable/expr_block.stderr
+++ b/src/test/ui/reachable/expr_block.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_block.rs:21:9
+  --> $DIR/expr_block.rs:20:9
    |
 LL |         22 //~ ERROR unreachable
    |         ^^
@@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable statement
-  --> $DIR/expr_block.rs:36:9
+  --> $DIR/expr_block.rs:35:9
    |
 LL |         println!("foo");
    |         ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_call.rs b/src/test/ui/reachable/expr_call.rs
index 86b95aad9c2..2772dd429d1 100644
--- a/src/test/ui/reachable/expr_call.rs
+++ b/src/test/ui/reachable/expr_call.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn foo(x: !, y: usize) { }
 
diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr
index 455e5ab3653..414d29ec2a7 100644
--- a/src/test/ui/reachable/expr_call.stderr
+++ b/src/test/ui/reachable/expr_call.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_call.rs:23:17
+  --> $DIR/expr_call.rs:22:17
    |
 LL |     foo(return, 22); //~ ERROR unreachable
    |                 ^^
@@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_call.rs:28:5
+  --> $DIR/expr_call.rs:27:5
    |
 LL |     bar(return); //~ ERROR unreachable
    |     ^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_cast.rs b/src/test/ui/reachable/expr_cast.rs
index 76b00c00ad9..88846b63841 100644
--- a/src/test/ui/reachable/expr_cast.rs
+++ b/src/test/ui/reachable/expr_cast.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 fn a() {
diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr
index 8c37759aa46..458334e2af9 100644
--- a/src/test/ui/reachable/expr_cast.stderr
+++ b/src/test/ui/reachable/expr_cast.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_cast.rs:20:13
+  --> $DIR/expr_cast.rs:19:13
    |
 LL |     let x = {return} as !; //~ ERROR unreachable
    |             ^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_if.rs b/src/test/ui/reachable/expr_if.rs
index 2a265e772f3..d2fb1044e48 100644
--- a/src/test/ui/reachable/expr_if.rs
+++ b/src/test/ui/reachable/expr_if.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn foo() {
     if {return} {
diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr
index c14cdbfc2bc..6e8afd1c5be 100644
--- a/src/test/ui/reachable/expr_if.stderr
+++ b/src/test/ui/reachable/expr_if.stderr
@@ -1,5 +1,5 @@
 error: unreachable statement
-  --> $DIR/expr_if.rs:38:5
+  --> $DIR/expr_if.rs:37:5
    |
 LL |     println!("But I am.");
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_loop.rs b/src/test/ui/reachable/expr_loop.rs
index 3ed4b2dcf0c..533cdac0968 100644
--- a/src/test/ui/reachable/expr_loop.rs
+++ b/src/test/ui/reachable/expr_loop.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn a() {
     loop { return; }
diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr
index 7f834567de3..a51ef293acf 100644
--- a/src/test/ui/reachable/expr_loop.stderr
+++ b/src/test/ui/reachable/expr_loop.stderr
@@ -1,5 +1,5 @@
 error: unreachable statement
-  --> $DIR/expr_loop.rs:19:5
+  --> $DIR/expr_loop.rs:18:5
    |
 LL |     println!("I am dead.");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(unreachable_code)]
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: unreachable statement
-  --> $DIR/expr_loop.rs:31:5
+  --> $DIR/expr_loop.rs:30:5
    |
 LL |     println!("I am dead.");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |     println!("I am dead.");
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: unreachable statement
-  --> $DIR/expr_loop.rs:41:5
+  --> $DIR/expr_loop.rs:40:5
    |
 LL |     println!("I am dead.");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_match.rs b/src/test/ui/reachable/expr_match.rs
index d2b96e51a95..193edd77435 100644
--- a/src/test/ui/reachable/expr_match.rs
+++ b/src/test/ui/reachable/expr_match.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn a() {
     // The match is considered unreachable here, because the `return`
diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr
index d4cf21cef28..dfc1417f3d2 100644
--- a/src/test/ui/reachable/expr_match.stderr
+++ b/src/test/ui/reachable/expr_match.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_match.rs:20:5
+  --> $DIR/expr_match.rs:19:5
    |
 LL |     match {return} { } //~ ERROR unreachable
    |     ^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable statement
-  --> $DIR/expr_match.rs:25:5
+  --> $DIR/expr_match.rs:24:5
    |
 LL |     println!("I am dead");
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     println!("I am dead");
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: unreachable statement
-  --> $DIR/expr_match.rs:35:5
+  --> $DIR/expr_match.rs:34:5
    |
 LL |     println!("I am dead");
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_method.rs b/src/test/ui/reachable/expr_method.rs
index 8be71e464b2..7dabb307097 100644
--- a/src/test/ui/reachable/expr_method.rs
+++ b/src/test/ui/reachable/expr_method.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 struct Foo;
 
diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr
index b9348b5d481..6d67bfcd54a 100644
--- a/src/test/ui/reachable/expr_method.stderr
+++ b/src/test/ui/reachable/expr_method.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_method.rs:26:21
+  --> $DIR/expr_method.rs:25:21
    |
 LL |     Foo.foo(return, 22); //~ ERROR unreachable
    |                     ^^
@@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_method.rs:31:5
+  --> $DIR/expr_method.rs:30:5
    |
 LL |     Foo.bar(return); //~ ERROR unreachable
    |     ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_repeat.rs b/src/test/ui/reachable/expr_repeat.rs
index 47ee2ba62b8..fd9fca413a7 100644
--- a/src/test/ui/reachable/expr_repeat.rs
+++ b/src/test/ui/reachable/expr_repeat.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 fn a() {
diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr
index 90cc3183c72..36393de90b7 100644
--- a/src/test/ui/reachable/expr_repeat.stderr
+++ b/src/test/ui/reachable/expr_repeat.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_repeat.rs:20:25
+  --> $DIR/expr_repeat.rs:19:25
    |
 LL |     let x: [usize; 2] = [return; 2]; //~ ERROR unreachable
    |                         ^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_return.rs b/src/test/ui/reachable/expr_return.rs
index fac1116dc68..9bbbe6f9099 100644
--- a/src/test/ui/reachable/expr_return.rs
+++ b/src/test/ui/reachable/expr_return.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 fn a() {
diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr
index 3876da6541d..2dcc50944c5 100644
--- a/src/test/ui/reachable/expr_return.stderr
+++ b/src/test/ui/reachable/expr_return.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_return.rs:21:22
+  --> $DIR/expr_return.rs:20:22
    |
 LL |     let x = {return {return {return;}}}; //~ ERROR unreachable
    |                      ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_struct.rs b/src/test/ui/reachable/expr_struct.rs
index b5acd395be6..66414f6084b 100644
--- a/src/test/ui/reachable/expr_struct.rs
+++ b/src/test/ui/reachable/expr_struct.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 struct Foo {
diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr
index 43985bbbb5c..3f0ecb20479 100644
--- a/src/test/ui/reachable/expr_struct.stderr
+++ b/src/test/ui/reachable/expr_struct.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_struct.rs:25:13
+  --> $DIR/expr_struct.rs:24:13
    |
 LL |     let x = Foo { a: 22, b: 33, ..return }; //~ ERROR unreachable
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,19 +11,19 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_struct.rs:30:33
+  --> $DIR/expr_struct.rs:29:33
    |
 LL |     let x = Foo { a: return, b: 33, ..return }; //~ ERROR unreachable
    |                                 ^^
 
 error: unreachable expression
-  --> $DIR/expr_struct.rs:35:39
+  --> $DIR/expr_struct.rs:34:39
    |
 LL |     let x = Foo { a: 22, b: return, ..return }; //~ ERROR unreachable
    |                                       ^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_struct.rs:40:13
+  --> $DIR/expr_struct.rs:39:13
    |
 LL |     let x = Foo { a: 22, b: return }; //~ ERROR unreachable
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_tup.rs b/src/test/ui/reachable/expr_tup.rs
index 089020bf385..e2c10090248 100644
--- a/src/test/ui/reachable/expr_tup.rs
+++ b/src/test/ui/reachable/expr_tup.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 fn a() {
diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr
index ff9aa666d8e..d372373ced0 100644
--- a/src/test/ui/reachable/expr_tup.stderr
+++ b/src/test/ui/reachable/expr_tup.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_tup.rs:20:38
+  --> $DIR/expr_tup.rs:19:38
    |
 LL |     let x: (usize, usize) = (return, 2); //~ ERROR unreachable
    |                                      ^
@@ -11,7 +11,7 @@ LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unreachable expression
-  --> $DIR/expr_tup.rs:25:29
+  --> $DIR/expr_tup.rs:24:29
    |
 LL |     let x: (usize, usize) = (2, return); //~ ERROR unreachable
    |                             ^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_type.rs b/src/test/ui/reachable/expr_type.rs
index 29c59d5304f..2381ea2ac7a 100644
--- a/src/test/ui/reachable/expr_type.rs
+++ b/src/test/ui/reachable/expr_type.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 #![feature(type_ascription)]
 
 fn a() {
diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr
index d6b9f75edf1..9b165d6b3ee 100644
--- a/src/test/ui/reachable/expr_type.stderr
+++ b/src/test/ui/reachable/expr_type.stderr
@@ -1,5 +1,5 @@
 error: unreachable expression
-  --> $DIR/expr_type.rs:20:13
+  --> $DIR/expr_type.rs:19:13
    |
 LL |     let x = {return}: !; //~ ERROR unreachable
    |             ^^^^^^^^^^^
diff --git a/src/test/ui/reachable/expr_unary.rs b/src/test/ui/reachable/expr_unary.rs
index ad12cb876fe..4096865f4c6 100644
--- a/src/test/ui/reachable/expr_unary.rs
+++ b/src/test/ui/reachable/expr_unary.rs
@@ -12,13 +12,9 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![deny(coerce_never)]
-#![feature(never_type)]
 
 fn foo() {
-    let x: ! = ! { return; 22 }; //~ ERROR unreachable
-    //~^ ERROR cannot coerce
-    //~| hard error
+    let x: ! = ! { return; }; //~ ERROR unreachable
     //~| ERROR cannot apply unary operator `!` to type `!`
 }
 
diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr
index b09721e5957..165eccd4239 100644
--- a/src/test/ui/reachable/expr_unary.stderr
+++ b/src/test/ui/reachable/expr_unary.stderr
@@ -1,8 +1,14 @@
+error[E0600]: cannot apply unary operator `!` to type `!`
+  --> $DIR/expr_unary.rs:17:16
+   |
+LL |     let x: ! = ! { return; }; //~ ERROR unreachable
+   |                ^^^^^^^^^^^^^
+
 error: unreachable expression
-  --> $DIR/expr_unary.rs:19:28
+  --> $DIR/expr_unary.rs:17:16
    |
-LL |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
-   |                            ^^
+LL |     let x: ! = ! { return; }; //~ ERROR unreachable
+   |                ^^^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/expr_unary.rs:14:9
@@ -10,26 +16,6 @@ note: lint level defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: cannot coerce `{integer}` to !
-  --> $DIR/expr_unary.rs:19:28
-   |
-LL |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
-   |                            ^^
-   |
-note: lint level defined here
-  --> $DIR/expr_unary.rs:15:9
-   |
-LL | #![deny(coerce_never)]
-   |         ^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #46325 <https://github.com/rust-lang/rust/issues/46325>
-
-error[E0600]: cannot apply unary operator `!` to type `!`
-  --> $DIR/expr_unary.rs:19:16
-   |
-LL |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
-   |                ^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/reachable/expr_while.rs b/src/test/ui/reachable/expr_while.rs
index 7dcd609fbc8..79fa69a9289 100644
--- a/src/test/ui/reachable/expr_while.rs
+++ b/src/test/ui/reachable/expr_while.rs
@@ -12,7 +12,6 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(never_type)]
 
 fn foo() {
     while {return} {
diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr
index cd093906615..90c35bfaa7a 100644
--- a/src/test/ui/reachable/expr_while.stderr
+++ b/src/test/ui/reachable/expr_while.stderr
@@ -1,5 +1,5 @@
 error: unreachable statement
-  --> $DIR/expr_while.rs:19:9
+  --> $DIR/expr_while.rs:18:9
    |
 LL |         println!("Hello, world!");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(unreachable_code)]
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: unreachable statement
-  --> $DIR/expr_while.rs:33:9
+  --> $DIR/expr_while.rs:32:9
    |
 LL |         println!("I am dead.");
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |         println!("I am dead.");
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: unreachable statement
-  --> $DIR/expr_while.rs:35:5
+  --> $DIR/expr_while.rs:34:5
    |
 LL |     println!("I am, too.");
    |     ^^^^^^^^^^^^^^^^^^^^^^^