@@ -770,55 +770,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
770
770
let prev_diverges = self . diverges . get ( ) ;
771
771
let ctxt = BreakableCtxt { coerce : Some ( coerce) , may_break : false } ;
772
772
773
- let ( ctxt, ( ) ) = self . with_breakable_ctxt ( blk. hir_id , ctxt, || {
774
- for ( pos, s) in blk. stmts . iter ( ) . enumerate ( ) {
775
- self . check_stmt ( s, blk. stmts . len ( ) - 1 == pos) ;
776
- }
773
+ let ( ctxt, ( ) ) =
774
+ self . with_breakable_ctxt ( blk. hir_id , ctxt, || {
775
+ for ( pos, s) in blk. stmts . iter ( ) . enumerate ( ) {
776
+ self . check_stmt ( s, blk. stmts . len ( ) - 1 == pos) ;
777
+ }
777
778
778
- // check the tail expression **without** holding the
779
- // `enclosing_breakables` lock below.
780
- let tail_expr_ty = tail_expr. map ( |t| self . check_expr_with_expectation ( t, expected) ) ;
781
-
782
- let mut enclosing_breakables = self . enclosing_breakables . borrow_mut ( ) ;
783
- let ctxt = enclosing_breakables. find_breakable ( blk. hir_id ) ;
784
- let coerce = ctxt. coerce . as_mut ( ) . unwrap ( ) ;
785
- if let Some ( tail_expr_ty) = tail_expr_ty {
786
- let tail_expr = tail_expr. unwrap ( ) ;
787
- let span = self . get_expr_coercion_span ( tail_expr) ;
788
- let cause = self . cause ( span, ObligationCauseCode :: BlockTailExpression ( blk. hir_id ) ) ;
789
- coerce. coerce ( self , & cause, tail_expr, tail_expr_ty) ;
790
- } else {
791
- // Subtle: if there is no explicit tail expression,
792
- // that is typically equivalent to a tail expression
793
- // of `()` -- except if the block diverges. In that
794
- // case, there is no value supplied from the tail
795
- // expression (assuming there are no other breaks,
796
- // this implies that the type of the block will be
797
- // `!`).
798
- //
799
- // #41425 -- label the implicit `()` as being the
800
- // "found type" here, rather than the "expected type".
801
- if !self . diverges . get ( ) . is_always ( ) {
802
- // #50009 -- Do not point at the entire fn block span, point at the return type
803
- // span, as it is the cause of the requirement, and
804
- // `consider_hint_about_removing_semicolon` will point at the last expression
805
- // if it were a relevant part of the error. This improves usability in editors
806
- // that highlight errors inline.
807
- let mut sp = blk. span ;
808
- let mut fn_span = None ;
809
- if let Some ( ( decl, ident) ) = self . get_parent_fn_decl ( blk. hir_id ) {
810
- let ret_sp = decl. output . span ( ) ;
811
- if let Some ( block_sp) = self . parent_item_span ( blk. hir_id ) {
812
- // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
813
- // output would otherwise be incorrect and even misleading. Make sure
814
- // the span we're aiming at correspond to a `fn` body.
815
- if block_sp == blk. span {
816
- sp = ret_sp;
817
- fn_span = Some ( ident. span ) ;
779
+ // check the tail expression **without** holding the
780
+ // `enclosing_breakables` lock below.
781
+ let tail_expr_ty = tail_expr. map ( |t| self . check_expr_with_expectation ( t, expected) ) ;
782
+
783
+ let mut enclosing_breakables = self . enclosing_breakables . borrow_mut ( ) ;
784
+ let ctxt = enclosing_breakables. find_breakable ( blk. hir_id ) ;
785
+ let coerce = ctxt. coerce . as_mut ( ) . unwrap ( ) ;
786
+ if let Some ( tail_expr_ty) = tail_expr_ty {
787
+ let tail_expr = tail_expr. unwrap ( ) ;
788
+ let span = self . get_expr_coercion_span ( tail_expr) ;
789
+ let cause =
790
+ self . cause ( span, ObligationCauseCode :: BlockTailExpression ( blk. hir_id ) ) ;
791
+ coerce. coerce ( self , & cause, tail_expr, tail_expr_ty) ;
792
+ } else {
793
+ // Subtle: if there is no explicit tail expression,
794
+ // that is typically equivalent to a tail expression
795
+ // of `()` -- except if the block diverges. In that
796
+ // case, there is no value supplied from the tail
797
+ // expression (assuming there are no other breaks,
798
+ // this implies that the type of the block will be
799
+ // `!`).
800
+ //
801
+ // #41425 -- label the implicit `()` as being the
802
+ // "found type" here, rather than the "expected type".
803
+ if !self . diverges . get ( ) . is_always ( ) {
804
+ // #50009 -- Do not point at the entire fn block span, point at the return type
805
+ // span, as it is the cause of the requirement, and
806
+ // `consider_hint_about_removing_semicolon` will point at the last expression
807
+ // if it were a relevant part of the error. This improves usability in editors
808
+ // that highlight errors inline.
809
+ let mut sp = blk. span ;
810
+ let mut fn_span = None ;
811
+ if let Some ( ( decl, ident) ) = self . get_parent_fn_decl ( blk. hir_id ) {
812
+ let ret_sp = decl. output . span ( ) ;
813
+ if let Some ( block_sp) = self . parent_item_span ( blk. hir_id ) {
814
+ // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
815
+ // output would otherwise be incorrect and even misleading. Make sure
816
+ // the span we're aiming at correspond to a `fn` body.
817
+ if block_sp == blk. span {
818
+ sp = ret_sp;
819
+ fn_span = Some ( ident. span ) ;
820
+ }
818
821
}
819
822
}
820
- }
821
- coerce. coerce_forced_unit (
823
+ coerce. coerce_forced_unit (
822
824
self ,
823
825
& self . misc ( sp) ,
824
826
& mut |err| {
@@ -827,19 +829,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
827
829
if expected_ty == self . tcx . types . bool {
828
830
// If this is caused by a missing `let` in a `while let`,
829
831
// silence this redundant error, as we already emit E0070.
830
- let parent = self . tcx . hir ( ) . get_parent_node ( blk. hir_id ) ;
831
- let parent = self . tcx . hir ( ) . get_parent_node ( parent) ;
832
- let parent = self . tcx . hir ( ) . get_parent_node ( parent) ;
833
- let parent = self . tcx . hir ( ) . get_parent_node ( parent) ;
834
- let parent = self . tcx . hir ( ) . get_parent_node ( parent) ;
835
- match self . tcx . hir ( ) . find ( parent) {
836
- Some ( hir:: Node :: Expr ( hir:: Expr {
837
- kind : hir:: ExprKind :: Loop ( _, _, hir:: LoopSource :: While , _) ,
838
- ..
839
- } ) ) => {
832
+
833
+ // Our block must be a `assign desugar local; assignment`
834
+ if let Some ( hir:: Node :: Block ( hir:: Block {
835
+ stmts :
836
+ [ hir:: Stmt {
837
+ kind :
838
+ hir:: StmtKind :: Local ( hir:: Local {
839
+ source : hir:: LocalSource :: AssignDesugar ( _) ,
840
+ ..
841
+ } ) ,
842
+ ..
843
+ } , hir:: Stmt {
844
+ kind :
845
+ hir:: StmtKind :: Expr ( hir:: Expr {
846
+ kind : hir:: ExprKind :: Assign ( ..) ,
847
+ ..
848
+ } ) ,
849
+ ..
850
+ } ] ,
851
+ ..
852
+ } ) ) = self . tcx . hir ( ) . find ( blk. hir_id )
853
+ {
854
+ self . comes_from_while_condition ( blk. hir_id , |_| {
840
855
err. downgrade_to_delayed_bug ( ) ;
841
- }
842
- _ => { }
856
+ } )
843
857
}
844
858
}
845
859
}
@@ -853,9 +867,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
853
867
} ,
854
868
false ,
855
869
) ;
870
+ }
856
871
}
857
- }
858
- } ) ;
872
+ } ) ;
859
873
860
874
if ctxt. may_break {
861
875
// If we can break from the block, then the block's exit is always reachable
0 commit comments