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