about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStepan Koltsov <stepan.koltsov@gmail.com>2013-08-07 22:07:24 +0400
committerStepan Koltsov <stepan.koltsov@gmail.com>2013-08-07 22:07:24 +0400
commit828bfb2c61aaac93325b00737362769d045b6438 (patch)
treedbe318e98a06cc74b166f3c3e2f19b56984582e8
parent29ffbbaaa850d3f8fe1b35e3a63defe9206a3eb7 (diff)
downloadrust-828bfb2c61aaac93325b00737362769d045b6438.tar.gz
rust-828bfb2c61aaac93325b00737362769d045b6438.zip
Fix incorrect non-exhaustive matching for fixed length vecs
Code like this is fixed now:

```
fn foo(p: [u8, ..4]) {
    match p {
        [a, b, c, d] => {}
    };
}
```

Invalid constructors are not reported as errors yet:

```
fn foo(p: [u8, ..4]) {
    match p {
        [_, _, _] => {} // this should be error
        [_, _, _, _, _, .._] => {} // and this
        _ => {}
    }
}
```

Issue #8311 is partially fixed by this commit. Fixed-length arrays in
let statement are not yet allowed:

```
let [a, b, c] = [1, 2, 3]; // still fails
```
-rw-r--r--doc/tutorial.md2
-rw-r--r--src/librustc/middle/check_match.rs26
-rw-r--r--src/test/compile-fail/borrowck-move-out-of-vec-tail.rs2
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-element-loan.rs6
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-nesting.rs14
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs2
-rw-r--r--src/test/compile-fail/match-vec-fixed.rs16
-rw-r--r--src/test/compile-fail/match-vec-unreachable.rs4
-rw-r--r--src/test/run-pass/vec-matching-fixed.rs28
-rw-r--r--src/test/run-pass/vec-matching.rs4
-rw-r--r--src/test/run-pass/vec-tail-matching.rs2
11 files changed, 88 insertions, 18 deletions
diff --git a/doc/tutorial.md b/doc/tutorial.md
index a5f2001eaf5..b721a3628c9 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -1305,7 +1305,7 @@ match crayons[0] {
 A vector can be destructured using pattern matching:
 
 ~~~~
-let numbers: [int, ..3] = [1, 2, 3];
+let numbers: &[int] = &[1, 2, 3];
 let score = match numbers {
     [] => 0,
     [a] => a * 10,
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 1b420b9c06a..1422e17b059 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -255,6 +255,9 @@ pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
                 }
                 not_useful
               }
