@@ -541,17 +541,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
541
541
} ;
542
542
let mut parent_id = self . tcx . hir ( ) . parent_id ( expr. hir_id ) ;
543
543
let mut parent;
544
- loop {
544
+ ' outer : loop {
545
545
// Climb the HIR tree to see if the current `Expr` is part of a `break;` statement.
546
- let Some ( hir:: Node :: Expr ( p) ) = self . tcx . hir ( ) . find ( parent_id) else {
546
+ let Some (
547
+ hir:: Node :: Stmt ( hir:: Stmt { kind : hir:: StmtKind :: Semi ( & ref p) , .. } )
548
+ | hir:: Node :: Expr ( & ref p) ,
549
+ ) = self . tcx . hir ( ) . find ( parent_id)
550
+ else {
547
551
break ;
548
552
} ;
549
553
parent = p;
550
- parent_id = self . tcx . hir ( ) . parent_id ( parent . hir_id ) ;
554
+ parent_id = self . tcx . hir ( ) . parent_id ( parent_id ) ;
551
555
let hir:: ExprKind :: Break ( destination, _) = parent. kind else {
552
556
continue ;
553
557
} ;
554
- let mut parent_id = parent. hir_id ;
558
+ let mut parent_id = parent_id;
559
+ let mut direct = false ;
555
560
loop {
556
561
// Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
557
562
let parent = match self . tcx . hir ( ) . find ( parent_id) {
@@ -567,14 +572,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
567
572
parent_id = self . tcx . hir ( ) . parent_id ( * hir_id) ;
568
573
parent
569
574
}
570
- Some ( hir:: Node :: Block ( hir :: Block { .. } ) ) => {
575
+ Some ( hir:: Node :: Block ( _ ) ) => {
571
576
parent_id = self . tcx . hir ( ) . parent_id ( parent_id) ;
572
577
parent
573
578
}
574
579
_ => break ,
575
580
} ;
581
+ if let hir:: ExprKind :: Loop ( ..) = parent. kind {
582
+ // When you have `'a: loop { break; }`, the `break` corresponds to the labeled
583
+ // loop, so we need to account for that.
584
+ direct = !direct;
585
+ }
576
586
if let hir:: ExprKind :: Loop ( _, label, _, span) = parent. kind
577
- && destination. label == label
587
+ && ( destination. label == label || direct )
578
588
{
579
589
if let Some ( ( reason_span, message) ) =
580
590
self . maybe_get_coercion_reason ( parent_id, parent. span )
@@ -588,20 +598,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
588
598
// Locate all other `break` statements within the same `loop` that might
589
599
// have affected inference.
590
600
struct FindBreaks < ' tcx > {
591
- destination : hir :: Destination ,
601
+ label : Option < rustc_ast :: Label > ,
592
602
uses : Vec < & ' tcx hir:: Expr < ' tcx > > ,
593
603
}
594
604
impl < ' tcx > Visitor < ' tcx > for FindBreaks < ' tcx > {
595
605
fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr < ' tcx > ) {
596
606
if let hir:: ExprKind :: Break ( destination, _) = ex. kind
597
- && self . destination . label == destination. label
607
+ && self . label == destination. label
598
608
{
599
609
self . uses . push ( ex) ;
600
610
}
601
611
hir:: intravisit:: walk_expr ( self , ex) ;
602
612
}
603
613
}
604
- let mut expr_finder = FindBreaks { destination , uses : vec ! [ ] } ;
614
+ let mut expr_finder = FindBreaks { label , uses : vec ! [ ] } ;
605
615
expr_finder. visit_expr ( parent) ;
606
616
for ex in expr_finder. uses {
607
617
let hir:: ExprKind :: Break ( _, val) = ex. kind else {
@@ -624,7 +634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
624
634
}
625
635
}
626
636
}
627
- break ;
637
+ break ' outer ;
628
638
}
629
639
}
630
640
}
0 commit comments