@@ -3474,37 +3474,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
34743474 } else {
34753475 // If this `if` expr is the parent's function return expr, the cause of the type
34763476 // 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+
35013479 let else_cause = self . cause ( sp, ObligationCauseCode :: IfExpressionWithNoElse ) ;
35023480 coerce. coerce_forced_unit ( self , & else_cause, & mut |err| {
35033481 if let Some ( ( sp, msg) ) = & ret_reason {
35043482 err. span_label ( * sp, msg. as_str ( ) ) ;
35053483 }
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 ( ) ) ;
35083487
35093488 // If the condition is false we can't diverge.
35103489 self . diverges . set ( cond_diverges) ;
@@ -3518,6 +3497,33 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
35183497 }
35193498 }
35203499
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+
35213527 // Check field access expressions
35223528 fn check_field ( & self ,
35233529 expr : & ' gcx hir:: Expr ,
0 commit comments