about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJakub Wieczorek <jakub@jakub.cc>2014-05-31 15:13:46 +0200
committerJakub Wieczorek <jakub@jakub.cc>2014-06-20 17:08:57 +0200
commitf5e513b2b2dd173f16b84f0531fc3628d62beb4d (patch)
tree26e7abc4c449cb9887303f77ae009a14ede0b80a /src
parent6750eb5a05042fe3fb84708909074f33ad86d3ec (diff)
downloadrust-f5e513b2b2dd173f16b84f0531fc3628d62beb4d.tar.gz
rust-f5e513b2b2dd173f16b84f0531fc3628d62beb4d.zip
Check pattern refutability the same way exhaustiveness is checked
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/check_match.rs89
-rw-r--r--src/test/compile-fail/precise-refutable-pattern-errors.rs32
-rw-r--r--src/test/compile-fail/refutable-pattern-errors.rs18
3 files changed, 44 insertions, 95 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index d8f7a97ce13..8483ffaa438 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -750,12 +750,15 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
         LocalFor => "`for` loop"
     };
 
-    let mut spans = vec![];
-    find_refutable(cx, &*loc.pat, &mut spans);
-
-    for span in spans.iter() {
-        cx.tcx.sess.span_err(*span,
-                             format!("refutable pattern in {} binding", name).as_slice());
+    match is_refutable(cx, loc.pat) {
+        Some(pat) => {
+            let msg = format!(
+                "refutable pattern in {} binding: {} not covered",
+                name, pat_to_str(&*pat)
+            );
+            cx.tcx.sess.span_err(loc.pat.span, msg.as_slice());
+        },
+        None => ()
     }
 
     // Check legality of move bindings.
@@ -769,67 +772,27 @@ fn check_fn(cx: &mut MatchCheckCtxt,
             sp: Span) {
     visit::walk_fn(cx, kind, decl, body, sp, ());
     for input in decl.inputs.iter() {
-        let mut spans = vec![];
-        find_refutable(cx, &*input.pat, &mut spans);
-
-        for span in spans.iter() {
-            cx.tcx.sess.span_err(*span,
-                                 "refutable pattern in function argument");
+        match is_refutable(cx, input.pat) {
+            Some(pat) => {
+                let msg = format!(
+                    "refutable pattern in function argument: {} not covered",
+                    pat_to_str(&*pat)
+                );
+                cx.tcx.sess.span_err(input.pat.span, msg.as_slice());
+            },
+            None => ()
         }
     }
 }
 
-fn find_refutable(cx: &MatchCheckCtxt, pat: &Pat, spans: &mut Vec<Span>) {
-    macro_rules! this_pattern {
-        () => {
-            {
-                spans.push(pat.span);
-                return
-            }
-        }
-    }
-    let opt_def = cx.tcx.def_map.borrow().find_copy(&pat.id);
-    match opt_def {
-      Some(DefVariant(enum_id, _, _)) => {
-        if ty::enum_variants(cx.tcx, enum_id).len() != 1u {
-            this_pattern!()
-        }
-      }
-      Some(DefStatic(..)) => this_pattern!(),
-      _ => ()
-    }
-
-    match pat.node {
-      PatBox(ref sub) | PatRegion(ref sub) | PatIdent(_, _, Some(ref sub)) => {
-        find_refutable(cx, &**sub, spans)
-      }
-      PatWild | PatWildMulti | PatIdent(_, _, None) => {}
-      PatLit(lit) => {
-          match lit.node {
-            ExprLit(lit) => {
-                match lit.node {
-                    LitNil => {}    // `()`
-                    _ => this_pattern!(),
-                }
-            }
-            _ => this_pattern!(),
-          }
-      }
-      PatRange(_, _) => { this_pattern!() }
-      PatStruct(_, ref fields, _) => {
-          for f in fields.iter() {
-              find_refutable(cx, &*f.pat, spans);
-          }
-      }
-      PatTup(ref elts) | PatEnum(_, Some(ref elts))=> {
-          for elt in elts.iter() {
-              find_refutable(cx, &**elt, spans)
-          }
-      }
-      PatEnum(_,_) => {}
-      PatVec(..) => { this_pattern!() }
-      PatMac(_) => cx.tcx.sess.bug("unexpanded macro"),
-    }
+fn is_refutable(cx: &MatchCheckCtxt, pat: Gc<Pat>) -> Option<Gc<Pat>> {
+    let pats = vec!(vec!(pat));
+    is_useful(cx, &pats, [wild()])
+        .useful()
+        .map(|pats| {
+            assert_eq!(pats.len(), 1);
+            pats.get(0).clone()
+        })
 }
 
 // Legality of move bindings checking
diff --git a/src/test/compile-fail/precise-refutable-pattern-errors.rs b/src/test/compile-fail/precise-refutable-pattern-errors.rs
deleted file mode 100644
index efa2dbad83f..00000000000
--- a/src/test/compile-fail/precise-refutable-pattern-errors.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-
-fn func(
-    (
-        1, //~ ERROR refutable pattern in function argument
-        (
-            Some( //~ ERROR refutable pattern in function argument
-                1), // nested, so no warning.
-            2..3 //~ ERROR refutable pattern in function argument
-            )
-        ): (int, (Option<int>, int))
-        ) {}
-
-fn main() {
-    let (
-        1, //~ ERROR refutable pattern in local binding
-        (
-            Some( //~ ERROR refutable pattern in local binding
-                1), // nested, so no warning.
-            2..3 //~ ERROR refutable pattern in local binding
-            )
-        ) = (1, (None, 2));
-}
diff --git a/src/test/compile-fail/refutable-pattern-errors.rs b/src/test/compile-fail/refutable-pattern-errors.rs
new file mode 100644
index 00000000000..38b9b888e06
--- /dev/null
+++ b/src/test/compile-fail/refutable-pattern-errors.rs
@@ -0,0 +1,18 @@
+// 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.
+
+
+fn func((1, (Some(1), 2..3)): (int, (Option<int>, int))) { }
+//~^ ERROR refutable pattern in function argument
+
+fn main() {
+    let (1, (Some(1), 2..3)) = (1, (None, 2));
+    //~^ ERROR refutable pattern in local binding
+}