]> git.lizzy.rs Git - rust.git/commitdiff
Fix a #14731 regression in missing_constructor() for vector patterns
authorJakub Wieczorek <jakub@jakub.cc>
Sat, 21 Jun 2014 12:52:23 +0000 (14:52 +0200)
committerJakub Wieczorek <jakub@jakub.cc>
Sat, 21 Jun 2014 18:36:17 +0000 (20:36 +0200)
Fixes #15080.

src/librustc/middle/check_match.rs
src/test/run-pass/issue-15080.rs [new file with mode: 0644]
src/test/run-pass/vec-matching.rs

index 6d8b178ba0014092bd77de97831a92279b43a2c1..2c3ba98daaef2db8c5daf96181f2c9da40f61a25 100644 (file)
@@ -281,21 +281,27 @@ fn missing_constructor(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Optio
 }
 
 fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor> {
+    // This produces a list of all vector constructors that we would expect to appear
+    // in an exhaustive set of patterns. Because such a list would normally be infinite,
+    // we narrow it down to only those constructors that actually appear in the inspected
+    // column, plus, any that are missing and not covered by a pattern with a destructured slice.
     fn vec_constructors(m: &Matrix) -> Vec<ctor> {
         let max_vec_len = m.iter().map(|r| match r.get(0).node {
             PatVec(ref before, _, ref after) => before.len() + after.len(),
             _ => 0u
         }).max().unwrap_or(0u);
-        let contains_slice = m.iter().any(|r| match r.get(0).node {
-            PatVec(_, ref slice, _) => slice.is_some(),
-            _ => false
-        });
-        let lengths = iter::range_inclusive(0u, if contains_slice {
-            max_vec_len
-        } else {
-            max_vec_len + 1
-        });
-        lengths.map(|len| vec(len)).collect()
+        let min_vec_len_with_slice = m.iter().map(|r| match r.get(0).node {
+            PatVec(ref before, Some(_), ref after) => before.len() + after.len(),
+            _ => max_vec_len + 1
+        }).min().unwrap_or(max_vec_len + 1);
+        let other_lengths = m.iter().map(|r| match r.get(0).node {
+            PatVec(ref before, _, ref after) => before.len() + after.len(),
+            _ => 0u
+        }).filter(|&len| len > min_vec_len_with_slice);
+        iter::range_inclusive(0u, min_vec_len_with_slice)
+            .chain(other_lengths)
+            .map(|len| vec(len))
+            .collect()
     }
 
     match ty::get(left_ty).sty {
diff --git a/src/test/run-pass/issue-15080.rs b/src/test/run-pass/issue-15080.rs
new file mode 100644 (file)
index 0000000..b12f0c6
--- /dev/null
@@ -0,0 +1,30 @@
+// 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 main() {
+    let mut x = &[1, 2, 3, 4];
+
+    let mut result = vec!();
+    loop {
+        x = match x {
+            [1, n, 3, ..rest] => {
+                result.push(n);
+                rest
+            }
+            [n, ..rest] => {
+                result.push(n);
+                rest
+            }
+            [] =>
+                break
+        }
+    }
+    assert!(result.as_slice() == [2, 4]);
+}
index 175f774bdfde01720577c9a17c2881ffe56a04ff..11143ba0c842341e34e5883e45e0c798db616e92 100644 (file)
@@ -68,9 +68,17 @@ fn d() {
     assert_eq!(branch, 1);
 }
 
+fn e() {
+    match &[1, 2, 3] {
+        [1, 2] => (),
+        [..] => ()
+    }
+}
+
 pub fn main() {
     a();
     b();
     c();
     d();
+    e();
 }