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:
parent
63c77214c1
commit
dd906ef7ec
5 changed files with 54 additions and 14 deletions
|
@ -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,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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
20
src/test/ui/coercion-missing-tail-expected-type.rs
Normal file
20
src/test/ui/coercion-missing-tail-expected-type.rs
Normal 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);
|
||||
}
|
19
src/test/ui/coercion-missing-tail-expected-type.stderr
Normal file
19
src/test/ui/coercion-missing-tail-expected-type.stderr
Normal 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
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue