Print a friendly error for the if-let construct without an else block

Fixes #19991.
This commit is contained in:
Barosl Lee 2014-12-20 01:42:21 +09:00
parent cbe9fb45bc
commit 7023bea22c
5 changed files with 44 additions and 9 deletions

View File

@ -238,7 +238,8 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
expr: &ast::Expr,
discrim: &ast::Expr,
arms: &[ast::Arm],
expected: Expectation<'tcx>) {
expected: Expectation<'tcx>,
match_src: ast::MatchSource) {
let tcx = fcx.ccx.tcx;
let discrim_ty = fcx.infcx().next_ty_var();
@ -290,12 +291,26 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
if ty::type_is_error(result_ty) || ty::type_is_error(bty) {
ty::mk_err()
} else {
let (origin, expected, found) = match match_src {
/* if-let construct without an else block */
ast::MatchIfLetDesugar(contains_else_arm) if !contains_else_arm => (
infer::IfExpressionWithNoElse(expr.span),
bty,
result_ty,
),
_ => (
infer::MatchExpressionArm(expr.span, arm.body.span),
result_ty,
bty,
),
};
infer::common_supertype(
fcx.infcx(),
infer::MatchExpressionArm(expr.span, arm.body.span),
true, // result_ty is "expected" here
result_ty,
bty
origin,
true,
expected,
found,
)
}
});

View File

@ -3918,8 +3918,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
fcx.write_nil(id);
}
}
ast::ExprMatch(ref discrim, ref arms, _) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected);
ast::ExprMatch(ref discrim, ref arms, match_src) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
}
ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);

View File

@ -754,7 +754,7 @@ pub struct QPath {
#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub enum MatchSource {
MatchNormal,
MatchIfLetDesugar,
MatchIfLetDesugar(bool /* contains_else_arm */),
MatchWhileLetDesugar,
}

View File

@ -170,7 +170,9 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
arms.extend(else_if_arms.into_iter());
arms.push(else_arm);
let match_expr = fld.cx.expr(span, ast::ExprMatch(expr, arms, ast::MatchIfLetDesugar));
let match_expr = fld.cx.expr(span, ast::ExprMatch(expr,
arms,
ast::MatchIfLetDesugar(elseopt.is_some())));
fld.fold_expr(match_expr)
}

View File

@ -0,0 +1,18 @@
// 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.
// Test if the sugared if-let construct correctly prints "missing an else clause" when an else
// clause does not exist, instead of the unsympathetic "match arms have incompatible types"
fn main() {
if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause: expected `()`
765i32
};
}