about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2017-06-16 10:34:17 -0700
committerEsteban Küber <esteban@kuber.com.ar>2017-06-16 12:15:06 -0700
commitda78b4d88e1ba4598428a92a6c8d5f9c399fede0 (patch)
tree4a0013d4424c574e22157ced62126d2762beeb9e
parent028b5f94e3aef435c626131e5b571272f2d3d52c (diff)
downloadrust-da78b4d88e1ba4598428a92a6c8d5f9c399fede0.tar.gz
rust-da78b4d88e1ba4598428a92a6c8d5f9c399fede0.zip
Review comments
- exhaustive match
- rename method to `check_expr_meets_expectation_or_error`
- formatting
- add `delay_span_bug`
- add test
-rw-r--r--src/librustc_typeck/check/_match.rs4
-rw-r--r--src/librustc_typeck/check/demand.rs3
-rw-r--r--src/librustc_typeck/check/mod.rs31
-rw-r--r--src/test/ui/type-check/assignment-in-if.rs (renamed from src/test/ui/type-check/issue-17283.rs)4
-rw-r--r--src/test/ui/type-check/assignment-in-if.stderr (renamed from src/test/ui/type-check/issue-17283.stderr)17
5 files changed, 38 insertions, 21 deletions
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 33f0b0282d1..bdd8169b84f 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -413,7 +413,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             // discriminant. This is sort of a workaround, see note (*) in
             // `check_pat` for some details.
             discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
-            self.check_expr_has_type(discrim, discrim_ty);
+            self.check_expr_has_type_or_error(discrim, discrim_ty);
         };
 
         // If the discriminant diverges, the match is pointless (e.g.,
@@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
             if let Some(ref e) = arm.guard {
                 self.diverges.set(pats_diverge);
-                self.check_expr_has_type(e, tcx.types.bool);
+                self.check_expr_has_type_or_error(e, tcx.types.bool);
             }
 
             self.diverges.set(pats_diverge);
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 732b9be81a3..1b6f96cf651 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -29,7 +29,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.demand_suptype_diag(sp, expected, actual).map(|mut e| e.emit());
     }
 
-    pub fn demand_suptype_diag(&self, sp: Span,
+    pub fn demand_suptype_diag(&self,
+                               sp: Span,
                                expected: Ty<'tcx>,
                                actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
         let cause = &self.misc(sp);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 5bba79a176e..d663d8f0d2b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -345,7 +345,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
         match self.resolve(fcx) {
             ExpectHasType(ty) => Some(ty),
             ExpectIfCondition => Some(fcx.tcx.types.bool),
-            _ => None
+            NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None,
         }
     }
 
@@ -2647,15 +2647,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.demand_eqtype(expr.span, expected, ty);
     }
 
