about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAndrew Cann <shum@canndrew.org>2016-11-29 15:10:26 +0800
committerAndrew Cann <shum@canndrew.org>2017-01-03 15:31:46 +0800
commitbcdbe942e108e47ffa712fa44ad9b251c53c105b (patch)
tree8afed02b3f00112fe4aed144a0209eacecdf1320 /src
parent9ad20442e8af42815fde41c03188764ac516cf18 (diff)
downloadrust-bcdbe942e108e47ffa712fa44ad9b251c53c105b.tar.gz
rust-bcdbe942e108e47ffa712fa44ad9b251c53c105b.zip
Make is_useful handle empty types properly
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lint/builtin.rs7
-rw-r--r--src/librustc_const_eval/_match.rs63
-rw-r--r--src/librustc_const_eval/check_match.rs20
-rw-r--r--src/librustc_const_eval/diagnostics.rs2
-rw-r--r--src/librustc_lint/lib.rs1
-rw-r--r--src/librustc_typeck/check/_match.rs8
-rw-r--r--src/test/compile-fail/E0001.rs6
-rw-r--r--src/test/compile-fail/issue-12116.rs2
-rw-r--r--src/test/compile-fail/issue-12369.rs2
-rw-r--r--src/test/compile-fail/issue-13727.rs3
-rw-r--r--src/test/compile-fail/issue-30240-b.rs26
-rw-r--r--src/test/compile-fail/issue-30240.rs1
-rw-r--r--src/test/compile-fail/issue-31221.rs11
-rw-r--r--src/test/compile-fail/issue-3601.rs1
-rw-r--r--src/test/compile-fail/match-argm-statics-2.rs71
-rw-r--r--src/test/compile-fail/match-arm-statics.rs42
-rw-r--r--src/test/compile-fail/match-byte-array-patterns-2.rs26
-rw-r--r--src/test/compile-fail/match-byte-array-patterns.rs9
-rw-r--r--src/test/compile-fail/match-range-fail-dominate.rs2
-rw-r--r--src/test/compile-fail/match-ref-ice.rs3
-rw-r--r--src/test/compile-fail/match-vec-fixed.rs1
-rw-r--r--src/test/compile-fail/match-vec-unreachable.rs7
-rw-r--r--src/test/compile-fail/struct-pattern-match-useless.rs4
-rw-r--r--src/test/compile-fail/unreachable-arm.rs13
24 files changed, 246 insertions, 85 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 667c2590fa9..96fb168581b 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -71,6 +71,12 @@ declare_lint! {
 }
 
 declare_lint! {
+    pub UNREACHABLE_PATTERNS,
+    Warn,
+    "detects unreachable patterns"
+}
+
+declare_lint! {
     pub WARNINGS,
     Warn,
     "mass-change the level for lints which produce warnings"
@@ -239,6 +245,7 @@ impl LintPass for HardwiredLints {
             UNUSED_ASSIGNMENTS,
             DEAD_CODE,
             UNREACHABLE_CODE,
+            UNREACHABLE_PATTERNS,
             WARNINGS,
             UNUSED_FEATURES,
             STABLE_FEATURES,
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index e1894544657..b517a77255e 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -17,7 +17,7 @@ use eval::{compare_const_vals};
 
 use rustc_const_math::ConstInt;
 
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::Idx;
 
 use pattern::{FieldPattern, Pattern, PatternKind};
@@ -29,6 +29,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::mir::Field;
 use rustc::util::common::ErrorReported;
 
+use syntax::ast::NodeId;
 use syntax_pos::{Span, DUMMY_SP};
 
 use arena::TypedArena;
@@ -144,6 +145,14 @@ impl<'a, 'tcx> FromIterator<Vec<&'a Pattern<'tcx>>> for Matrix<'a, 'tcx> {
 //NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv
 pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    /// (roughly) where in the code the match occurs. This is necessary for
+    /// checking inhabited-ness of types because whether a type is (visibly)
+    /// inhabited can depend on whether it was defined in the current module or
+    /// not. eg.
+    ///     struct Foo { _private: ! }
+    /// can not be seen to be empty outside it's module and should not
+    /// be matchable with an empty match statement.
+    pub node: NodeId,
     /// A wild pattern with an error type - it exists to avoid having to normalize
     /// associated types to get field types.
     pub wild_pattern: &'a Pattern<'tcx>,
@@ -154,6 +163,7 @@ pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
 impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
     pub fn create_and_enter<F, R>(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        node: NodeId,
         f: F) -> R
         where F: for<'b> FnOnce(MatchCheckCtxt<'b, 'tcx>) -> R
     {
@@ -167,6 +177,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
 
         f(MatchCheckCtxt {
             tcx: tcx,
+            node: node,
             wild_pattern: &wild_pattern,
             pattern_arena: &pattern_arena,
             byte_array_map: FxHashMap(),
@@ -362,9 +373,9 @@ impl<'tcx> Witness<'tcx> {
 /// Therefore, if there is some pattern that is unmatched by `matrix`, it will
 /// still be unmatched if the first constructor is replaced by any of the constructors
 /// in the return value.
-fn missing_constructors(cx: &mut MatchCheckCtxt,
-                        matrix: &Matrix,
-                        pcx: PatternContext) -> Vec<Constructor> {
+fn missing_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
+                                      matrix: &Matrix,
+                                      pcx: PatternContext<'tcx>) -> Vec<Constructor> {
     let used_constructors: Vec<Constructor> =
         matrix.0.iter()
         .flat_map(|row| pat_constructors(cx, row[0], pcx).unwrap_or(vec![]))
@@ -384,16 +395,46 @@ fn missing_constructors(cx: &mut MatchCheckCtxt,
 ///
 /// but is instead bounded by the maximum fixed length of slice patterns in
 /// the column of patterns being analyzed.
-fn all_constructors(_cx: &mut MatchCheckCtxt, pcx: PatternContext) -> Vec<Constructor> {
+///
+/// We make sure to omit constructors that are statically impossible. eg for
+/// Option<!> we do not include Some(_) in the returned list of constructors.
+fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
+                                  pcx: PatternContext<'tcx>) -> Vec<Constructor>
+{
     match pcx.ty.sty {
         ty::TyBool =>
             [true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
-        ty::TySlice(_) =>
-            (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect(),
-        ty::TyArray(_, length) => vec![Slice(length)],
-        ty::TyAdt(def, _) if def.is_enum() && def.variants.len() > 1 =>
-            def.variants.iter().map(|v| Variant(v.did)).collect(),
-        _ => vec![Single]
+        ty::TySlice(ref sub_ty) => {
+            if sub_ty.is_uninhabited(Some(cx.node), cx.tcx) {
+                vec![Slice(0)]
+            } else {
+                (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
+            }
+        }
+        ty::TyArray(ref sub_ty, length) => {
+            if length == 0 || !sub_ty.is_uninhabited(Some(cx.node), cx.tcx) {
+                vec![Slice(length)]
+            } else {
+                vec![]
+            }
+        }
+        ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
+            def.variants.iter().filter_map(|v| {
+                let mut visited = FxHashSet::default();
+                if v.is_uninhabited_recurse(&mut visited, Some(cx.node), cx.tcx, substs, false) {
+                    None
+                } else {
+                    Some(Variant(v.did))
+                }
+            }).collect()
+        }
+        _ => {
+            if pcx.ty.is_uninhabited(Some(cx.node), cx.tcx) {
+                vec![]
+            } else {
+                vec![Single]
+            }
+        }
     }
 }
 
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 53e83815b46..d6187f40b7f 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -25,6 +25,7 @@ use rustc::middle::mem_categorization::{cmt};
 use rustc::session::Session;
 use rustc::traits::Reveal;
 use rustc::ty::{self, TyCtxt};
+use rustc::lint;
 use rustc_errors::DiagnosticBuilder;
 
 use rustc::hir::def::*;
@@ -150,7 +151,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             }
         }
 
-        MatchCheckCtxt::create_and_enter(self.tcx, |ref mut cx| {
+        MatchCheckCtxt::create_and_enter(self.tcx, scrut.id, |ref mut cx| {
             let mut have_errors = false;
 
             let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| (
@@ -210,7 +211,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             "local binding"
         };
 
-        MatchCheckCtxt::create_and_enter(self.tcx, |ref mut cx| {
+        MatchCheckCtxt::create_and_enter(self.tcx, pat.id, |ref mut cx| {
             let mut patcx = PatternContext::new(self.tcx);
             let pats : Matrix = vec![vec![
                 expand_pattern(cx, patcx.lower_pattern(pat))
@@ -324,14 +325,19 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                         },
 
                         hir::MatchSource::Normal => {
-                            let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
-                                                           "unreachable pattern");
-                            err.span_label(pat.span, &"this is an unreachable pattern");
-                            // if we had a catchall pattern, hint at that
+                            // if we had a catchall pattern, raise an error.
+                            // Otherwise an unreachable pattern raises a warning.
                             if let Some(catchall) = catchall {
+                                let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
+                                                               "unreachable pattern");
+                                err.span_label(pat.span, &"this is an unreachable pattern");
                                 err.span_note(catchall, "this pattern matches any value");
+                                err.emit();
+                            } else {
+                                cx.tcx.sess.add_lint(lint::builtin::UNREACHABLE_PATTERNS,
+                                                     hir_pat.id, pat.span,
+                                                     String::from("unreachable pattern"));
                             }
-                            err.emit();
                         },
 
                         hir::MatchSource::TryDesugar => {
diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs
index b24cd261dd5..139443a1719 100644
--- a/src/librustc_const_eval/diagnostics.rs
+++ b/src/librustc_const_eval/diagnostics.rs
@@ -28,7 +28,7 @@ For example, the following `match` block has too many arms:
 ```compile_fail,E0001
 match Some(0) {
     Some(bar) => {/* ... */}
-    None => {/* ... */}
+    x => {/* ... */} // This handles the `None` case
     _ => {/* ... */} // All possible cases have already been handled
 }
 ```
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index a24edfaaac1..efccc4abd43 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -165,6 +165,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                     DEAD_CODE,
                     UNUSED_MUT,
                     UNREACHABLE_CODE,
+                    UNREACHABLE_PATTERNS,
                     UNUSED_MUST_USE,
                     UNUSED_UNSAFE,
                     PATH_STATEMENTS,
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 9b86196b3ec..0fa9062df45 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -399,7 +399,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.check_pat(&p, discrim_ty);
                 all_pats_diverge &= self.diverges.get();
             }
-            all_pats_diverge
+            // As discussed with @eddyb, this is for disabling unreachable_code
+            // warnings on patterns (they're now subsumed by unreachable_patterns
+            // warnings).
+            match all_pats_diverge {
+                Diverges::Maybe => Diverges::Maybe,
+                Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
+            }
         }).collect();
 
         // Now typecheck the blocks.
diff --git a/src/test/compile-fail/E0001.rs b/src/test/compile-fail/E0001.rs
index 906642d8555..b72b0d66190 100644
--- a/src/test/compile-fail/E0001.rs
+++ b/src/test/compile-fail/E0001.rs
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(unreachable_patterns)]
+
 fn main() {
     let foo = Some(1);
     match foo {
-        Some(bar) => {/* ... */}
+        Some(_) => {/* ... */}
         None => {/* ... */}
-        _ => {/* ... */} //~ ERROR E0001
+        _ => {/* ... */} //~ ERROR unreachable pattern
     }
 }
diff --git a/src/test/compile-fail/issue-12116.rs b/src/test/compile-fail/issue-12116.rs
index 1978068575b..24765cfc2a6 100644
--- a/src/test/compile-fail/issue-12116.rs
+++ b/src/test/compile-fail/issue-12116.rs
@@ -20,7 +20,7 @@ fn tail(source_list: &IntList) -> IntList {
     match source_list {
         &IntList::Cons(val, box ref next_list) => tail(next_list),
         &IntList::Cons(val, box Nil)           => IntList::Cons(val, box Nil),
-//~^ ERROR unreachable pattern
+//~^ ERROR cannot move out of borrowed content
 //~^^ WARN pattern binding `Nil` is named the same as one of the variants of the type `IntList`
         _                          => panic!()
     }
diff --git a/src/test/compile-fail/issue-12369.rs b/src/test/compile-fail/issue-12369.rs
index 978d6f59b2d..4df1e24dcfb 100644
--- a/src/test/compile-fail/issue-12369.rs
+++ b/src/test/compile-fail/issue-12369.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #![feature(slice_patterns)]
+#![allow(unused_variables)]
+#![deny(unreachable_patterns)]
 
 fn main() {
     let sl = vec![1,2,3];
diff --git a/src/test/compile-fail/issue-13727.rs b/src/test/compile-fail/issue-13727.rs
index 28c2c7bc0e2..2e815548e89 100644
--- a/src/test/compile-fail/issue-13727.rs
+++ b/src/test/compile-fail/issue-13727.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(overflowing_literals)]
+#![deny(unreachable_patterns)]
+
 fn test(val: u8) {
   match val {
     256 => print!("0b1110\n"),
diff --git a/src/test/compile-fail/issue-30240-b.rs b/src/test/compile-fail/issue-30240-b.rs
new file mode 100644
index 00000000000..cf6935b9ba6
--- /dev/null
+++ b/src/test/compile-fail/issue-30240-b.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+#![deny(unreachable_patterns)]
+
+fn main() {
+    match "world" {
+        "hello" => {}
+        _ => {},
+    }
+
+    match "world" {
+        ref _x if false => {}
+        "hello" => {}
+        "hello" => {} //~ ERROR unreachable pattern
+        _ => {},
+    }
+}
+
diff --git a/src/test/compile-fail/issue-30240.rs b/src/test/compile-fail/issue-30240.rs
index 9b105e7ec15..60fb307d4e1 100644
--- a/src/test/compile-fail/issue-30240.rs
+++ b/src/test/compile-fail/issue-30240.rs
@@ -16,6 +16,5 @@ fn main() {
     match "world" { //~ ERROR non-exhaustive patterns: `&_`
         ref _x if false => {}
         "hello" => {}
-        "hello" => {} //~ ERROR unreachable pattern
     }
 }
diff --git a/src/test/compile-fail/issue-31221.rs b/src/test/compile-fail/issue-31221.rs
index 4997a6fee19..8cf6725cec4 100644
--- a/src/test/compile-fail/issue-31221.rs
+++ b/src/test/compile-fail/issue-31221.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(unreachable_patterns)]
+
 enum Enum {
     Var1,
     Var2,
@@ -41,13 +43,4 @@ fn main() {
         //~^ ERROR unreachable pattern
         //~^^ NOTE this is an unreachable pattern
     };
-    // `_` need not emit a note, it is pretty obvious already.
-    let t = (Var1, Var1);
-    match t {
-        (Var1, b) => (),
-        _ => (),
-        anything => ()
-        //~^ ERROR unreachable pattern
-        //~^^ NOTE this is an unreachable pattern
-    };
 }
diff --git a/src/test/compile-fail/issue-3601.rs b/src/test/compile-fail/issue-3601.rs
index b25e683db09..cc69a76e043 100644
--- a/src/test/compile-fail/issue-3601.rs
+++ b/src/test/compile-fail/issue-3601.rs
@@ -40,6 +40,5 @@ fn main() {
         box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
             box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
         },
-        _ => panic!("WAT") //~ ERROR unreachable pattern
     };
 }
diff --git a/src/test/compile-fail/match-argm-statics-2.rs b/src/test/compile-fail/match-argm-statics-2.rs
new file mode 100644
index 00000000000..40dcf3d0f12
--- /dev/null
+++ b/src/test/compile-fail/match-argm-statics-2.rs
@@ -0,0 +1,71 @@
+// Copyright 2014 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.
+
+use self::Direction::{North, East, South, West};
+
+struct NewBool(bool);
+
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+
+const TRUE_TRUE: (bool, bool) = (true, true);
+
+fn nonexhaustive_1() {
+    match (true, false) {
+    //~^ ERROR non-exhaustive patterns: `(true, false)` not covered
+        TRUE_TRUE => (),
+        (false, false) => (),
+        (false, true) => ()
+    }
+}
+
+const NONE: Option<Direction> = None;
+const EAST: Direction = East;
+
+fn nonexhaustive_2() {
+    match Some(Some(North)) {
+    //~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
+        Some(NONE) => (),
+        Some(Some(North)) => (),
+        Some(Some(EAST)) => (),
+        Some(Some(South)) => (),
+        None => ()
+    }
+}
+
+const NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+
+const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
+
+fn nonexhaustive_3() {
+    match (Foo { bar: Some(North), baz: NewBool(true) }) {
+    //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }`
+        Foo { bar: None, baz: NewBool(true) } => (),
+        Foo { bar: _, baz: NEW_FALSE } => (),
+        Foo { bar: Some(West), baz: NewBool(true) } => (),
+        Foo { bar: Some(South), .. } => (),
+        Foo { bar: Some(EAST), .. } => ()
+    }
+}
+
+fn main() {
+    nonexhaustive_1();
+    nonexhaustive_2();
+    nonexhaustive_3();
+}
+
diff --git a/src/test/compile-fail/match-arm-statics.rs b/src/test/compile-fail/match-arm-statics.rs
index 9b313f248fc..40d73ab51c7 100644
--- a/src/test/compile-fail/match-arm-statics.rs
+++ b/src/test/compile-fail/match-arm-statics.rs
@@ -7,10 +7,16 @@
 // <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.
+
+#![allow(dead_code)]
+#![deny(unreachable_patterns)]
+
 use self::Direction::{North, East, South, West};
 
+#[derive(PartialEq, Eq)]
 struct NewBool(bool);
 
+#[derive(PartialEq, Eq)]
 enum Direction {
     North,
     East,
@@ -20,15 +26,6 @@ enum Direction {
 
 const TRUE_TRUE: (bool, bool) = (true, true);
 
-fn nonexhaustive_1() {
-    match (true, false) {
-    //~^ ERROR non-exhaustive patterns: `(true, false)` not covered
-        TRUE_TRUE => (),
-        (false, false) => (),
-        (false, true) => ()
-    }
-}
-
 fn unreachable_1() {
     match (true, false) {
         TRUE_TRUE => (),
@@ -43,17 +40,6 @@ fn unreachable_1() {
 const NONE: Option<Direction> = None;
 const EAST: Direction = East;
 
-fn nonexhaustive_2() {
-    match Some(Some(North)) {
-    //~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
-        Some(NONE) => (),
-        Some(Some(North)) => (),
-        Some(Some(EAST)) => (),
-        Some(Some(South)) => (),
-        None => ()
-    }
-}
-
 fn unreachable_2() {
     match Some(Some(North)) {
         Some(NONE) => (),
@@ -73,19 +59,6 @@ struct Foo {
     baz: NewBool
 }
 
-const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
-
-fn nonexhaustive_3() {
-    match (Foo { bar: Some(North), baz: NewBool(true) }) {
-    //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }`
-        Foo { bar: None, baz: NewBool(true) } => (),
-        Foo { bar: _, baz: NEW_FALSE } => (),
-        Foo { bar: Some(West), baz: NewBool(true) } => (),
-        Foo { bar: Some(South), .. } => (),
-        Foo { bar: Some(EAST), .. } => ()
-    }
-}
-
 fn unreachable_3() {
     match (Foo { bar: Some(EAST), baz: NewBool(true) }) {
         Foo { bar: None, baz: NewBool(true) } => (),
@@ -100,9 +73,6 @@ fn unreachable_3() {
 }
 
 fn main() {
-    nonexhaustive_1();
-    nonexhaustive_2();
-    nonexhaustive_3();
     unreachable_1();
     unreachable_2();
     unreachable_3();
diff --git a/src/test/compile-fail/match-byte-array-patterns-2.rs b/src/test/compile-fail/match-byte-array-patterns-2.rs
new file mode 100644
index 00000000000..ad7e931a0ec
--- /dev/null
+++ b/src/test/compile-fail/match-byte-array-patterns-2.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+#![feature(advanced_slice_patterns, slice_patterns)]
+
+fn main() {
+    let buf = &[0, 1, 2, 3];
+
+    match buf { //~ ERROR non-exhaustive
+        b"AAAA" => {}
+    }
+
+    let buf: &[u8] = buf;
+
+    match buf { //~ ERROR non-exhaustive
+        b"AAAA" => {}
+    }
+}
+
diff --git a/src/test/compile-fail/match-byte-array-patterns.rs b/src/test/compile-fail/match-byte-array-patterns.rs
index 86323656b87..1ff07eae1c9 100644
--- a/src/test/compile-fail/match-byte-array-patterns.rs
+++ b/src/test/compile-fail/match-byte-array-patterns.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(advanced_slice_patterns, slice_patterns)]
+#![deny(unreachable_patterns)]
 
 fn main() {
     let buf = &[0, 1, 2, 3];
@@ -37,10 +38,6 @@ fn main() {
         _ => {}
     }
 
-    match buf { //~ ERROR non-exhaustive
-        b"AAAA" => {}
-    }
-
     let buf: &[u8] = buf;
 
     match buf {
@@ -66,8 +63,4 @@ fn main() {
         b"AAAA" => {}, //~ ERROR unreachable pattern
         _ => {}
     }
-
-    match buf { //~ ERROR non-exhaustive
-        b"AAAA" => {}
-    }
 }
diff --git a/src/test/compile-fail/match-range-fail-dominate.rs b/src/test/compile-fail/match-range-fail-dominate.rs
index 825a485d529..256aa180f4a 100644
--- a/src/test/compile-fail/match-range-fail-dominate.rs
+++ b/src/test/compile-fail/match-range-fail-dominate.rs
@@ -14,6 +14,8 @@
 //error-pattern: unreachable
 //error-pattern: unreachable
 
+#![deny(unreachable_patterns)]
+
 fn main() {
     match 5 {
       1 ... 10 => { }
diff --git a/src/test/compile-fail/match-ref-ice.rs b/src/test/compile-fail/match-ref-ice.rs
index 042ec95f7e7..1cdbba17f65 100644
--- a/src/test/compile-fail/match-ref-ice.rs
+++ b/src/test/compile-fail/match-ref-ice.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
 
 // The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose
 // arity is always 0, an ICE occurs.
@@ -19,7 +20,7 @@ fn main() {
     let homura = [1, 2, 3];
 
     match homura {
-        [1, ref madoka, 3] => (),
+        [1, ref _madoka, 3] => (),
         [1, 2, 3] => (), //~ ERROR unreachable pattern
         [_, _, _] => (),
     }
diff --git a/src/test/compile-fail/match-vec-fixed.rs b/src/test/compile-fail/match-vec-fixed.rs
index 60d0c24bb3d..dd9379c756d 100644
--- a/src/test/compile-fail/match-vec-fixed.rs
+++ b/src/test/compile-fail/match-vec-fixed.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
 
 fn a() {
     let v = [1, 2, 3];
diff --git a/src/test/compile-fail/match-vec-unreachable.rs b/src/test/compile-fail/match-vec-unreachable.rs
index 4d9b3aea112..6b8111ac313 100644
--- a/src/test/compile-fail/match-vec-unreachable.rs
+++ b/src/test/compile-fail/match-vec-unreachable.rs
@@ -9,13 +9,14 @@
 // except according to those terms.
 
 #![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
 
 fn main() {
     let x: Vec<(isize, isize)> = Vec::new();
     let x: &[(isize, isize)] = &x;
     match *x {
-        [a, (2, 3), _] => (),
-        [(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern
+        [_, (2, 3), _] => (),
+        [(1, 2), (2, 3), _] => (), //~ ERROR unreachable pattern
         _ => ()
     }
 
@@ -24,7 +25,7 @@ fn main() {
                               "baz".to_string()];
     let x: &[String] = &x;
     match *x {
-        [a, _, _, ..] => { println!("{}", a); }
+        [ref a, _, _, ..] => { println!("{}", a); }
         [_, _, _, _, _] => { } //~ ERROR unreachable pattern
         _ => { }
     }
diff --git a/src/test/compile-fail/struct-pattern-match-useless.rs b/src/test/compile-fail/struct-pattern-match-useless.rs
index 9f7ebc261ad..dda30141b4a 100644
--- a/src/test/compile-fail/struct-pattern-match-useless.rs
+++ b/src/test/compile-fail/struct-pattern-match-useless.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(unreachable_patterns)]
+
 struct Foo {
     x: isize,
     y: isize,
@@ -16,7 +18,7 @@ struct Foo {
 pub fn main() {
     let a = Foo { x: 1, y: 2 };
     match a {
-        Foo { x: x, y: y } => (),
+        Foo { x: _x, y: _y } => (),
         Foo { .. } => () //~ ERROR unreachable pattern
     }
 
diff --git a/src/test/compile-fail/unreachable-arm.rs b/src/test/compile-fail/unreachable-arm.rs
index bc93b86a391..461f092b98b 100644
--- a/src/test/compile-fail/unreachable-arm.rs
+++ b/src/test/compile-fail/unreachable-arm.rs
@@ -12,7 +12,16 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![allow(dead_code)]
+#![deny(unreachable_patterns)]
 
-enum foo { a(Box<foo>, isize), b(usize), }
+enum Foo { A(Box<Foo>, isize), B(usize), }
+
+fn main() {
+    match Foo::B(1) {
+        Foo::B(_) | Foo::A(box _, 1) => { }
+        Foo::A(_, 1) => { }
+        _ => { }
+    }
+}
 
-fn main() { match foo::b(1) { foo::b(_) | foo::a(box _, 1) => { } foo::a(_, 1) => { } } }