@@ -530,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
530530
531531 // When encountering a type error on the value of a `break`, try to point at the reason for the
532532 // expected type.
533- fn annotate_loop_expected_due_to_inference (
533+ pub fn annotate_loop_expected_due_to_inference (
534534 & self ,
535535 err : & mut Diagnostic ,
536536 expr : & hir:: Expr < ' _ > ,
@@ -540,11 +540,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
540540 return ;
541541 } ;
542542 let mut parent_id = self . tcx . hir ( ) . parent_id ( expr. hir_id ) ;
543+ let mut parent;
543544 loop {
544545 // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement.
545- let Some ( hir:: Node :: Expr ( parent ) ) = self . tcx . hir ( ) . find ( parent_id) else {
546+ let Some ( hir:: Node :: Expr ( p ) ) = self . tcx . hir ( ) . find ( parent_id) else {
546547 break ;
547548 } ;
549+ parent = p;
548550 parent_id = self . tcx . hir ( ) . parent_id ( parent. hir_id ) ;
549551 let hir:: ExprKind :: Break ( destination, _) = parent. kind else {
550552 continue ;
@@ -582,6 +584,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
582584 span,
583585 format ! ( "this loop is expected to be of type `{expected}`" ) ,
584586 ) ;
587+ } else {
588+ // Locate all other `break` statements within the same `loop` that might
589+ // have affected inference.
590+ struct FindBreaks < ' tcx > {
591+ destination : hir:: Destination ,
592+ uses : Vec < & ' tcx hir:: Expr < ' tcx > > ,
593+ }
594+ impl < ' tcx > Visitor < ' tcx > for FindBreaks < ' tcx > {
595+ fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr < ' tcx > ) {
596+ if let hir:: ExprKind :: Break ( destination, _) = ex. kind
597+ && self . destination . label == destination. label
598+ {
599+ self . uses . push ( ex) ;
600+ }
601+ hir:: intravisit:: walk_expr ( self , ex) ;
602+ }
603+ }
604+ let mut expr_finder = FindBreaks { destination, uses : vec ! [ ] } ;
605+ expr_finder. visit_expr ( parent) ;
606+ for ex in expr_finder. uses {
607+ let hir:: ExprKind :: Break ( _, val) = ex. kind else {
608+ continue ;
609+ } ;
610+ let ty = match val {
611+ Some ( val) => {
612+ match self . typeck_results . borrow ( ) . expr_ty_adjusted_opt ( val) {
613+ None => continue ,
614+ Some ( ty) => ty,
615+ }
616+ }
617+ None => self . tcx . types . unit ,
618+ } ;
619+ if self . can_eq ( self . param_env , ty, expected) {
620+ err. span_label (
621+ ex. span ,
622+ format ! ( "expected because of this `break`" ) ,
623+ ) ;
624+ }
625+ }
585626 }
586627 break ;
587628 }
0 commit comments