@@ -530,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
530
530
531
531
// When encountering a type error on the value of a `break`, try to point at the reason for the
532
532
// expected type.
533
- fn annotate_loop_expected_due_to_inference (
533
+ pub fn annotate_loop_expected_due_to_inference (
534
534
& self ,
535
535
err : & mut Diagnostic ,
536
536
expr : & hir:: Expr < ' _ > ,
@@ -540,11 +540,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
540
540
return ;
541
541
} ;
542
542
let mut parent_id = self . tcx . hir ( ) . parent_id ( expr. hir_id ) ;
543
+ let mut parent;
543
544
loop {
544
545
// 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 {
546
547
break ;
547
548
} ;
549
+ parent = p;
548
550
parent_id = self . tcx . hir ( ) . parent_id ( parent. hir_id ) ;
549
551
let hir:: ExprKind :: Break ( destination, _) = parent. kind else {
550
552
continue ;
@@ -582,6 +584,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
582
584
span,
583
585
format ! ( "this loop is expected to be of type `{expected}`" ) ,
584
586
) ;
587
+ } else {
588
+ // Locate all the usages of the relevant binding.
589
+ struct FindBreaks < ' tcx > {
590
+ destination : hir:: Destination ,
591
+ uses : Vec < & ' tcx hir:: Expr < ' tcx > > ,
592
+ }
593
+ impl < ' tcx > Visitor < ' tcx > for FindBreaks < ' tcx > {
594
+ fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr < ' tcx > ) {
595
+ if let hir:: ExprKind :: Break ( destination, _) = ex. kind
596
+ && self . destination . label == destination. label
597
+ {
598
+ self . uses . push ( ex) ;
599
+ }
600
+ hir:: intravisit:: walk_expr ( self , ex) ;
601
+ }
602
+ }
603
+ let mut expr_finder = FindBreaks { destination, uses : vec ! [ ] } ;
604
+ expr_finder. visit_expr ( parent) ;
605
+ for ex in expr_finder. uses {
606
+ info ! ( ?ex) ;
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
+ }
585
626
}
586
627
break ;
587
628
}
0 commit comments