From d4da4ba4b2f3412c7f9630c4d88ea3e121cd6f2a Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Sat, 21 Jun 2014 14:52:23 +0200 Subject: [PATCH] Fix a #14731 regression in missing_constructor() for vector patterns Fixes #15080. --- src/librustc/middle/check_match.rs | 26 ++++++++++++++++---------- src/test/run-pass/issue-15080.rs | 30 ++++++++++++++++++++++++++++++ src/test/run-pass/vec-matching.rs | 8 ++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/issue-15080.rs diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 6d8b178ba0014..2c3ba98daaef2 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -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 { + // 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 { 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 index 0000000000000..b12f0c6462edf --- /dev/null +++ b/src/test/run-pass/issue-15080.rs @@ -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 or the MIT license +// , 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]); +} diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index 175f774bdfde0..11143ba0c8423 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -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(); }