1
Fork 0

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:
alexey zabelin 2017-04-25 18:28:08 -04:00
parent 63c77214c1
commit dd906ef7ec
No known key found for this signature in database
GPG key ID: 3A169985478324E9
5 changed files with 54 additions and 14 deletions

View file

@ -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,

View file

@ -1001,7 +1001,7 @@ 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 +1019,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 +1040,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
@ -1119,11 +1122,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
}
}
Err(err) => {
let (expected, found) = if expression.is_none() {
// 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());
let (expected, found) = if label_expression_as_expected {
(expression_ty, self.final_ty.unwrap_or(self.expected_ty))
} else {
// Otherwise, the "expected" type for error

View file

@ -2785,7 +2785,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);
@ -3502,7 +3502,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
@ -3537,7 +3537,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
}
@ -4077,6 +4077,8 @@ 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) {
@ -4084,7 +4086,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected_ty,
err);
}
});
}, false);
}
}
});

View file

@ -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);
}

View file

@ -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 (), found i32
|
= 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