From 7023bea22c969a324d7d95d8794370410ff7c4c9 Mon Sep 17 00:00:00 2001 From: Barosl Lee Date: Sat, 20 Dec 2014 01:42:21 +0900 Subject: [PATCH] Print a friendly error for the if-let construct without an else block Fixes #19991. --- src/librustc_typeck/check/_match.rs | 25 ++++++++++++++++++++----- src/librustc_typeck/check/mod.rs | 4 ++-- src/libsyntax/ast.rs | 2 +- src/libsyntax/ext/expand.rs | 4 +++- src/test/compile-fail/issue-19991.rs | 18 ++++++++++++++++++ 5 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 src/test/compile-fail/issue-19991.rs diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 44cc5fce53d..d4b89621ace 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -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, ) } }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bbc33826f35..f8a8ef35f75 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3918,8 +3918,8 @@ fn check_struct_fields_on_error(fcx: &FnCtxt, 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); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index be8f32bc4d5..ab338da63bf 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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, } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 20c8ff20b71..63bd38de8a0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -170,7 +170,9 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { 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) } diff --git a/src/test/compile-fail/issue-19991.rs b/src/test/compile-fail/issue-19991.rs new file mode 100644 index 00000000000..0f1dbfa3492 --- /dev/null +++ b/src/test/compile-fail/issue-19991.rs @@ -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 or the MIT license +// , 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 + }; +} -- 2.44.0