mirror of https://github.com/rust-lang/rust.git
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
This commit is contained in:
commit
96e2c34286
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue