Skip to content

Commit 828bfb2

Browse files
committed
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 ```
1 parent 29ffbba commit 828bfb2

11 files changed

+88
-18
lines changed

doc/tutorial.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ match crayons[0] {
13051305
A vector can be destructured using pattern matching:
13061306
13071307
~~~~
1308-
let numbers: [int, ..3] = [1, 2, 3];
1308+
let numbers: &[int] = &[1, 2, 3];
13091309
let score = match numbers {
13101310
[] => 0,
13111311
[a] => a * 10,

src/librustc/middle/check_match.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ pub fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
255255
}
256256
not_useful
257257
}
258+
ty::ty_evec(_, ty::vstore_fixed(n)) => {
259+
is_useful_specialized(cx, m, v, vec(n), n, left_ty)
260+
}
258261
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
259262
let max_len = do m.rev_iter().fold(0) |max_len, r| {
260263
match r[0].node {
@@ -409,6 +412,29 @@ pub fn missing_ctor(cx: &MatchCheckCtxt,
409412
else if true_found { Some(val(const_bool(false))) }
410413
else { Some(val(const_bool(true))) }
411414
}
415+
ty::ty_evec(_, ty::vstore_fixed(n)) => {
416+
let mut missing = true;
417+
let mut wrong = false;
418+
for r in m.iter() {
419+
match r[0].node {
420+
pat_vec(ref before, ref slice, ref after) => {
421+
let count = before.len() + after.len();
422+
if (count < n && slice.is_none()) || count > n {
423+
wrong = true;
424+
}
425+
if count == n || (count < n && slice.is_some()) {
426+
missing = false;
427+
}
428+
}
429+
_ => {}
430+
}
431+
}
432+
match (wrong, missing) {
433+
(true, _) => Some(vec(n)), // should be compile-time error
434+
(_, true) => Some(vec(n)),
435+
_ => None
436+
}
437+
}
412438
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
413439

414440
// Find the lengths and slices of all vector patterns.

src/test/compile-fail/borrowck-move-out-of-vec-tail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ struct Foo {
66
}
77

88
pub fn main() {
9-
let x = [
9+
let x = ~[
1010
Foo { string: ~"foo" },
1111
Foo { string: ~"bar" },
1212
Foo { string: ~"baz" }

src/test/compile-fail/borrowck-vec-pattern-element-loan.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn a() -> &[int] {
2-
let vec = [1, 2, 3, 4];
2+
let vec = ~[1, 2, 3, 4];
33
let tail = match vec {
44
[_, ..tail] => tail, //~ ERROR does not live long enough
55
_ => fail!("a")
@@ -8,7 +8,7 @@ fn a() -> &[int] {
88
}
99

1010
fn b() -> &[int] {
11-
let vec = [1, 2, 3, 4];
11+
let vec = ~[1, 2, 3, 4];
1212
let init = match vec {
1313
[..init, _] => init, //~ ERROR does not live long enough
1414
_ => fail!("b")
@@ -17,7 +17,7 @@ fn b() -> &[int] {
1717
}
1818

1919
fn c() -> &[int] {
20-
let vec = [1, 2, 3, 4];
20+
let vec = ~[1, 2, 3, 4];
2121
let slice = match vec {
2222
[_, ..slice, _] => slice, //~ ERROR does not live long enough
2323
_ => fail!("c")

src/test/compile-fail/borrowck-vec-pattern-nesting.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
fn a() {
2-
let mut vec = [~1, ~2, ~3];
2+
let mut vec = ~[~1, ~2, ~3];
33
match vec {
44
[~ref _a] => {
5-
vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
5+
vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
66
}
77
_ => fail!("foo")
88
}
99
}
1010

1111
fn b() {
12-
let mut vec = [~1, ~2, ~3];
12+
let mut vec = ~[~1, ~2, ~3];
1313
match vec {
1414
[.._b] => {
15-
vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
15+
vec[0] = ~4; //~ ERROR cannot assign to `(*vec)[]` because it is borrowed
1616
}
1717
}
1818
}
1919

2020
fn c() {
21-
let mut vec = [~1, ~2, ~3];
21+
let mut vec = ~[~1, ~2, ~3];
2222
match vec {
2323
[_a, .._b] => {
2424
//~^ ERROR cannot move out
@@ -35,7 +35,7 @@ fn c() {
3535
}
3636

3737
fn d() {
38-
let mut vec = [~1, ~2, ~3];
38+
let mut vec = ~[~1, ~2, ~3];
3939
match vec {
4040
[.._a, _b] => {
4141
//~^ ERROR cannot move out
@@ -46,7 +46,7 @@ fn d() {
4646
}
4747

4848
fn e() {
49-
let mut vec = [~1, ~2, ~3];
49+
let mut vec = ~[~1, ~2, ~3];
5050
match vec {
5151
[_a, _b, _c] => {}
5252
_ => {}

src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn a() -> &int {
2-
let vec = [1, 2, 3, 4];
2+
let vec = ~[1, 2, 3, 4];
33
let tail = match vec {
44
[_a, ..tail] => &tail[0], //~ ERROR borrowed value does not live long enough
55
_ => fail!("foo")
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
fn a() {
2+
let v = [1, 2, 3];
3+
match v {
4+
[_, _, _] => {}
5+
[_, _, _] => {} //~ ERROR unreachable pattern
6+
}
7+
match v {
8+
[_, 1, _] => {}
9+
[_, 1, _] => {} //~ ERROR unreachable pattern
10+
_ => {}
11+
}
12+
}
13+
14+
fn main() {
15+
a();
16+
}

src/test/compile-fail/match-vec-unreachable.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ fn main() {
66
_ => ()
77
}
88

9-
match [~"foo", ~"bar", ~"baz"] {
9+
match ~[~"foo", ~"bar", ~"baz"] {
1010
[a, _, _, .._] => { println(a); }
1111
[~"foo", ~"bar", ~"baz", ~"foo", ~"bar"] => { } //~ ERROR unreachable pattern
1212
_ => { }
1313
}
1414

15-
match ['a', 'b', 'c'] {
15+
match ~['a', 'b', 'c'] {
1616
['a', 'b', 'c', .._tail] => {}
1717
['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
1818
_ => {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
fn a() {
2+
let x = [1, 2, 3];
3+
match x {
4+
[1, 2, 4] => ::std::util::unreachable(),
5+
[0, 2, 3, .._] => ::std::util::unreachable(),
6+
[0, .._, 3] => ::std::util::unreachable(),
7+
[0, .._] => ::std::util::unreachable(),
8+
[1, 2, 3] => (),
9+
[_, _, _] => ::std::util::unreachable(),
10+
}
11+
match x {
12+
[.._] => (),
13+
}
14+
match x {
15+
[_, _, _, .._] => (),
16+
}
17+
match x {
18+
[a, b, c] => {
19+
assert_eq!(1, a);
20+
assert_eq!(2, b);
21+
assert_eq!(3, c);
22+
}
23+
}
24+
}
25+
26+
pub fn main() {
27+
a();
28+
}

src/test/run-pass/vec-matching.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn a() {
2-
let x = [1];
2+
let x = ~[1];
33
match x {
44
[_, _, _, _, _, .._] => ::std::util::unreachable(),
55
[.._, _, _, _, _] => ::std::util::unreachable(),
@@ -13,7 +13,7 @@ fn a() {
1313
}
1414

1515
fn b() {
16-
let x = [1, 2, 3];
16+
let x = ~[1, 2, 3];
1717
match x {
1818
[a, b, ..c] => {
1919
assert_eq!(a, 1);

src/test/run-pass/vec-tail-matching.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ struct Foo {
33
}
44

55
pub fn main() {
6-
let x = [
6+
let x = ~[
77
Foo { string: ~"foo" },
88
Foo { string: ~"bar" },
99
Foo { string: ~"baz" }

0 commit comments

Comments
 (0)