Skip to content

Commit d4da4ba

Browse files
author
Jakub Wieczorek
committed
Fix a #14731 regression in missing_constructor() for vector patterns
Fixes #15080.
1 parent f556c8c commit d4da4ba

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

Diff for: src/librustc/middle/check_match.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -281,21 +281,27 @@ fn missing_constructor(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Optio
281281
}
282282

283283
fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor> {
284+
// This produces a list of all vector constructors that we would expect to appear
285+
// in an exhaustive set of patterns. Because such a list would normally be infinite,
286+
// we narrow it down to only those constructors that actually appear in the inspected
287+
// column, plus, any that are missing and not covered by a pattern with a destructured slice.
284288
fn vec_constructors(m: &Matrix) -> Vec<ctor> {
285289
let max_vec_len = m.iter().map(|r| match r.get(0).node {
286290
PatVec(ref before, _, ref after) => before.len() + after.len(),
287291
_ => 0u
288292
}).max().unwrap_or(0u);
289-
let contains_slice = m.iter().any(|r| match r.get(0).node {
290-
PatVec(_, ref slice, _) => slice.is_some(),
291-
_ => false
292-
});
293-
let lengths = iter::range_inclusive(0u, if contains_slice {
294-
max_vec_len
295-
} else {
296-
max_vec_len + 1
297-
});
298-
lengths.map(|len| vec(len)).collect()
293+
let min_vec_len_with_slice = m.iter().map(|r| match r.get(0).node {
294+
PatVec(ref before, Some(_), ref after) => before.len() + after.len(),
295+
_ => max_vec_len + 1
296+
}).min().unwrap_or(max_vec_len + 1);
297+
let other_lengths = m.iter().map(|r| match r.get(0).node {
298+
PatVec(ref before, _, ref after) => before.len() + after.len(),
299+
_ => 0u
300+
}).filter(|&len| len > min_vec_len_with_slice);
301+
iter::range_inclusive(0u, min_vec_len_with_slice)
302+
.chain(other_lengths)
303+
.map(|len| vec(len))
304+
.collect()
299305
}
300306

301307
match ty::get(left_ty).sty {

Diff for: src/test/run-pass/issue-15080.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
let mut x = &[1, 2, 3, 4];
13+
14+
let mut result = vec!();
15+
loop {
16+
x = match x {
17+
[1, n, 3, ..rest] => {
18+
result.push(n);
19+
rest
20+
}
21+
[n, ..rest] => {
22+
result.push(n);
23+
rest
24+
}
25+
[] =>
26+
break
27+
}
28+
}
29+
assert!(result.as_slice() == [2, 4]);
30+
}

Diff for: src/test/run-pass/vec-matching.rs

+8
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,17 @@ fn d() {
6868
assert_eq!(branch, 1);
6969
}
7070

71+
fn e() {
72+
match &[1, 2, 3] {
73+
[1, 2] => (),
74+
[..] => ()
75+
}
76+
}
77+
7178
pub fn main() {
7279
a();
7380
b();
7481
c();
7582
d();
83+
e();
7684
}

0 commit comments

Comments
 (0)