-    pub fn check_expr_has_type(&self,
-                               expr: &'gcx hir::Expr,
-                               expected: Ty<'tcx>) -> Ty<'tcx> {
-        self.check_expr_expect_type(expr, ExpectHasType(expected))
+    pub fn check_expr_has_type_or_error(&self,
+                                        expr: &'gcx hir::Expr,
+                                        expected: Ty<'tcx>) -> Ty<'tcx> {
+        self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected))
     }
 
-    fn check_expr_expect_type(&self,
-                              expr: &'gcx hir::Expr,
-                              expected: Expectation<'tcx>) -> Ty<'tcx> {
+    fn check_expr_meets_expectation_or_error(&self,
+                                             expr: &'gcx hir::Expr,
+                                             expected: Expectation<'tcx>) -> Ty<'tcx> {
         let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool);
         let mut ty = self.check_expr_with_expectation(expr, expected);
 
@@ -2865,7 +2865,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                        opt_else_expr: Option<&'gcx hir::Expr>,
                        sp: Span,
                        expected: Expectation<'tcx>) -> Ty<'tcx> {
-        let cond_ty = self.check_expr_expect_type(cond_expr, ExpectIfCondition);
+        let cond_ty = self.check_expr_meets_expectation_or_error(cond_expr, ExpectIfCondition);
         let cond_diverges = self.diverges.get();
         self.diverges.set(Diverges::Maybe);
 
@@ -3352,7 +3352,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields,
                                       base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
-            self.check_expr_has_type(base_expr, struct_ty);
+            self.check_expr_has_type_or_error(base_expr, struct_ty);
             match struct_ty.sty {
                 ty::TyAdt(adt, substs) if adt.is_struct() => {
                     let fru_field_types = adt.struct_variant().fields.iter().map(|f| {
@@ -3668,7 +3668,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
 
             match expected {
-                ExpectIfCondition => (),
+                ExpectIfCondition => {
+                    self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\
+                                                            expected error elsehwere");
+                }
                 _ => {
                     // Only check this if not in an `if` condition, as the
                     // mistyped comparison help is more appropriate.
@@ -3704,7 +3707,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
               };
 
               self.with_breakable_ctxt(expr.id, ctxt, || {
-                  self.check_expr_has_type(&cond, tcx.types.bool);
+                  self.check_expr_has_type_or_error(&cond, tcx.types.bool);
                   let cond_diverging = self.diverges.get();
                   self.check_block_no_value(&body);
 
@@ -3842,7 +3845,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
                 None => {
                     let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span));
-                    let element_ty = self.check_expr_has_type(&element, t);
+                    let element_ty = self.check_expr_has_type_or_error(&element, t);
                     (element_ty, t)
                 }
             };
@@ -4097,7 +4100,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
             hir::StmtExpr(ref expr, _) => {
                 // Check with expected type of ()
-                self.check_expr_has_type(&expr, self.tcx.mk_nil());
+                self.check_expr_has_type_or_error(&expr, self.tcx.mk_nil());
             }
             hir::StmtSemi(ref expr, _) => {
                 self.check_expr(&expr);
diff --git a/src/test/ui/type-check/issue-17283.rs b/src/test/ui/type-check/assignment-in-if.rs
index f06888b8ec4..98dc55c6663 100644
--- a/src/test/ui/type-check/issue-17283.rs
+++ b/src/test/ui/type-check/assignment-in-if.rs
@@ -45,4 +45,8 @@ fn main() {
         //~| HELP did you mean to compare equality?
         println!("{}", x);
     }
+    if (if true { x = 4 } else { x = 5 }) {
+        //~^ ERROR mismatched types
+        println!("{}", x);
+    }
 }
diff --git a/src/test/ui/type-check/issue-17283.stderr b/src/test/ui/type-check/assignment-in-if.stderr
index f258caecd30..29439999273 100644
--- a/src/test/ui/type-check/issue-17283.stderr
+++ b/src/test/ui/type-check/assignment-in-if.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-17283.rs:25:8
+  --> $DIR/assignment-in-if.rs:25:8
    |
 25 |     if x = x {
    |        ^^^^^
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
               found type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-17283.rs:31:8
+  --> $DIR/assignment-in-if.rs:31:8
    |
 31 |     if (x = x) {
    |        ^^^^^^^
@@ -23,7 +23,7 @@ error[E0308]: mismatched types
               found type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-17283.rs:37:8
+  --> $DIR/assignment-in-if.rs:37:8
    |
 37 |     if y = (Foo { foo: x }) {
    |        ^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ error[E0308]: mismatched types
               found type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-17283.rs:43:8
+  --> $DIR/assignment-in-if.rs:43:8
    |
 43 |     if 3 = x {
    |        ^^^^^
@@ -46,5 +46,14 @@ error[E0308]: mismatched types
    = note: expected type `bool`
               found type `()`
 
+error[E0308]: mismatched types
+  --> $DIR/assignment-in-if.rs:48:8
+   |
+48 |     if (if true { x = 4 } else { x = 5 }) {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bool, found ()
+   |
+   = note: expected type `bool`
+              found type `()`
+
 error: aborting due to previous error(s)