diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index cc319b70e396..9b751447504e 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -863,13 +863,17 @@ fn default(cx: &MatchCheckCtxt, r: &[@Pat]) -> Option > { fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) { visit::walk_local(cx, loc, ()); - if is_refutable(cx, loc.pat) { - let name = match loc.source { - LocalLet => "local", - LocalFor => "`for` loop" - }; - cx.tcx.sess.span_err(loc.pat.span, + let name = match loc.source { + LocalLet => "local", + LocalFor => "`for` loop" + }; + + let mut spans = vec![]; + find_refutable(cx, loc.pat, &mut spans); + + for span in spans.iter() { + cx.tcx.sess.span_err(*span, format!("refutable pattern in {} binding", name).as_slice()); } @@ -884,53 +888,65 @@ fn check_fn(cx: &mut MatchCheckCtxt, sp: Span) { visit::walk_fn(cx, kind, decl, body, sp, ()); for input in decl.inputs.iter() { - if is_refutable(cx, input.pat) { - cx.tcx.sess.span_err(input.pat.span, + let mut spans = vec![]; + find_refutable(cx, input.pat, &mut spans); + + for span in spans.iter() { + cx.tcx.sess.span_err(*span, "refutable pattern in function argument"); } } } -fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool { +fn find_refutable(cx: &MatchCheckCtxt, pat: &Pat, spans: &mut Vec) { + macro_rules! this_pattern { + () => { + { + spans.push(pat.span); + return + } + } + } let opt_def = cx.tcx.def_map.borrow().find_copy(&pat.id); match opt_def { Some(DefVariant(enum_id, _, _)) => { if ty::enum_variants(cx.tcx, enum_id).len() != 1u { - return true; + this_pattern!() } } - Some(DefStatic(..)) => return true, + Some(DefStatic(..)) => this_pattern!(), _ => () } match pat.node { PatUniq(sub) | PatRegion(sub) | PatIdent(_, _, Some(sub)) => { - is_refutable(cx, sub) + find_refutable(cx, sub, spans) } - PatWild | PatWildMulti | PatIdent(_, _, None) => { false } + PatWild | PatWildMulti | PatIdent(_, _, None) => {} PatLit(lit) => { match lit.node { ExprLit(lit) => { match lit.node { - LitNil => false, // `()` - _ => true, + LitNil => {} // `()` + _ => this_pattern!(), } } - _ => true, + _ => this_pattern!(), } } - PatRange(_, _) => { true } + PatRange(_, _) => { this_pattern!() } PatStruct(_, ref fields, _) => { - fields.iter().any(|f| is_refutable(cx, f.pat)) + for f in fields.iter() { + find_refutable(cx, f.pat, spans); + } } - PatTup(ref elts) => { - elts.iter().any(|elt| is_refutable(cx, *elt)) + PatTup(ref elts) | PatEnum(_, Some(ref elts))=> { + for elt in elts.iter() { + find_refutable(cx, *elt, spans) + } } - PatEnum(_, Some(ref args)) => { - args.iter().any(|a| is_refutable(cx, *a)) - } - PatEnum(_,_) => { false } - PatVec(..) => { true } + PatEnum(_,_) => {} + PatVec(..) => { this_pattern!() } } } diff --git a/src/test/compile-fail/precise-refutable-pattern-errors.rs b/src/test/compile-fail/precise-refutable-pattern-errors.rs new file mode 100644 index 000000000000..efa2dbad83fd --- /dev/null +++ b/src/test/compile-fail/precise-refutable-pattern-errors.rs @@ -0,0 +1,32 @@ +// 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 func( + ( + 1, //~ ERROR refutable pattern in function argument + ( + Some( //~ ERROR refutable pattern in function argument + 1), // nested, so no warning. + 2..3 //~ ERROR refutable pattern in function argument + ) + ): (int, (Option, int)) + ) {} + +fn main() { + let ( + 1, //~ ERROR refutable pattern in local binding + ( + Some( //~ ERROR refutable pattern in local binding + 1), // nested, so no warning. + 2..3 //~ ERROR refutable pattern in local binding + ) + ) = (1, (None, 2)); +}