Skip to content

Commit

Permalink
Tweak type mismatch caused by break on tail expr
Browse files Browse the repository at this point in the history
When `break;` has a type mismatch because the `Destination` points at a tail
expression with an obligation flowing from a return type, point at the
return type.

Fix #39968.
  • Loading branch information
estebank committed Nov 5, 2019
1 parent d3d28a4 commit b0f258b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
fn suggest_fn_call(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
points_at_arg: bool,
) {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

pub fn check_for_cast(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>,
Expand Down
10 changes: 9 additions & 1 deletion src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
assert!(e_ty.is_unit());
let ty = coerce.expected_ty();
coerce.coerce_forced_unit(self, &cause, &mut |err| {
coerce.coerce_forced_unit(self, &cause, &mut |mut err| {
self.suggest_mismatched_types_on_tail(
&mut err,
expr,
ty,
e_ty,
cause.span,
target_id,
);
let val = match ty.kind {
ty::Bool => "true",
ty::Char => "'a'",
Expand Down
14 changes: 7 additions & 7 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4246,7 +4246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// - Possible missing return type if the return type is the default, and not `fn main()`.
pub fn suggest_mismatched_types_on_tail(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expr: &'tcx hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
Expand All @@ -4273,7 +4273,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// ```
fn suggest_fn_call(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expr: &hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
Expand Down Expand Up @@ -4386,7 +4386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

pub fn suggest_ref_or_into(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expr: &hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
Expand Down Expand Up @@ -4454,7 +4454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// in the heap by calling `Box::new()`.
fn suggest_boxing_when_appropriate(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expr: &hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
Expand Down Expand Up @@ -4498,7 +4498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// it suggests adding a semicolon.
fn suggest_missing_semicolon(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expression: &'tcx hir::Expr,
expected: Ty<'tcx>,
cause_span: Span,
Expand Down Expand Up @@ -4537,7 +4537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// type.
fn suggest_missing_return_type(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
fn_decl: &hir::FnDecl,
expected: Ty<'tcx>,
found: Ty<'tcx>,
Expand Down Expand Up @@ -4603,7 +4603,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// `.await` to the tail of the expression.
fn suggest_missing_await(
&self,
err: &mut DiagnosticBuilder<'tcx>,
err: &mut DiagnosticBuilder<'_>,
expr: &hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/type/type-error-break-tail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn loop_ending() -> i32 {
loop {
if false { break; } //~ ERROR mismatched types
return 42;
}
}

fn main() {}
18 changes: 18 additions & 0 deletions src/test/ui/type/type-error-break-tail.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0308]: mismatched types
--> $DIR/type-error-break-tail.rs:3:20
|
LL | fn loop_ending() -> i32 {
| --- expected `i32` because of return type
LL | loop {
LL | if false { break; }
| ^^^^^
| |
| expected i32, found ()
| help: give it a value of the expected type: `break 42`
|
= note: expected type `i32`
found type `()`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit b0f258b

Please sign in to comment.