1
Fork 0

custom message for refutable patterns in for loops

This commit is contained in:
Jorge Aparicio 2015-01-22 17:46:40 -05:00
parent 5e1820f346
commit 76362f0a0e
6 changed files with 38 additions and 9 deletions

View file

@ -1163,6 +1163,7 @@ impl LintPass for UnusedParens {
ast::MatchSource::Normal => (head, "`match` head expression", true),
ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true),
},
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
ast::ExprAssign(_, ref value) => (value, "assigned value", false),

View file

@ -221,7 +221,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
.flat_map(|arm| arm.0.iter())
.map(|pat| vec![&**pat])
.collect();
check_exhaustive(cx, ex.span, &matrix);
check_exhaustive(cx, ex.span, &matrix, source);
},
ast::ExprForLoop(ref pat, _, _, _) => {
let mut static_inliner = StaticInliner::new(cx.tcx);
@ -327,6 +327,14 @@ fn check_arms(cx: &MatchCheckCtxt,
span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
},
ast::MatchSource::ForLoopDesugar => {
// this is a bug, because on `match iter.next()` we cover
// `Some(<head>)` and `None`. It's impossible to have an unreachable
// pattern
// (see libsyntax/ext/expand.rs for the full expansion of a for loop)
cx.tcx.sess.span_bug(pat.span, "unreachable for-loop pattern")
},
ast::MatchSource::Normal => {
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
},
@ -351,7 +359,7 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
}
}
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast::MatchSource) {
match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
UsefulWithWitness(pats) => {
let witness = match &pats[] {
@ -359,10 +367,29 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
[] => DUMMY_WILD_PAT,
_ => unreachable!()
};
span_err!(cx.tcx.sess, sp, E0004,
"non-exhaustive patterns: `{}` not covered",
pat_to_string(witness)
);
match source {
ast::MatchSource::ForLoopDesugar => {
// `witness` has the form `Some(<head>)`, peel off the `Some`
let witness = match witness.node {
ast::PatEnum(_, Some(ref pats)) => match &pats[] {
[ref pat] => &**pat,
_ => unreachable!(),
},
_ => unreachable!(),
};
span_err!(cx.tcx.sess, sp, E0297,
"refutable pattern in `for` loop binding: \
`{}` not covered",
pat_to_string(witness));
},
_ => {
span_err!(cx.tcx.sess, sp, E0004,
"non-exhaustive patterns: `{}` not covered",
pat_to_string(witness)
);
},
}
}
NotUseful => {
// This is good, wildcard pattern isn't reachable

View file

@ -100,6 +100,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
ast::ExprMethodCall(..) => "method call",
ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => "while let",
ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) => "for",
ast::ExprMatch(..) => "match",
_ => "expression",
},

View file

@ -788,6 +788,7 @@ pub enum MatchSource {
Normal,
IfLetDesugar { contains_else_clause: bool },
WhileLetDesugar,
ForLoopDesugar,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]

View file

@ -288,8 +288,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
fld.cx.expr_call(span, fld.cx.expr_path(next_path), vec![ref_mut_iter]);
let arms = vec![pat_arm, break_arm];
// FIXME(japaric) This should use `ForLoopDesugar` as MatchSource
fld.cx.expr_match(pat_span, next_expr, arms)
fld.cx.expr(pat_span,
ast::ExprMatch(next_expr, arms, ast::MatchSource::ForLoopDesugar))
};
// `[opt_ident]: loop { ... }`

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
for
&1is //~ ERROR refutable pattern in `for` loop binding