@@ -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