Skip to content

Commit dd906ef

Browse files
committed
Fix error message for mismatched types
This addresses rust-lang#41425 by implementing the changes mentioned in the following comment: rust-lang#41425 (comment)
1 parent 63c7721 commit dd906ef

File tree

5 files changed

+54
-14
lines changed

5 files changed

+54
-14
lines changed

src/librustc_typeck/check/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
498498
if is_if_let_fallback {
499499
let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
500500
assert!(arm_ty.is_nil());
501-
coercion.coerce_forced_unit(self, &cause, &mut |_| ());
501+
coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
502502
} else {
503503
let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
504504
arm_span: arm.body.span,

src/librustc_typeck/check/coercion.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
10011001
expression_ty: Ty<'tcx>,
10021002
expression_diverges: Diverges)
10031003
{
1004-
self.coerce_inner(fcx, cause, Some(expression), expression_ty, expression_diverges, None)
1004+
self.coerce_inner(fcx, cause, Some(expression), expression_ty, expression_diverges, None, false)
10051005
}
10061006

10071007
/// 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>
10191019
pub fn coerce_forced_unit<'a>(&mut self,
10201020
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
10211021
cause: &ObligationCause<'tcx>,
1022-
augment_error: &mut FnMut(&mut DiagnosticBuilder))
1022+
augment_error: &mut FnMut(&mut DiagnosticBuilder),
1023+
label_unit_as_expected: bool)
10231024
{
10241025
self.coerce_inner(fcx,
10251026
cause,
10261027
None,
10271028
fcx.tcx.mk_nil(),
10281029
Diverges::Maybe,
1029-
Some(augment_error))
1030+
Some(augment_error),
1031+
label_unit_as_expected)
10301032
}
10311033

10321034
/// The inner coercion "engine". If `expression` is `None`, this
@@ -1038,7 +1040,8 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
10381040
expression: Option<&'gcx hir::Expr>,
10391041
mut expression_ty: Ty<'tcx>,
10401042
expression_diverges: Diverges,
1041-
augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>)
1043+
augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>,
1044+
label_expression_as_expected: bool)
10421045
{
10431046
// Incorporate whatever type inference information we have
10441047
// until now; in principle we might also want to process
@@ -1119,11 +1122,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
11191122
}
11201123
}
11211124
Err(err) => {
1122-
let (expected, found) = if expression.is_none() {
1123-
// In the case where this is a "forced unit", like
1124-
// `break`, we want to call the `()` "expected"
1125-
// since it is implied by the syntax.
1126-
assert!(expression_ty.is_nil());
1125+
let (expected, found) = if label_expression_as_expected {
11271126
(expression_ty, self.final_ty.unwrap_or(self.expected_ty))
11281127
} else {
11291128
// Otherwise, the "expected" type for error

src/librustc_typeck/check/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -2785,7 +2785,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
27852785
self.diverges.set(cond_diverges | then_diverges & else_diverges);
27862786
} else {
27872787
let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse);
2788-
coerce.coerce_forced_unit(self, &else_cause, &mut |_| ());
2788+
coerce.coerce_forced_unit(self, &else_cause, &mut |_| (), true);
27892789

27902790
// If the condition is false we can't diverge.
27912791
self.diverges.set(cond_diverges);
@@ -3502,7 +3502,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
35023502
coerce.coerce(self, &cause, e, e_ty, e_diverges);
35033503
} else {
35043504
assert!(e_ty.is_nil());
3505-
coerce.coerce_forced_unit(self, &cause, &mut |_| ());
3505+
coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
35063506
}
35073507
} else {
35083508
// If `ctxt.coerce` is `None`, we can just ignore
@@ -3537,7 +3537,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
35373537
} else {
35383538
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
35393539
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
3540-
coercion.coerce_forced_unit(self, &cause, &mut |_| ());
3540+
coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
35413541
}
35423542
tcx.types.never
35433543
}
@@ -4077,14 +4077,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40774077
// expression (assuming there are no other breaks,
40784078
// this implies that the type of the block will be
40794079
// `!`).
4080+
//
4081+
// #41425 -- label the implicit `()` as being the "found type" here, rather than the "expected type".
40804082
if !self.diverges.get().always() {
40814083
coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| {
40824084
if let Some(expected_ty) = expected.only_has_type(self) {
40834085
self.consider_hint_about_removing_semicolon(blk,
40844086
expected_ty,
40854087
err);
40864088
}
4087-
});
4089+
}, false);
40884090
}
40894091
}
40904092
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// #41425 -- error message "mismatched types" has wrong types
12+
13+
fn plus_one(x: i32) -> i32 {
14+
x + 1;
15+
}
16+
17+
fn main() {
18+
let x = plus_one(5);
19+
println!("X = {}", x);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/coercion-missing-tail-expected-type.rs:13:28
3+
|
4+
13 | fn plus_one(x: i32) -> i32 {
5+
| ____________________________^
6+
14 | | x + 1;
7+
15 | | }
8+
| |_^ expected (), found i32
9+
|
10+
= note: expected type `i32`
11+
found type `()`
12+
help: consider removing this semicolon:
13+
--> $DIR/coercion-missing-tail-expected-type.rs:14:10
14+
|
15+
14 | x + 1;
16+
| ^
17+
18+
error: aborting due to previous error
19+

0 commit comments

Comments
 (0)