Improve error message, fix and add tests.
Changes the non-exhaustive match error message to generate more general witnesses.
This commit is contained in:
parent
9c5e86d0cd
commit
9ba9cd5fd5
5 changed files with 131 additions and 31 deletions
|
|
@ -359,25 +359,6 @@ impl<'tcx> Witness<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the set of constructors from the same type as the first column of `matrix`,
|
||||
/// that are matched only by wildcard patterns from that first column.
|
||||
///
|
||||
/// Therefore, if there is some pattern that is unmatched by `matrix`, it will
|
||||
/// still be unmatched if the first constructor is replaced by any of the constructors
|
||||
/// in the return value.
|
||||
fn missing_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
matrix: &Matrix,
|
||||
pcx: PatternContext<'tcx>) -> Vec<Constructor> {
|
||||
let used_constructors: Vec<Constructor> =
|
||||
matrix.0.iter()
|
||||
.flat_map(|row| pat_constructors(cx, row[0], pcx).unwrap_or(vec![]))
|
||||
.collect();
|
||||
debug!("used_constructors = {:?}", used_constructors);
|
||||
all_constructors(cx, pcx).into_iter()
|
||||
.filter(|c| !used_constructors.contains(c))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// This determines the set of all possible constructors of a pattern matching
|
||||
/// values of type `left_ty`. For vectors, this would normally be an infinite set
|
||||
///
|
||||
|
|
@ -586,10 +567,28 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
|||
).find(|result| result.is_useful()).unwrap_or(NotUseful)
|
||||
} else {
|
||||
debug!("is_useful - expanding wildcard");
|
||||
let constructors = missing_constructors(cx, matrix, pcx);
|
||||
debug!("is_useful - missing_constructors = {:?}", constructors);
|
||||
if constructors.is_empty() {
|
||||
all_constructors(cx, pcx).into_iter().map(|c| {
|
||||
|
||||
let used_ctors: Vec<Constructor> = rows.iter().flat_map(|row| {
|
||||
pat_constructors(cx, row[0], pcx).unwrap_or(vec![])
|
||||
}).collect();
|
||||
debug!("used_ctors = {:?}", used_ctors);
|
||||
let all_ctors = all_constructors(cx, pcx);
|
||||
debug!("all_ctors = {:?}", all_ctors);
|
||||
let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
|
||||
!used_ctors.contains(*c)
|
||||
}).cloned().collect();
|
||||
debug!("missing_ctors = {:?}", missing_ctors);
|
||||
|
||||
// `missing_ctors` is the set of constructors from the same type as the
|
||||
// first column of `matrix` that are matched only by wildcard patterns
|
||||
// from the first column.
|
||||
//
|
||||
// Therefore, if there is some pattern that is unmatched by `matrix`,
|
||||
// it will still be unmatched if the first constructor is replaced by
|
||||
// any of the constructors in `missing_ctors`
|
||||
|
||||
if missing_ctors.is_empty() {
|
||||
all_ctors.into_iter().map(|c| {
|
||||
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
|
||||
}).find(|result| result.is_useful()).unwrap_or(NotUseful)
|
||||
} else {
|
||||
|
|
@ -603,11 +602,25 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
|||
match is_useful(cx, &matrix, &v[1..], witness) {
|
||||
UsefulWithWitness(pats) => {
|
||||
let cx = &*cx;
|
||||
UsefulWithWitness(pats.into_iter().flat_map(|witness| {
|
||||
constructors.iter().map(move |ctor| {
|
||||
witness.clone().push_wild_constructor(cx, ctor, pcx.ty)
|
||||
})
|
||||
}).collect())
|
||||
let new_witnesses = if used_ctors.is_empty() {
|
||||
// All constructors are unused. Add wild patterns
|
||||
// rather than each individual constructor
|
||||
pats.into_iter().map(|mut witness| {
|
||||
witness.0.push(P(hir::Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
node: PatKind::Wild,
|
||||
span: DUMMY_SP,
|
||||
}));
|
||||
witness
|
||||
}).collect()
|
||||
} else {
|
||||
pats.into_iter().flat_map(|witness| {
|
||||
missing_ctors.iter().map(move |ctor| {
|
||||
witness.clone().push_wild_constructor(cx, ctor, pcx.ty)
|
||||
})
|
||||
}).collect()
|
||||
};
|
||||
UsefulWithWitness(new_witnesses)
|
||||
}
|
||||
result => result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
fn check(list: &[Option<()>]) {
|
||||
match list {
|
||||
//~^ ERROR `&[None, Some(_), None, _]` and `&[Some(_), Some(_), None, _]` not covered
|
||||
//~^ ERROR `&[_, Some(_), None, _]` not covered
|
||||
&[] => {},
|
||||
&[_] => {},
|
||||
&[_, _] => {},
|
||||
|
|
|
|||
38
src/test/compile-fail/uninhabited-irrefutable.rs
Normal file
38
src/test/compile-fail/uninhabited-irrefutable.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2012 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.
|
||||
|
||||
#![feature(never_type)]
|
||||
|
||||
mod foo {
|
||||
pub struct SecretlyEmpty {
|
||||
_priv: !,
|
||||
}
|
||||
|
||||
pub struct NotSoSecretlyEmpty {
|
||||
pub _pub: !,
|
||||
}
|
||||
}
|
||||
|
||||
struct NotSoSecretlyEmpty {
|
||||
_priv: !,
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
A(foo::SecretlyEmpty),
|
||||
B(foo::NotSoSecretlyEmpty),
|
||||
C(NotSoSecretlyEmpty),
|
||||
D(u32),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: Foo = Foo::D(123);
|
||||
let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
|
||||
}
|
||||
|
||||
49
src/test/compile-fail/uninhabited-patterns.rs
Normal file
49
src/test/compile-fail/uninhabited-patterns.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2012 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.
|
||||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(never_type)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
mod foo {
|
||||
pub struct SecretlyEmpty {
|
||||
_priv: !,
|
||||
}
|
||||
}
|
||||
|
||||
struct NotSoSecretlyEmpty {
|
||||
_priv: !,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: &[!] = &[];
|
||||
|
||||
match x {
|
||||
&[] => (),
|
||||
&[..] => (), //~ ERROR unreachable pattern
|
||||
};
|
||||
|
||||
let x: Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]> = Err(&[]);
|
||||
match x {
|
||||
Ok(box _) => (), //~ ERROR unreachable pattern
|
||||
Err(&[]) => (),
|
||||
Err(&[..]) => (), //~ ERROR unreachable pattern
|
||||
}
|
||||
|
||||
let x: Result<foo::SecretlyEmpty, Result<NotSoSecretlyEmpty, u32>> = Err(Err(123));
|
||||
match x {
|
||||
Ok(_y) => (),
|
||||
Err(Err(_y)) => (),
|
||||
Err(Ok(_y)) => (), //~ ERROR unreachable pattern
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4,11 +4,11 @@ error[E0004]: non-exhaustive patterns: `(B, _)`, `(C, _)`, `(D, _)` and 2 more n
|
|||
20 | match (A, ()) {
|
||||
| ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `(A, B)`, `(B, B)`, `(C, B)` and 27 more not covered
|
||||
error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
|
||||
--> $DIR/issue-35609.rs:24:11
|
||||
|
|
||||
24 | match (A, A) {
|
||||
| ^^^^^^ patterns `(A, B)`, `(B, B)`, `(C, B)` and 27 more not covered
|
||||
| ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
|
||||
--> $DIR/issue-35609.rs:28:11
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue