Skip to content

Commit f5e513b

Browse files
author
Jakub Wieczorek
committed
Check pattern refutability the same way exhaustiveness is checked
1 parent 6750eb5 commit f5e513b

File tree

3 files changed

+44
-95
lines changed

3 files changed

+44
-95
lines changed

src/librustc/middle/check_match.rs

+26-63
Original file line numberDiff line numberDiff line change
@@ -750,12 +750,15 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
750750
LocalFor => "`for` loop"
751751
};
752752

753-
let mut spans = vec![];
754-
find_refutable(cx, &*loc.pat, &mut spans);
755-
756-
for span in spans.iter() {
757-
cx.tcx.sess.span_err(*span,
758-
format!("refutable pattern in {} binding", name).as_slice());
753+
match is_refutable(cx, loc.pat) {
754+
Some(pat) => {
755+
let msg = format!(
756+
"refutable pattern in {} binding: {} not covered",
757+
name, pat_to_str(&*pat)
758+
);
759+
cx.tcx.sess.span_err(loc.pat.span, msg.as_slice());
760+
},
761+
None => ()
759762
}
760763

761764
// Check legality of move bindings.
@@ -769,67 +772,27 @@ fn check_fn(cx: &mut MatchCheckCtxt,
769772
sp: Span) {
770773
visit::walk_fn(cx, kind, decl, body, sp, ());
771774
for input in decl.inputs.iter() {
772-
let mut spans = vec![];
773-
find_refutable(cx, &*input.pat, &mut spans);
774-
775-
for span in spans.iter() {
776-
cx.tcx.sess.span_err(*span,
777-
"refutable pattern in function argument");
775+
match is_refutable(cx, input.pat) {
776+
Some(pat) => {
777+
let msg = format!(
778+
"refutable pattern in function argument: {} not covered",
779+
pat_to_str(&*pat)
780+
);
781+
cx.tcx.sess.span_err(input.pat.span, msg.as_slice());
782+
},
783+
None => ()
778784
}
779785
}
780786
}
781787

782-
fn find_refutable(cx: &MatchCheckCtxt, pat: &Pat, spans: &mut Vec<Span>) {
783-
macro_rules! this_pattern {
784-
() => {
785-
{
786-
spans.push(pat.span);
787-
return
788-
}
789-
}
790-
}
791-
let opt_def = cx.tcx.def_map.borrow().find_copy(&pat.id);
792-
match opt_def {
793-
Some(DefVariant(enum_id, _, _)) => {
794-
if ty::enum_variants(cx.tcx, enum_id).len() != 1u {
795-
this_pattern!()
796-
}
797-
}
798-
Some(DefStatic(..)) => this_pattern!(),
799-
_ => ()
800-
}
801-
802-
match pat.node {
803-
PatBox(ref sub) | PatRegion(ref sub) | PatIdent(_, _, Some(ref sub)) => {
804-
find_refutable(cx, &**sub, spans)
805-
}
806-
PatWild | PatWildMulti | PatIdent(_, _, None) => {}
807-
PatLit(lit) => {
808-
match lit.node {
809-
ExprLit(lit) => {
810-
match lit.node {
811-
LitNil => {} // `()`
812-
_ => this_pattern!(),
813-
}
814-
}
815-
_ => this_pattern!(),
816-
}
817-
}
818-
PatRange(_, _) => { this_pattern!() }
819-
PatStruct(_, ref fields, _) => {
820-
for f in fields.iter() {
821-
find_refutable(cx, &*f.pat, spans);
822-
}
823-
}
824-
PatTup(ref elts) | PatEnum(_, Some(ref elts))=> {
825-
for elt in elts.iter() {
826-
find_refutable(cx, &**elt, spans)
827-
}
828-
}
829-
PatEnum(_,_) => {}
830-
PatVec(..) => { this_pattern!() }
831-
PatMac(_) => cx.tcx.sess.bug("unexpanded macro"),
832-
}
788+
fn is_refutable(cx: &MatchCheckCtxt, pat: Gc<Pat>) -> Option<Gc<Pat>> {
789+
let pats = vec!(vec!(pat));
790+
is_useful(cx, &pats, [wild()])
791+
.useful()
792+
.map(|pats| {
793+
assert_eq!(pats.len(), 1);
794+
pats.get(0).clone()
795+
})
833796
}
834797

835798
// Legality of move bindings checking

src/test/compile-fail/precise-refutable-pattern-errors.rs

-32
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
12+
fn func((1, (Some(1), 2..3)): (int, (Option<int>, int))) { }
13+
//~^ ERROR refutable pattern in function argument
14+
15+
fn main() {
16+
let (1, (Some(1), 2..3)) = (1, (None, 2));
17+
//~^ ERROR refutable pattern in local binding
18+
}

0 commit comments

Comments
 (0)