@@ -758,22 +758,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
758
758
second_ty : Ty < ' tcx > ,
759
759
second_span : Span ,
760
760
) {
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 ) ) => {
777
768
err. multipart_suggestion (
778
769
"consider removing this semicolon and boxing the expressions" ,
779
770
vec ! [
@@ -785,28 +776,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
785
776
] ,
786
777
Applicability :: MachineApplicable ,
787
778
) ;
788
- } else {
779
+ }
780
+ Some ( ( sp, StatementAsExpression :: CorrectType ) ) => {
789
781
err. span_suggestion_short (
790
782
sp,
791
783
"consider removing this semicolon" ,
792
784
"" ,
793
785
Applicability :: MachineApplicable ,
794
786
) ;
795
787
}
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
+ }
810
797
}
811
798
}
812
799
}
@@ -2884,8 +2871,10 @@ impl TyCategory {
2884
2871
}
2885
2872
2886
2873
impl < ' tcx > InferCtxt < ' _ , ' tcx > {
2874
+ /// Given a [`hir::Block`], get the span of its last expression or
2875
+ /// statement, peeling off any inner blocks.
2887
2876
pub fn find_block_span ( & self , block : & ' tcx hir:: Block < ' tcx > ) -> Span {
2888
- let block = block. peel_blocks ( ) ;
2877
+ let block = block. innermost_block ( ) ;
2889
2878
if let Some ( expr) = & block. expr {
2890
2879
expr. span
2891
2880
} else if let Some ( stmt) = block. stmts . last ( ) {
@@ -2897,27 +2886,30 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
2897
2886
}
2898
2887
}
2899
2888
2889
+ /// Given a [`hir::HirId`] for a block, get the span of its last expression
2890
+ /// or statement, peeling off any inner blocks.
2900
2891
pub fn find_block_span_from_hir_id ( & self , hir_id : hir:: HirId ) -> Span {
2901
2892
match self . tcx . hir ( ) . get ( hir_id) {
2902
2893
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.
2904
2896
hir:: Node :: Expr ( e) => e. span ,
2905
2897
_ => rustc_span:: DUMMY_SP ,
2906
2898
}
2907
2899
}
2908
2900
2901
+ /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
2902
+ /// is enough to fix the error.
2909
2903
pub fn could_remove_semicolon (
2910
2904
& self ,
2911
2905
blk : & ' tcx hir:: Block < ' tcx > ,
2912
2906
expected_ty : Ty < ' tcx > ,
2913
2907
) -> Option < ( Span , StatementAsExpression ) > {
2914
- let blk = blk. peel_blocks ( ) ;
2908
+ let blk = blk. innermost_block ( ) ;
2915
2909
// Do not suggest if we have a tail expr.
2916
2910
if blk. expr . is_some ( ) {
2917
2911
return None ;
2918
2912
}
2919
- // Be helpful when the user wrote `{... expr;}` and
2920
- // taking the `;` off is enough to fix the error.
2921
2913
let last_stmt = blk. stmts . last ( ) ?;
2922
2914
let hir:: StmtKind :: Semi ( ref last_expr) = last_stmt. kind else {
2923
2915
return None ;
@@ -2987,13 +2979,15 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
2987
2979
Some ( ( span, needs_box) )
2988
2980
}
2989
2981
2982
+ /// Suggest returning a local binding with a compatible type if the block
2983
+ /// has no return expression.
2990
2984
pub fn consider_returning_binding (
2991
2985
& self ,
2992
2986
blk : & ' tcx hir:: Block < ' tcx > ,
2993
2987
expected_ty : Ty < ' tcx > ,
2994
2988
err : & mut Diagnostic ,
2995
2989
) -> bool {
2996
- let blk = blk. peel_blocks ( ) ;
2990
+ let blk = blk. innermost_block ( ) ;
2997
2991
// Do not suggest if we have a tail expr.
2998
2992
if blk. expr . is_some ( ) {
2999
2993
return false ;
0 commit comments