Skip to content

Commit 96e2c34

Browse files
committed
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: #41425 (comment)
2 parents 50517d5 + c741bc8 commit 96e2c34

File tree

5 files changed

+62
-12
lines changed

5 files changed

+62
-12
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

+15-7
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,12 @@ 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,
1005+
cause,
1006+
Some(expression),
1007+
expression_ty,
1008+
expression_diverges,
1009+
None, false)
10051010
}
10061011

10071012
/// 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>
10191024
pub fn coerce_forced_unit<'a>(&mut self,
10201025
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
10211026
cause: &ObligationCause<'tcx>,
1022-
augment_error: &mut FnMut(&mut DiagnosticBuilder))
1027+
augment_error: &mut FnMut(&mut DiagnosticBuilder),
1028+
label_unit_as_expected: bool)
10231029
{
10241030
self.coerce_inner(fcx,
10251031
cause,
10261032
None,
10271033
fcx.tcx.mk_nil(),
10281034
Diverges::Maybe,
1029-
Some(augment_error))
1035+
Some(augment_error),
1036+
label_unit_as_expected)
10301037
}
10311038

10321039
/// The inner coercion "engine". If `expression` is `None`, this
@@ -1038,7 +1045,8 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
10381045
expression: Option<&'gcx hir::Expr>,
10391046
mut expression_ty: Ty<'tcx>,
10401047
expression_diverges: Diverges,
1041-
augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>)
1048+
augment_error: Option<&mut FnMut(&mut DiagnosticBuilder)>,
1049+
label_expression_as_expected: bool)
10421050
{
10431051
// Incorporate whatever type inference information we have
10441052
// until now; in principle we might also want to process
@@ -1096,7 +1104,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
10961104
// Another example is `break` with no argument expression.
10971105
assert!(expression_ty.is_nil());
10981106
assert!(expression_ty.is_nil(), "if let hack without unit type");
1099-
fcx.eq_types(true, cause, expression_ty, self.merged_ty())
1107+
fcx.eq_types(label_expression_as_expected, cause, expression_ty, self.merged_ty())
11001108
.map(|infer_ok| {
11011109
fcx.register_infer_ok_obligations(infer_ok);
11021110
expression_ty
@@ -1119,11 +1127,11 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
11191127
}
11201128
}
11211129
Err(err) => {
1122-
let (expected, found) = if expression.is_none() {
1130+
let (expected, found) = if label_expression_as_expected {
11231131
// In the case where this is a "forced unit", like
11241132
// `break`, we want to call the `()` "expected"
11251133
// since it is implied by the syntax.
1126-
assert!(expression_ty.is_nil());
1134+
// (Note: not all force-units work this way.)"
11271135
(expression_ty, self.final_ty.unwrap_or(self.expected_ty))
11281136
} else {
11291137
// Otherwise, the "expected" type for error

src/librustc_typeck/check/mod.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -2864,7 +2864,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
28642864
self.diverges.set(cond_diverges | then_diverges & else_diverges);
28652865
} else {
28662866
let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse);
2867-
coerce.coerce_forced_unit(self, &else_cause, &mut |_| ());
2867+
coerce.coerce_forced_unit(self, &else_cause, &mut |_| (), true);
28682868

28692869
// If the condition is false we can't diverge.
28702870
self.diverges.set(cond_diverges);
@@ -3581,7 +3581,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
35813581
coerce.coerce(self, &cause, e, e_ty, e_diverges);
35823582
} else {
35833583
assert!(e_ty.is_nil());
3584-
coerce.coerce_forced_unit(self, &cause, &mut |_| ());
3584+
coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
35853585
}
35863586
} else {
35873587
// If `ctxt.coerce` is `None`, we can just ignore
@@ -3616,7 +3616,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36163616
} else {
36173617
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
36183618
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
3619-
coercion.coerce_forced_unit(self, &cause, &mut |_| ());
3619+
coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
36203620
}
36213621
tcx.types.never
36223622
}
@@ -4154,14 +4154,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
41544154
// expression (assuming there are no other breaks,
41554155
// this implies that the type of the block will be
41564156
// `!`).
4157+
//
4158+
// #41425 -- label the implicit `()` as being the
4159+
// "found type" here, rather than the "expected type".
41574160
if !self.diverges.get().always() {
41584161
coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| {
41594162
if let Some(expected_ty) = expected.only_has_type(self) {
41604163
self.consider_hint_about_removing_semicolon(blk,
41614164
expected_ty,
41624165
err);
41634166
}
4164-
});
4167+
}, false);
41654168
}
41664169
}
41674170
});
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 i32, found ()
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)