@@ -3474,37 +3474,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3474
3474
} else {
3475
3475
// If this `if` expr is the parent's function return expr, the cause of the type
3476
3476
// coercion is the return type, point at it. (#25228)
3477
- let mut ret_reason = None ;
3478
- if let Node :: Block ( block) = self . tcx . hir ( ) . get_by_hir_id (
3479
- self . tcx . hir ( ) . get_parent_node_by_hir_id (
3480
- self . tcx . hir ( ) . get_parent_node_by_hir_id ( then_expr. hir_id ) ,
3481
- ) ,
3482
- ) {
3483
- // check that the body's parent is an fn
3484
- let parent = self . tcx . hir ( ) . get_by_hir_id (
3485
- self . tcx . hir ( ) . get_parent_node_by_hir_id (
3486
- self . tcx . hir ( ) . get_parent_node_by_hir_id ( block. hir_id ) ,
3487
- ) ,
3488
- ) ;
3489
- if let ( Some ( expr) , Node :: Item ( hir:: Item {
3490
- node : hir:: ItemKind :: Fn ( ..) , ..
3491
- } ) ) = ( & block. expr , parent) {
3492
- // check that the `if` expr without `else` is the fn body's expr
3493
- if expr. span == sp {
3494
- ret_reason = self . get_fn_decl ( then_expr. hir_id ) . map ( |( fn_decl, _) | (
3495
- fn_decl. output . span ( ) ,
3496
- format ! ( "found `{}` because of this return type" , fn_decl. output) ,
3497
- ) ) ;
3498
- }
3499
- }
3500
- }
3477
+ let ret_reason = self . maybe_get_coercion_reason ( then_expr. hir_id , sp) ;
3478
+
3501
3479
let else_cause = self . cause ( sp, ObligationCauseCode :: IfExpressionWithNoElse ) ;
3502
3480
coerce. coerce_forced_unit ( self , & else_cause, & mut |err| {
3503
3481
if let Some ( ( sp, msg) ) = & ret_reason {
3504
3482
err. span_label ( * sp, msg. as_str ( ) ) ;
3505
3483
}
3506
- err. note ( "`if` expressions without `else` must evaluate to `()`" ) ;
3507
- } , true ) ;
3484
+ err. note ( "`if` expressions without `else` evaluate to `()`" ) ;
3485
+ err. help ( "consider adding an `else` block that evaluates to the expected type" ) ;
3486
+ } , ret_reason. is_none ( ) ) ;
3508
3487
3509
3488
// If the condition is false we can't diverge.
3510
3489
self . diverges . set ( cond_diverges) ;
@@ -3518,6 +3497,33 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3518
3497
}
3519
3498
}
3520
3499
3500
+ fn maybe_get_coercion_reason ( & self , hir_id : hir:: HirId , sp : Span ) -> Option < ( Span , String ) > {
3501
+ if let Node :: Block ( block) = self . tcx . hir ( ) . get_by_hir_id (
3502
+ self . tcx . hir ( ) . get_parent_node_by_hir_id (
3503
+ self . tcx . hir ( ) . get_parent_node_by_hir_id ( hir_id) ,
3504
+ ) ,
3505
+ ) {
3506
+ // check that the body's parent is an fn
3507
+ let parent = self . tcx . hir ( ) . get_by_hir_id (
3508
+ self . tcx . hir ( ) . get_parent_node_by_hir_id (
3509
+ self . tcx . hir ( ) . get_parent_node_by_hir_id ( block. hir_id ) ,
3510
+ ) ,
3511
+ ) ;
3512
+ if let ( Some ( expr) , Node :: Item ( hir:: Item {
3513
+ node : hir:: ItemKind :: Fn ( ..) , ..
3514
+ } ) ) = ( & block. expr , parent) {
3515
+ // check that the `if` expr without `else` is the fn body's expr
3516
+ if expr. span == sp {
3517
+ return self . get_fn_decl ( hir_id) . map ( |( fn_decl, _) | (
3518
+ fn_decl. output . span ( ) ,
3519
+ format ! ( "expected `{}` because of this return type" , fn_decl. output) ,
3520
+ ) ) ;
3521
+ }
3522
+ }
3523
+ }
3524
+ None
3525
+ }
3526
+
3521
3527
// Check field access expressions
3522
3528
fn check_field ( & self ,
3523
3529
expr : & ' gcx hir:: Expr ,
0 commit comments