diff options
| author | bors <bors@rust-lang.org> | 2017-05-02 12:11:54 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-05-02 12:11:54 +0000 |
| commit | 96e2c34286099eea4f51daaadbb82a8fbe99e0f6 (patch) | |
| tree | 11b9c36039988c5b30c4ff443659e7f4e6c76ce6 | |
| parent | 50517d58a2f43779c27478baf77f938c0b3ebba0 (diff) | |
| parent | c741bc80320e18093a328fd36955a2d1bfae689b (diff) | |
| download | rust-96e2c34286099eea4f51daaadbb82a8fbe99e0f6.tar.gz rust-96e2c34286099eea4f51daaadbb82a8fbe99e0f6.zip | |
Auto merge of #41547 - alexeyzab:41425-fix-mismatched-types-error-message, r=arielb1
Fix error message for mismatched types This addresses #41425 by implementing the changes mentioned in the following comment: https://github.com/rust-lang/rust/issues/41425#issuecomment-296754508
| -rw-r--r-- | src/librustc_typeck/check/_match.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/coercion.rs | 22 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/coercion-missing-tail-expected-type.rs | 20 | ||||
| -rw-r--r-- | src/test/ui/coercion-missing-tail-expected-type.stderr | 19 |
5 files changed, 62 insertions, 12 deletions
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 1086773041c..ac10dfd36e2 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -498,7 +498,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if is_if_let_fallback { let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse); assert!(arm_ty.is_nil()); - coercion.coerce_forced_unit(self, &cause, &mut |_| ()); + coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); } else { let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm { arm_span: arm.body.span, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index d21b5f739bd..57415021976 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1001,7 +1001,12 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> expression_ty: Ty<'tcx>, expression_diverges: Diverges) { - self.coerce_inner(fcx, cause, Some(expression), expression_ty, expression_diverges, None) + self.coerce_inner(fcx, + cause, + Some(expression), + expression_ty, + expression_diverges, + None, false) } /// Indicates that one of the inputs is a "forced unit". This @@ -1019,14 +1024,16 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> pub fn coerce_forced_unit<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, cause: &ObligationCause<'tcx>, - augment_error: &mut FnMut(&mut DiagnosticBuilder)) + augment_error: &mut FnMut(&mut DiagnosticBuilder), + label_unit_as_expected: bool) { self.coerce_inner(fcx, cause, None, fcx.tcx.mk_nil(), Diverges::Maybe, - Some(augment_error)) + Some(augment_error), + label_unit_as_expected) } /// The inner coercion "engine". If `expression` is `None`, this @@ -1038,7 +1045,8 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> expression: Option<&'gcx hir::Expr>, mut expression_ty: Ty<'tcx>, expression_diverges: Diverges, - augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>) + augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>, + label_expression_as_expected: bool) { // Incorporate whatever type inference information we have // until now; in principle we might also want to process @@ -1096,7 +1104,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> // Another example is `break` with no argument expression. assert!(expression_ty.is_nil()); assert!(expression_ty.is_nil(), "if let hack without unit type"); - fcx.eq_types(true, cause, expression_ty, self.merged_ty()) + fcx.eq_types(label_expression_as_expected, cause, expression_ty, self.merged_ty()) .map(|infer_ok| { fcx.register_infer_ok_obligations(infer_ok); expression_ty @@ -1119,11 +1127,11 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> } } Err(err) => { - let (expected, found) = if expression.is_none() { + let (expected, found) = if label_expression_as_expected { // In the case where this is a "forced unit", like // `break`, we want to call the `()` "expected" // since it is implied by the syntax. - assert!(expression_ty.is_nil()); + // (Note: not all force-units work this way.)" (expression_ty, self.final_ty.unwrap_or(self.expected_ty)) } else { // Otherwise, the "expected" type for error diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5a581788a21..9185b6ec7b1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2864,7 +2864,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(cond_diverges | then_diverges & else_diverges); } else { let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse); - coerce.coerce_forced_unit(self, &else_cause, &mut |_| ()); + coerce.coerce_forced_unit(self, &else_cause, &mut |_| (), true); // If the condition is false we can't diverge. self.diverges.set(cond_diverges); @@ -3581,7 +3581,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { coerce.coerce(self, &cause, e, e_ty, e_diverges); } else { assert!(e_ty.is_nil()); - coerce.coerce_forced_unit(self, &cause, &mut |_| ()); + coerce.coerce_forced_unit(self, &cause, &mut |_| (), true); } } else { // If `ctxt.coerce` is `None`, we can just ignore @@ -3616,7 +3616,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - coercion.coerce_forced_unit(self, &cause, &mut |_| ()); + coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); } tcx.types.never } @@ -4154,6 +4154,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // expression (assuming there are no other breaks, // this implies that the type of the block will be // `!`). + // + // #41425 -- label the implicit `()` as being the + // "found type" here, rather than the "expected type". if !self.diverges.get().always() { coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| { if let Some(expected_ty) = expected.only_has_type(self) { @@ -4161,7 +4164,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected_ty, err); } - }); + }, false); } } }); diff --git a/src/test/ui/coercion-missing-tail-expected-type.rs b/src/test/ui/coercion-missing-tail-expected-type.rs new file mode 100644 index 00000000000..489ad817ea8 --- /dev/null +++ b/src/test/ui/coercion-missing-tail-expected-type.rs @@ -0,0 +1,20 @@ +// Copyright 2017 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. + +// #41425 -- error message "mismatched types" has wrong types + +fn plus_one(x: i32) -> i32 { + x + 1; +} + +fn main() { + let x = plus_one(5); + println!("X = {}", x); +} diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr new file mode 100644 index 00000000000..8f08ff34637 --- /dev/null +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:13:28 + | +13 | fn plus_one(x: i32) -> i32 { + | ____________________________^ +14 | | x + 1; +15 | | } + | |_^ expected i32, found () + | + = note: expected type `i32` + found type `()` +help: consider removing this semicolon: + --> $DIR/coercion-missing-tail-expected-type.rs:14:10 + | +14 | x + 1; + | ^ + +error: aborting due to previous error + |
