]> git.lizzy.rs Git - rust.git/commitdiff
Print a friendly error for the if-let construct without an else block
authorBarosl Lee <vcs@barosl.com>
Fri, 19 Dec 2014 16:42:21 +0000 (01:42 +0900)
committerBarosl Lee <vcs@barosl.com>
Sat, 20 Dec 2014 00:17:14 +0000 (09:17 +0900)
Fixes #19991.

src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ext/expand.rs
src/test/compile-fail/issue-19991.rs [new file with mode: 0644]

index 44cc5fce53da35c81c0f118e2eff0b7382f2324f..d4b89621ace008c21ddfd3e5f3cdadb5c40d041e 100644 (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,
             )
         }
     });
index bbc33826f35519af565553491638aadb448ff99b..f8a8ef35f754b8b70e50f2af07e046a172b51480 100644 (file)
@@ -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);
index be8f32bc4d5d8e58a640b0b461e817613391c8d0..ab338da63bf4d854eebae86ee3a91cd324039f1c 100644 (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,
 }
 
index 20c8ff20b713b88bd3b62a690d8a27e242aa251e..63bd38de8a096f65849a0ed19fee9b899fc00a7a 100644 (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)
         }
 
diff --git a/src/test/compile-fail/issue-19991.rs b/src/test/compile-fail/issue-19991.rs
new file mode 100644 (file)
index 0000000..0f1dbfa
--- /dev/null
@@ -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
+    };
+}