@@ -614,13 +614,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
614614 err. span_label ( span, "expected due to this" ) ;
615615 }
616616 ObligationCauseCode :: MatchExpressionArm ( box MatchExpressionArmCause {
617- semi_span,
617+ arm_block_id,
618+ arm_span,
619+ arm_ty,
620+ prior_arm_block_id,
621+ prior_arm_span,
622+ prior_arm_ty,
618623 source,
619624 ref prior_arms,
620- last_ty,
621625 scrut_hir_id,
622626 opt_suggest_box_span,
623- arm_span,
624627 scrut_span,
625628 ..
626629 } ) => match source {
@@ -651,10 +654,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
651654 }
652655 }
653656 _ => {
654- // `last_ty ` can be `!`, `expected` will have better info when present.
657+ // `prior_arm_ty ` can be `!`, `expected` will have better info when present.
655658 let t = self . resolve_vars_if_possible ( match exp_found {
656659 Some ( ty:: error:: ExpectedFound { expected, .. } ) => expected,
657- _ => last_ty ,
660+ _ => prior_arm_ty ,
658661 } ) ;
659662 let source_map = self . tcx . sess . source_map ( ) ;
660663 let mut any_multiline_arm = source_map. is_multiline ( arm_span) ;
@@ -679,37 +682,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
679682 } ;
680683 let msg = "`match` arms have incompatible types" ;
681684 err. span_label ( outer_error_span, msg) ;
682- if let Some ( ( sp, boxed) ) = semi_span {
683- if let ( StatementAsExpression :: NeedsBoxing , [ .., prior_arm] ) =
684- ( boxed, & prior_arms[ ..] )
685- {
686- err. multipart_suggestion (
687- "consider removing this semicolon and boxing the expressions" ,
688- vec ! [
689- ( prior_arm. shrink_to_lo( ) , "Box::new(" . to_string( ) ) ,
690- ( prior_arm. shrink_to_hi( ) , ")" . to_string( ) ) ,
691- ( arm_span. shrink_to_lo( ) , "Box::new(" . to_string( ) ) ,
692- ( arm_span. shrink_to_hi( ) , ")" . to_string( ) ) ,
693- ( sp, String :: new( ) ) ,
694- ] ,
695- Applicability :: HasPlaceholders ,
696- ) ;
697- } else if matches ! ( boxed, StatementAsExpression :: NeedsBoxing ) {
698- err. span_suggestion_short (
699- sp,
700- "consider removing this semicolon and boxing the expressions" ,
701- "" ,
702- Applicability :: MachineApplicable ,
703- ) ;
704- } else {
705- err. span_suggestion_short (
706- sp,
707- "consider removing this semicolon" ,
708- "" ,
709- Applicability :: MachineApplicable ,
710- ) ;
711- }
712- }
685+ self . suggest_remove_semi_or_return_binding (
686+ err,
687+ prior_arm_block_id,
688+ prior_arm_ty,
689+ prior_arm_span,
690+ arm_block_id,
691+ arm_ty,
692+ arm_span,
693+ ) ;
713694 if let Some ( ret_sp) = opt_suggest_box_span {
714695 // Get return type span and point to it.
715696 self . suggest_boxing_for_return_impl_trait (
@@ -734,48 +715,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
734715 if let Some ( sp) = outer_span {
735716 err. span_label ( sp, "`if` and `else` have incompatible types" ) ;
736717 }
737- let semicolon = if let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( then_id)
738- && let Some ( remove_semicolon) = self . could_remove_semicolon ( blk, else_ty)
739- {
740- Some ( remove_semicolon)
741- } else if let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( else_id)
742- && let Some ( remove_semicolon) = self . could_remove_semicolon ( blk, then_ty)
743- {
744- Some ( remove_semicolon)
745- } else {
746- None
747- } ;
748- if let Some ( ( sp, boxed) ) = semicolon {
749- if matches ! ( boxed, StatementAsExpression :: NeedsBoxing ) {
750- err. multipart_suggestion (
751- "consider removing this semicolon and boxing the expression" ,
752- vec ! [
753- ( then_span. shrink_to_lo( ) , "Box::new(" . to_string( ) ) ,
754- ( then_span. shrink_to_hi( ) , ")" . to_string( ) ) ,
755- ( else_span. shrink_to_lo( ) , "Box::new(" . to_string( ) ) ,
756- ( else_span. shrink_to_hi( ) , ")" . to_string( ) ) ,
757- ( sp, String :: new( ) ) ,
758- ] ,
759- Applicability :: MachineApplicable ,
760- ) ;
761- } else {
762- err. span_suggestion_short (
763- sp,
764- "consider removing this semicolon" ,
765- "" ,
766- Applicability :: MachineApplicable ,
767- ) ;
768- }
769- } else {
770- let suggested = if let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( then_id) {
771- self . consider_returning_binding ( blk, else_ty, err)
772- } else {
773- false
774- } ;
775- if !suggested && let hir:: Node :: Block ( blk) = self . tcx . hir ( ) . get ( else_id) {
776- self . consider_returning_binding ( blk, then_ty, err) ;
777- }
778- }
718+ self . suggest_remove_semi_or_return_binding (
719+ err,
720+ Some ( then_id) ,
721+ then_ty,
722+ then_span,
723+ Some ( else_id) ,
724+ else_ty,
725+ else_span,
726+ ) ;
779727 if let Some ( ret_sp) = opt_suggest_box_span {
780728 self . suggest_boxing_for_return_impl_trait (
781729 err,
@@ -800,6 +748,69 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
800748 }
801749 }
802750
751+ fn suggest_remove_semi_or_return_binding (
752+ & self ,
753+ err : & mut Diagnostic ,
754+ first_id : Option < hir:: HirId > ,
755+ first_ty : Ty < ' tcx > ,
756+ first_span : Span ,
757+ second_id : Option < hir:: HirId > ,
758+ second_ty : Ty < ' tcx > ,
759+ second_span : Span ,
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 ) {
777+ err. multipart_suggestion (
778+ "consider removing this semicolon and boxing the expressions" ,
779+ vec ! [
780+ ( first_span. shrink_to_lo( ) , "Box::new(" . to_string( ) ) ,
781+ ( first_span. shrink_to_hi( ) , ")" . to_string( ) ) ,
782+ ( second_span. shrink_to_lo( ) , "Box::new(" . to_string( ) ) ,
783+ ( second_span. shrink_to_hi( ) , ")" . to_string( ) ) ,
784+ ( sp, String :: new( ) ) ,
785+ ] ,
786+ Applicability :: MachineApplicable ,
787+ ) ;
788+ } else {
789+ err. span_suggestion_short (
790+ sp,
791+ "consider removing this semicolon" ,
792+ "" ,
793+ Applicability :: MachineApplicable ,
794+ ) ;
795+ }
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) ;
810+ }
811+ }
812+ }
813+
803814 fn suggest_boxing_for_return_impl_trait (
804815 & self ,
805816 err : & mut Diagnostic ,
0 commit comments