@@ -768,55 +768,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
768768 let prev_diverges = self . diverges . get ( ) ;
769769 let ctxt = BreakableCtxt { coerce : Some ( coerce) , may_break : false } ;
770770
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+ }
775776
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+ }
816819 }
817820 }
818- }
819- coerce. coerce_forced_unit (
821+ coerce. coerce_forced_unit (
820822 self ,
821823 & self . misc ( sp) ,
822824 & mut |err| {
@@ -825,19 +827,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
825827 if expected_ty == self . tcx . types . bool {
826828 // If this is caused by a missing `let` in a `while let`,
827829 // 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 , |_| {
838853 err. downgrade_to_delayed_bug ( ) ;
839- }
840- _ => { }
854+ } )
841855 }
842856 }
843857 }
@@ -851,9 +865,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
851865 } ,
852866 false ,
853867 ) ;
868+ }
854869 }
855- }
856- } ) ;
870+ } ) ;
857871
858872 if ctxt. may_break {
859873 // If we can break from the block, then the block's exit is always reachable
0 commit comments