+              ty::ty_evec(_, ty::vstore_fixed(n)) => {
+                is_useful_specialized(cx, m, v, vec(n), n, left_ty)
+              }
               ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
                 let max_len = do m.rev_iter().fold(0) |max_len, r| {
                   match r[0].node {
@@ -409,6 +412,29 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
         else if true_found { Some(val(const_bool(false))) }
         else { Some(val(const_bool(true))) }
       }
+      ty::ty_evec(_, ty::vstore_fixed(n)) => {
+        let mut missing = true;
+        let mut wrong = false;
+        for r in m.iter() {
+          match r[0].node {
+            pat_vec(ref before, ref slice, ref after) => {
+              let count = before.len() + after.len();
+              if (count < n && slice.is_none()) || count > n {
+                wrong = true;
+              }
+              if count == n || (count < n && slice.is_some()) {
+                missing = false;
+              }
+            }
+            _ => {}
+          }
+        }
+        match (wrong, missing) {
+          (true, _) => Some(vec(n)), // should be compile-time error
+          (_, true) => Some(vec(n)),
+          _         => None
+        }
+      }
       ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
 
         // Find the lengths and slices of all vector patterns.
diff --git a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
index 39a0e585ad2..0f67d8a6d0c 100644
--- a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
+++ b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
@@ -6,7 +6,7 @@ struct Foo {
 }
 
 pub fn main() {
-    let x = [
+    let x = ~[
         Foo { string: ~"foo" },
         Foo { string: ~"bar" },
         Foo { string: ~"baz" }
diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
index 7f98eba5996..ca20d68e4cd 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
@@ -1,5 +1,5 @@
 fn a() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let tail = match vec {
         [_, ..tail] => tail, //~ ERROR does not live long enough
         _ => fail!("a")
@@ -8,7 +8,7 @@ fn a() -> &[int] {
 }
 
 fn b() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let init = match vec {
         [..init, _] => init, //~ ERROR does not live long enough
         _ => fail!("b")
@@ -17,7 +17,7 @@ fn b() -> &[int] {
 }
 
 fn c() -> &[int] {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let slice = match vec {
         [_, ..slice, _] => slice, //~ ERROR does not live long enough
         _ => fail!("c")
diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
index 36ae5f88208..02ba1b9d2ff 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
@@ -1,24 +1,24 @@
 fn a() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [~ref _a] => {
-            vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
+            vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
         }
         _ => fail!("foo")
     }
 }
 
 fn b() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [.._b] => {
-            vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
+            vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
         }
     }
 }
 
 fn c() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [_a, .._b] => {
             //~^ ERROR cannot move out
@@ -35,7 +35,7 @@ fn c() {
 }
 
 fn d() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [.._a, _b] => {
             //~^ ERROR cannot move out
@@ -46,7 +46,7 @@ fn d() {
 }
 
 fn e() {
-    let mut vec = [~1, ~2, ~3];
+    let mut vec = ~[~1, ~2, ~3];
     match vec {
         [_a, _b, _c] => {}
         _ => {}
diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
index e3e12a4a416..87511c34172 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
@@ -1,5 +1,5 @@
 fn a() -> &int {
-    let vec = [1, 2, 3, 4];
+    let vec = ~[1, 2, 3, 4];
     let tail = match vec {
         [_a, ..tail] => &tail[0], //~ ERROR borrowed value does not live long enough
         _ => fail!("foo")
diff --git a/src/test/compile-fail/match-vec-fixed.rs b/src/test/compile-fail/match-vec-fixed.rs
new file mode 100644
index 00000000000..b3e139805a0
--- /dev/null
+++ b/src/test/compile-fail/match-vec-fixed.rs
@@ -0,0 +1,16 @@
+fn a() {
+    let v = [1, 2, 3];
+    match v {
+        [_, _, _] => {}
+        [_, _, _] => {} //~ ERROR unreachable pattern
+    }
+    match v {
+        [_, 1, _] => {}
+        [_, 1, _] => {} //~ ERROR unreachable pattern
+        _ => {}
+    }
+}
+
+fn main() {
+    a();
+}
diff --git a/src/test/compile-fail/match-vec-unreachable.rs b/src/test/compile-fail/match-vec-unreachable.rs
index 3930e7d2192..b557242af44 100644
--- a/src/test/compile-fail/match-vec-unreachable.rs
+++ b/src/test/compile-fail/match-vec-unreachable.rs
@@ -6,13 +6,13 @@ fn main() {
         _ => ()
     }
 
-    match [~"foo", ~"bar", ~"baz"] {
+    match ~[~"foo", ~"bar", ~"baz"] {
         [a, _, _, .._] => { println(a); }
         [~"foo", ~"bar", ~"baz", ~"foo", ~"bar"] => { } //~ ERROR unreachable pattern
         _ => { }
     }
 
-    match ['a', 'b', 'c'] {
+    match ~['a', 'b', 'c'] {
         ['a', 'b', 'c', .._tail] => {}
         ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
         _ => {}
diff --git a/src/test/run-pass/vec-matching-fixed.rs b/src/test/run-pass/vec-matching-fixed.rs
new file mode 100644
index 00000000000..234311dec33
--- /dev/null
+++ b/src/test/run-pass/vec-matching-fixed.rs
@@ -0,0 +1,28 @@
+fn a() {
+    let x = [1, 2, 3];
+    match x {
+        [1, 2, 4] => ::std::util::unreachable(),
+        [0, 2, 3, .._] => ::std::util::unreachable(),
+        [0, .._, 3] => ::std::util::unreachable(),
+        [0, .._] => ::std::util::unreachable(),
+        [1, 2, 3] => (),
+        [_, _, _] => ::std::util::unreachable(),
+    }
+    match x {
+        [.._] => (),
+    }
+    match x {
+        [_, _, _, .._] => (),
+    }
+    match x {
+        [a, b, c] => {
+            assert_eq!(1, a);
+            assert_eq!(2, b);
+            assert_eq!(3, c);
+        }
+    }
+}
+
+pub fn main() {
+    a();
+}
diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs
index 5e906fa2659..fb73c7e097d 100644
--- a/src/test/run-pass/vec-matching.rs
+++ b/src/test/run-pass/vec-matching.rs
@@ -1,5 +1,5 @@
 fn a() {
-    let x = [1];
+    let x = ~[1];
     match x {
         [_, _, _, _, _, .._] => ::std::util::unreachable(),
         [.._, _, _, _, _] => ::std::util::unreachable(),
@@ -13,7 +13,7 @@ fn a() {
 }
 
 fn b() {
-    let x = [1, 2, 3];
+    let x = ~[1, 2, 3];
     match x {
         [a, b, ..c] => {
             assert_eq!(a, 1);
diff --git a/src/test/run-pass/vec-tail-matching.rs b/src/test/run-pass/vec-tail-matching.rs
index 27f4fc83351..6a60308f2e7 100644
--- a/src/test/run-pass/vec-tail-matching.rs
+++ b/src/test/run-pass/vec-tail-matching.rs
@@ -3,7 +3,7 @@ struct Foo {
 }
 
 pub fn main() {
-    let x = [
+    let x = ~[
         Foo { string: ~"foo" },
         Foo { string: ~"bar" },
         Foo { string: ~"baz" }