@@ -758,22 +758,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
758758 second_ty : Ty < ' tcx > ,
759759 second_span : Span ,
760760 ) {
761- let semicolon =
762- if let Some ( first_id) = first_id
763- && let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( first_id)
764- && let Some ( remove_semicolon) = self . could_remove_semicolon ( blk, second_ty)
765- {
766- Some ( remove_semicolon)
767- } else if let Some ( second_id) = second_id
768- && let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( second_id)
769- && let Some ( remove_semicolon) = self . could_remove_semicolon ( blk, first_ty)
770- {
771- Some ( remove_semicolon)
772- } else {
773- None
774- } ;
775- if let Some ( ( sp, boxed) ) = semicolon {
776- if matches ! ( boxed, StatementAsExpression :: NeedsBoxing ) {
761+ let remove_semicolon =
762+ [ ( first_id, second_ty) , ( second_id, first_ty) ] . into_iter ( ) . find_map ( |( id, ty) | {
763+ let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( id?) else { return None } ;
764+ self . could_remove_semicolon ( blk, ty)
765+ } ) ;
766+ match remove_semicolon {
767+ Some ( ( sp, StatementAsExpression :: NeedsBoxing ) ) => {
777768 err. multipart_suggestion (
778769 "consider removing this semicolon and boxing the expressions" ,
779770 vec ! [
@@ -785,28 +776,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
785776 ] ,
786777 Applicability :: MachineApplicable ,
787778 ) ;
788- } else {
779+ }
780+ Some ( ( sp, StatementAsExpression :: CorrectType ) ) => {
789781 err. span_suggestion_short (
790782 sp,
791783 "consider removing this semicolon" ,
792784 "" ,
793785 Applicability :: MachineApplicable ,
794786 ) ;
795787 }
796- } else {
797- let suggested =
798- if let Some ( first_id) = first_id
799- && let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( first_id)
800- {
801- self . consider_returning_binding ( blk, second_ty, err)
802- } else {
803- false
804- } ;
805- if !suggested
806- && let Some ( second_id) = second_id
807- && let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( second_id)
808- {
809- self . consider_returning_binding ( blk, first_ty, err) ;
788+ None => {
789+ for ( id, ty) in [ ( first_id, second_ty) , ( second_id, first_ty) ] {
790+ if let Some ( id) = id
791+ && let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( id)
792+ && self . consider_returning_binding ( blk, ty, err)
793+ {
794+ break ;
795+ }
796+ }
810797 }
811798 }
812799 }
@@ -2884,8 +2871,10 @@ impl TyCategory {
28842871}
28852872
28862873impl < ' tcx > InferCtxt < ' _ , ' tcx > {
2874+ /// Given a [`hir::Block`], get the span of its last expression or
2875+ /// statement, peeling off any inner blocks.
28872876 pub fn find_block_span ( & self , block : & ' tcx hir:: Block < ' tcx > ) -> Span {
2888- let block = block. peel_blocks ( ) ;
2877+ let block = block. innermost_block ( ) ;
28892878 if let Some ( expr) = & block. expr {
28902879 expr. span
28912880 } else if let Some ( stmt) = block. stmts . last ( ) {
@@ -2897,27 +2886,30 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
28972886 }
28982887 }
28992888
2889+ /// Given a [`hir::HirId`] for a block, get the span of its last expression
2890+ /// or statement, peeling off any inner blocks.
29002891 pub fn find_block_span_from_hir_id ( & self , hir_id : hir:: HirId ) -> Span {
29012892 match self . tcx . hir ( ) . get ( hir_id) {
29022893 hir:: Node :: Block ( blk) => self . find_block_span ( blk) ,
2903- // The parser was in a weird state if either of these happen...
2894+ // The parser was in a weird state if either of these happen, but
2895+ // it's better not to panic.
29042896 hir:: Node :: Expr ( e) => e. span ,
29052897 _ => rustc_span:: DUMMY_SP ,
29062898 }
29072899 }
29082900
2901+ /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
2902+ /// is enough to fix the error.
29092903 pub fn could_remove_semicolon (
29102904 & self ,
29112905 blk : & ' tcx hir:: Block < ' tcx > ,
29122906 expected_ty : Ty < ' tcx > ,
29132907 ) -> Option < ( Span , StatementAsExpression ) > {
2914- let blk = blk. peel_blocks ( ) ;
2908+ let blk = blk. innermost_block ( ) ;
29152909 // Do not suggest if we have a tail expr.
29162910 if blk. expr . is_some ( ) {
29172911 return None ;
29182912 }
2919- // Be helpful when the user wrote `{... expr;}` and
2920- // taking the `;` off is enough to fix the error.
29212913 let last_stmt = blk. stmts . last ( ) ?;
29222914 let hir:: StmtKind :: Semi ( ref last_expr) = last_stmt. kind else {
29232915 return None ;
@@ -2987,13 +2979,15 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
29872979 Some ( ( span, needs_box) )
29882980 }
29892981
2982+ /// Suggest returning a local binding with a compatible type if the block
2983+ /// has no return expression.
29902984 pub fn consider_returning_binding (
29912985 & self ,
29922986 blk : & ' tcx hir:: Block < ' tcx > ,
29932987 expected_ty : Ty < ' tcx > ,
29942988 err : & mut Diagnostic ,
29952989 ) -> bool {
2996- let blk = blk. peel_blocks ( ) ;
2990+ let blk = blk. innermost_block ( ) ;
29972991 // Do not suggest if we have a tail expr.
29982992 if blk. expr . is_some ( ) {
29992993 return false ;
0 commit comments