@@ -770,55 +770,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
770770 let prev_diverges = self . diverges . get ( ) ;
771771 let ctxt = BreakableCtxt { coerce : Some ( coerce) , may_break : false } ;
772772
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+ }
777778
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+ }
818821 }
819822 }
820- }
821- coerce. coerce_forced_unit (
823+ coerce. coerce_forced_unit (
822824 self ,
823825 & self . misc ( sp) ,
824826 & mut |err| {
@@ -827,19 +829,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
827829 if expected_ty == self . tcx . types . bool {
828830 // If this is caused by a missing `let` in a `while let`,
829831 // 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 , |_| {
840855 err. downgrade_to_delayed_bug ( ) ;
841- }
842- _ => { }
856+ } )
843857 }
844858 }
845859 }
@@ -853,9 +867,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
853867 } ,
854868 false ,
855869 ) ;
870+ }
856871 }
857- }
858- } ) ;
872+ } ) ;
859873
860874 if ctxt. may_break {
861875 // If we can break from the block, then the block's exit is always reachable
0 commit comments