Address review comments
This commit is contained in:
parent
76f7eeef52
commit
abce42afa3
10 changed files with 153 additions and 66 deletions
|
@ -51,13 +51,13 @@ impl Usefulness {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
|
fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
|
||||||
ty::with_path(tcx, id, |path| Path {
|
ty::with_path(tcx, id, |mut path| Path {
|
||||||
global: false,
|
global: false,
|
||||||
segments: path.map(|elem| PathSegment {
|
segments: path.last().map(|elem| PathSegment {
|
||||||
identifier: Ident::new(elem.name()),
|
identifier: Ident::new(elem.name()),
|
||||||
lifetimes: vec!(),
|
lifetimes: vec!(),
|
||||||
types: OwnedSlice::empty()
|
types: OwnedSlice::empty()
|
||||||
}).collect(),
|
}).move_iter().collect(),
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -100,10 +100,11 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
|
||||||
arm.pats.as_slice());
|
arm.pats.as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Second, check for unreachable arms.
|
||||||
check_arms(cx, arms.as_slice());
|
check_arms(cx, arms.as_slice());
|
||||||
/* Check for exhaustiveness */
|
|
||||||
// Check for empty enum, because is_useful only works on inhabited
|
// Finally, check if the whole match expression is exhaustive.
|
||||||
// types.
|
// Check for empty enum, because is_useful only works on inhabited types.
|
||||||
let pat_ty = node_id_to_type(cx.tcx, scrut.id);
|
let pat_ty = node_id_to_type(cx.tcx, scrut.id);
|
||||||
if (*arms).is_empty() {
|
if (*arms).is_empty() {
|
||||||
if !type_is_empty(cx.tcx, pat_ty) {
|
if !type_is_empty(cx.tcx, pat_ty) {
|
||||||
|
@ -180,11 +181,11 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
|
||||||
}
|
}
|
||||||
Useful(pats) => {
|
Useful(pats) => {
|
||||||
let witness = match pats.as_slice() {
|
let witness = match pats.as_slice() {
|
||||||
[ref witness] => witness.clone(),
|
[witness] => witness,
|
||||||
[] => wild(),
|
[] => wild(),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
let msg = format!("non-exhaustive patterns: {0} not covered", pat_to_str(&*witness));
|
let msg = format!("non-exhaustive patterns: `{0}` not covered", pat_to_str(&*witness));
|
||||||
cx.tcx.sess.span_err(sp, msg.as_slice());
|
cx.tcx.sess.span_err(sp, msg.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +194,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
|
||||||
#[deriving(Clone, PartialEq)]
|
#[deriving(Clone, PartialEq)]
|
||||||
enum ctor {
|
enum ctor {
|
||||||
single,
|
single,
|
||||||
variant(DefId),
|
variant(DefId /* variant */, bool /* is_structure */),
|
||||||
val(const_val),
|
val(const_val),
|
||||||
range(const_val, const_val),
|
range(const_val, const_val),
|
||||||
vec(uint)
|
vec(uint)
|
||||||
|
@ -215,23 +216,23 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec<Gc<Pat>>, lty:
|
||||||
let pat = match ty::get(lty).sty {
|
let pat = match ty::get(lty).sty {
|
||||||
ty::ty_tup(_) => PatTup(pats),
|
ty::ty_tup(_) => PatTup(pats),
|
||||||
|
|
||||||
ty::ty_enum(_, _) => {
|
ty::ty_enum(cid, _) | ty::ty_struct(cid, _) => {
|
||||||
let vid = match ctor {
|
let (vid, is_structure) = match ctor {
|
||||||
&variant(vid) => vid,
|
&variant(vid, is_structure) => (vid, is_structure),
|
||||||
_ => unreachable!()
|
_ => (cid, true)
|
||||||
};
|
};
|
||||||
PatEnum(def_to_path(cx.tcx, vid), Some(pats))
|
if is_structure {
|
||||||
},
|
let fields = ty::lookup_struct_fields(cx.tcx, vid);
|
||||||
|
|
||||||
ty::ty_struct(cid, _) => {
|
|
||||||
let fields = ty::lookup_struct_fields(cx.tcx, cid);
|
|
||||||
let field_pats = fields.move_iter()
|
let field_pats = fields.move_iter()
|
||||||
.zip(pats.iter())
|
.zip(pats.iter())
|
||||||
.map(|(field, pat)| FieldPat {
|
.map(|(field, pat)| FieldPat {
|
||||||
ident: Ident::new(field.name),
|
ident: Ident::new(field.name),
|
||||||
pat: pat.clone()
|
pat: pat.clone()
|
||||||
}).collect();
|
}).collect();
|
||||||
PatStruct(def_to_path(cx.tcx, cid), field_pats, false)
|
PatStruct(def_to_path(cx.tcx, vid), field_pats, false)
|
||||||
|
} else {
|
||||||
|
PatEnum(def_to_path(cx.tcx, vid), Some(pats))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => {
|
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => {
|
||||||
|
@ -307,7 +308,10 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::ty_enum(eid, _) =>
|
ty::ty_enum(eid, _) =>
|
||||||
ty::enum_variants(cx.tcx, eid).iter().map(|va| variant(va.id)).collect(),
|
ty::enum_variants(cx.tcx, eid)
|
||||||
|
.iter()
|
||||||
|
.map(|va| variant(va.id, va.arg_names.is_some()))
|
||||||
|
.collect(),
|
||||||
|
|
||||||
ty::ty_vec(_, None) =>
|
ty::ty_vec(_, None) =>
|
||||||
vec_constructors(m),
|
vec_constructors(m),
|
||||||
|
@ -389,8 +393,8 @@ fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
|
||||||
},
|
},
|
||||||
|
|
||||||
Some(ctor) => {
|
Some(ctor) => {
|
||||||
let matrix = &m.iter().filter_map(|r| default(cx, r.as_slice())).collect();
|
let matrix = m.iter().filter_map(|r| default(cx, r.as_slice())).collect();
|
||||||
match is_useful(cx, matrix, v.tail(), witness) {
|
match is_useful(cx, &matrix, v.tail(), witness) {
|
||||||
Useful(pats) => Useful(match witness {
|
Useful(pats) => Useful(match witness {
|
||||||
ConstructWitness => {
|
ConstructWitness => {
|
||||||
let arity = constructor_arity(cx, &ctor, left_ty);
|
let arity = constructor_arity(cx, &ctor, left_ty);
|
||||||
|
@ -424,19 +428,28 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
|
||||||
fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc<Pat>) -> Option<ctor> {
|
fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc<Pat>) -> Option<ctor> {
|
||||||
let pat = raw_pat(p);
|
let pat = raw_pat(p);
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatIdent(..) | PatEnum(..) | PatStruct(..) =>
|
PatIdent(..) =>
|
||||||
match cx.tcx.def_map.borrow().find(&pat.id) {
|
match cx.tcx.def_map.borrow().find(&pat.id) {
|
||||||
Some(&DefStatic(did, false)) => {
|
Some(&DefStatic(did, false)) => {
|
||||||
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
|
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
|
||||||
Some(val(eval_const_expr(cx.tcx, &*const_expr)))
|
Some(val(eval_const_expr(cx.tcx, &*const_expr)))
|
||||||
},
|
},
|
||||||
Some(&DefVariant(_, id, _)) =>
|
Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)),
|
||||||
Some(variant(id)),
|
_ => None
|
||||||
_ => match pat.node {
|
},
|
||||||
PatEnum(..) | PatStruct(..) => Some(single),
|
PatEnum(..) =>
|
||||||
PatIdent(..) => None,
|
match cx.tcx.def_map.borrow().find(&pat.id) {
|
||||||
_ => unreachable!()
|
Some(&DefStatic(did, false)) => {
|
||||||
}
|
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
|
||||||
|
Some(val(eval_const_expr(cx.tcx, &*const_expr)))
|
||||||
|
},
|
||||||
|
Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)),
|
||||||
|
_ => Some(single)
|
||||||
|
},
|
||||||
|
PatStruct(..) =>
|
||||||
|
match cx.tcx.def_map.borrow().find(&pat.id) {
|
||||||
|
Some(&DefVariant(_, id, is_structure)) => Some(variant(id, is_structure)),
|
||||||
|
_ => Some(single)
|
||||||
},
|
},
|
||||||
PatLit(expr) =>
|
PatLit(expr) =>
|
||||||
Some(val(eval_const_expr(cx.tcx, &*expr))),
|
Some(val(eval_const_expr(cx.tcx, &*expr))),
|
||||||
|
@ -485,7 +498,7 @@ fn constructor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
|
||||||
},
|
},
|
||||||
ty::ty_enum(eid, _) => {
|
ty::ty_enum(eid, _) => {
|
||||||
match *ctor {
|
match *ctor {
|
||||||
variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
|
variant(id, _) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -532,13 +545,10 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
|
||||||
&PatIdent(_, _, _) => {
|
&PatIdent(_, _, _) => {
|
||||||
let opt_def = cx.tcx.def_map.borrow().find_copy(pat_id);
|
let opt_def = cx.tcx.def_map.borrow().find_copy(pat_id);
|
||||||
match opt_def {
|
match opt_def {
|
||||||
Some(DefVariant(_, id, _)) => {
|
Some(DefVariant(_, id, _)) => match *ctor_id {
|
||||||
if variant(id) == *ctor_id {
|
variant(vid, _) if vid == id => Some(vec!()),
|
||||||
Some(vec!())
|
_ => None
|
||||||
} else {
|
},
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(DefStatic(did, _)) => {
|
Some(DefStatic(did, _)) => {
|
||||||
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
|
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
|
||||||
let e_v = eval_const_expr(cx.tcx, &*const_expr);
|
let e_v = eval_const_expr(cx.tcx, &*const_expr);
|
||||||
|
@ -571,7 +581,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefVariant(_, id, _) if variant(id) != *ctor_id => None,
|
DefVariant(_, id, _) if variant(id, false) != *ctor_id => None,
|
||||||
DefVariant(..) | DefFn(..) | DefStruct(..) => {
|
DefVariant(..) | DefFn(..) | DefStruct(..) => {
|
||||||
Some(match args {
|
Some(match args {
|
||||||
&Some(ref args) => args.clone(),
|
&Some(ref args) => args.clone(),
|
||||||
|
@ -586,7 +596,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
|
||||||
// Is this a struct or an enum variant?
|
// Is this a struct or an enum variant?
|
||||||
let def = cx.tcx.def_map.borrow().get_copy(pat_id);
|
let def = cx.tcx.def_map.borrow().get_copy(pat_id);
|
||||||
let class_id = match def {
|
let class_id = match def {
|
||||||
DefVariant(_, variant_id, _) => if variant(variant_id) == *ctor_id {
|
DefVariant(_, variant_id, _) => if *ctor_id == variant(variant_id, true) {
|
||||||
Some(variant_id)
|
Some(variant_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -687,7 +697,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
|
||||||
match is_refutable(cx, loc.pat) {
|
match is_refutable(cx, loc.pat) {
|
||||||
Some(pat) => {
|
Some(pat) => {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"refutable pattern in {} binding: {} not covered",
|
"refutable pattern in {} binding: `{}` not covered",
|
||||||
name, pat_to_str(&*pat)
|
name, pat_to_str(&*pat)
|
||||||
);
|
);
|
||||||
cx.tcx.sess.span_err(loc.pat.span, msg.as_slice());
|
cx.tcx.sess.span_err(loc.pat.span, msg.as_slice());
|
||||||
|
@ -709,7 +719,7 @@ fn check_fn(cx: &mut MatchCheckCtxt,
|
||||||
match is_refutable(cx, input.pat) {
|
match is_refutable(cx, input.pat) {
|
||||||
Some(pat) => {
|
Some(pat) => {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"refutable pattern in function argument: {} not covered",
|
"refutable pattern in function argument: `{}` not covered",
|
||||||
pat_to_str(&*pat)
|
pat_to_str(&*pat)
|
||||||
);
|
);
|
||||||
cx.tcx.sess.span_err(input.pat.span, msg.as_slice());
|
cx.tcx.sess.span_err(input.pat.span, msg.as_slice());
|
||||||
|
|
|
@ -701,10 +701,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
|
||||||
Some(format!("a fixed vector pattern of size {}", min_len)),
|
Some(format!("a fixed vector pattern of size {}", min_len)),
|
||||||
|
|
||||||
_ => None
|
_ => None
|
||||||
}).and_then(|message| {
|
}).map(check_err);
|
||||||
check_err(message);
|
|
||||||
Some(())
|
|
||||||
});
|
|
||||||
|
|
||||||
for elt in before.iter() {
|
for elt in before.iter() {
|
||||||
check_pat(pcx, &**elt, elt_type);
|
check_pat(pcx, &**elt, elt_type);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
fn foo(a: Option<uint>, b: Option<uint>) {
|
fn foo(a: Option<uint>, b: Option<uint>) {
|
||||||
match (a,b) {
|
match (a,b) {
|
||||||
//~^ ERROR: non-exhaustive patterns: (core::option::None, core::option::None) not covered
|
//~^ ERROR: non-exhaustive patterns: `(None, None)` not covered
|
||||||
(Some(a), Some(b)) if a == b => { }
|
(Some(a), Some(b)) if a == b => { }
|
||||||
(Some(_), None) |
|
(Some(_), None) |
|
||||||
(None, Some(_)) => { }
|
(None, Some(_)) => { }
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let tup = (true, true);
|
let tup = (true, true);
|
||||||
println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: (true, false) not covered
|
println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
|
||||||
(false, false) => "foo",
|
(false, false) => "foo",
|
||||||
(false, true) => "bar",
|
(false, true) => "bar",
|
||||||
(true, true) => "baz"
|
(true, true) => "baz"
|
||||||
|
|
|
@ -13,7 +13,7 @@ enum u { c, d }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = a(c);
|
let x = a(c);
|
||||||
match x { //~ ERROR non-exhaustive patterns: a(c) not covered
|
match x { //~ ERROR non-exhaustive patterns: `a(c)` not covered
|
||||||
a(d) => { fail!("hello"); }
|
a(d) => { fail!("hello"); }
|
||||||
b => { fail!("goodbye"); }
|
b => { fail!("goodbye"); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,21 @@ enum t { a, b, }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = a;
|
let x = a;
|
||||||
match x { b => { } } //~ ERROR non-exhaustive patterns: a not covered
|
match x { b => { } } //~ ERROR non-exhaustive patterns: `a` not covered
|
||||||
match true { //~ ERROR non-exhaustive patterns: false not covered
|
match true { //~ ERROR non-exhaustive patterns: `false` not covered
|
||||||
true => {}
|
true => {}
|
||||||
}
|
}
|
||||||
match Some(10) { //~ ERROR non-exhaustive patterns: core::option::Some(_) not covered
|
match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
match (2, 3, 4) { //~ ERROR non-exhaustive patterns: (_, _, _) not covered
|
match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, _)` not covered
|
||||||
(_, _, 4) => {}
|
(_, _, 4) => {}
|
||||||
}
|
}
|
||||||
match (a, a) { //~ ERROR non-exhaustive patterns: (a, a) not covered
|
match (a, a) { //~ ERROR non-exhaustive patterns: `(a, a)` not covered
|
||||||
(a, b) => {}
|
(a, b) => {}
|
||||||
(b, a) => {}
|
(b, a) => {}
|
||||||
}
|
}
|
||||||
match a { //~ ERROR non-exhaustive patterns: b not covered
|
match a { //~ ERROR non-exhaustive patterns: `b` not covered
|
||||||
a => {}
|
a => {}
|
||||||
}
|
}
|
||||||
// This is exhaustive, though the algorithm got it wrong at one point
|
// This is exhaustive, though the algorithm got it wrong at one point
|
||||||
|
@ -37,7 +37,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
let vec = vec!(Some(42), None, Some(21));
|
let vec = vec!(Some(42), None, Some(21));
|
||||||
let vec: &[Option<int>] = vec.as_slice();
|
let vec: &[Option<int>] = vec.as_slice();
|
||||||
match vec { //~ ERROR non-exhaustive patterns: [] not covered
|
match vec { //~ ERROR non-exhaustive patterns: `[]` not covered
|
||||||
[Some(..), None, ..tail] => {}
|
[Some(..), None, ..tail] => {}
|
||||||
[Some(..), Some(..), ..tail] => {}
|
[Some(..), Some(..), ..tail] => {}
|
||||||
[None] => {}
|
[None] => {}
|
||||||
|
@ -50,7 +50,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
let vec = vec!(0.5);
|
let vec = vec!(0.5);
|
||||||
let vec: &[f32] = vec.as_slice();
|
let vec: &[f32] = vec.as_slice();
|
||||||
match vec { //~ ERROR non-exhaustive patterns: [_, _, _, _] not covered
|
match vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
|
||||||
[0.1, 0.2, 0.3] => (),
|
[0.1, 0.2, 0.3] => (),
|
||||||
[0.1, 0.2] => (),
|
[0.1, 0.2] => (),
|
||||||
[0.1] => (),
|
[0.1] => (),
|
||||||
|
|
74
src/test/compile-fail/non-exhaustive-pattern-witness.rs
Normal file
74
src/test/compile-fail/non-exhaustive-pattern-witness.rs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#![feature(struct_variant)]
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
first: bool,
|
||||||
|
second: Option<[uint, ..4]>
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Color {
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn struct_with_a_nested_enum_and_vector() {
|
||||||
|
match Foo { first: true, second: None } {
|
||||||
|
//~^ ERROR non-exhaustive patterns: `Foo{first: false, second: Some([_, _, _, _])}` not covered
|
||||||
|
Foo { first: true, second: None } => (),
|
||||||
|
Foo { first: true, second: Some(_) } => (),
|
||||||
|
Foo { first: false, second: None } => (),
|
||||||
|
Foo { first: false, second: Some([1u, 2u, 3u, 4u]) } => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enum_with_multiple_missing_variants() {
|
||||||
|
match Red {
|
||||||
|
//~^ ERROR non-exhaustive patterns: `Red` not covered
|
||||||
|
CustomRGBA { .. } => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enum_struct_variant() {
|
||||||
|
match Red {
|
||||||
|
//~^ ERROR non-exhaustive patterns: `CustomRGBA{a: true, r: _, g: _, b: _}` not covered
|
||||||
|
Red => (),
|
||||||
|
Green => (),
|
||||||
|
CustomRGBA { a: false, r: _, g: _, b: 0 } => (),
|
||||||
|
CustomRGBA { a: false, r: _, g: _, b: _ } => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Enum {
|
||||||
|
First,
|
||||||
|
Second(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vectors_with_nested_enums() {
|
||||||
|
let x: &'static [Enum] = [First, Second(false)];
|
||||||
|
match x {
|
||||||
|
//~^ ERROR non-exhaustive patterns: `[Second(true), Second(false)]` not covered
|
||||||
|
[] => (),
|
||||||
|
[_] => (),
|
||||||
|
[First, _] => (),
|
||||||
|
[Second(true), First] => (),
|
||||||
|
[Second(true), Second(true)] => (),
|
||||||
|
[Second(false), _] => (),
|
||||||
|
[_, _, ..tail, _] => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
struct_with_a_nested_enum_and_vector();
|
||||||
|
enum_with_multiple_missing_variants();
|
||||||
|
enum_struct_variant();
|
||||||
|
}
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
|
|
||||||
fn func((1, (Some(1), 2..3)): (int, (Option<int>, int))) { }
|
fn func((1, (Some(1), 2..3)): (int, (Option<int>, int))) { }
|
||||||
//~^ ERROR refutable pattern in function argument: (_, _) not covered
|
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (1, (Some(1), 2..3)) = (1, (None, 2));
|
let (1, (Some(1), 2..3)) = (1, (None, 2));
|
||||||
//~^ ERROR refutable pattern in local binding: (_, _) not covered
|
//~^ ERROR refutable pattern in local binding: `(_, _)` not covered
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let f = |3: int| println!("hello");
|
let f = |3: int| println!("hello");
|
||||||
//~^ ERROR refutable pattern in function argument: _ not covered
|
//~^ ERROR refutable pattern in function argument: `_` not covered
|
||||||
f(4);
|
f(4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,4 +27,10 @@ fn main() {
|
||||||
let [a, _, _, d] = bar("baz", "foo");
|
let [a, _, _, d] = bar("baz", "foo");
|
||||||
assert_eq!(a, "baz");
|
assert_eq!(a, "baz");
|
||||||
assert_eq!(d, "baz");
|
assert_eq!(d, "baz");
|
||||||
|
|
||||||
|
let out = bar("baz", "foo");
|
||||||
|
let [a, ..xs, d] = out;
|
||||||
|
assert_eq!(a, "baz");
|
||||||
|
assert!(xs == ["foo", "foo"]);
|
||||||
|
assert_eq!(d, "baz");
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue