@@ -541,17 +541,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
541541 } ;
542542 let mut parent_id = self . tcx . hir ( ) . parent_id ( expr. hir_id ) ;
543543 let mut parent;
544- loop {
544+ ' outer : loop {
545545 // 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 {
547551 break ;
548552 } ;
549553 parent = p;
550- parent_id = self . tcx . hir ( ) . parent_id ( parent . hir_id ) ;
554+ parent_id = self . tcx . hir ( ) . parent_id ( parent_id ) ;
551555 let hir:: ExprKind :: Break ( destination, _) = parent. kind else {
552556 continue ;
553557 } ;
554- let mut parent_id = parent. hir_id ;
558+ let mut parent_id = parent_id;
559+ let mut direct = false ;
555560 loop {
556561 // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
557562 let parent = match self . tcx . hir ( ) . find ( parent_id) {
@@ -567,14 +572,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
567572 parent_id = self . tcx . hir ( ) . parent_id ( * hir_id) ;
568573 parent
569574 }
570- Some ( hir:: Node :: Block ( hir :: Block { .. } ) ) => {
575+ Some ( hir:: Node :: Block ( _ ) ) => {
571576 parent_id = self . tcx . hir ( ) . parent_id ( parent_id) ;
572577 parent
573578 }
574579 _ => break ,
575580 } ;
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+ }
576586 if let hir:: ExprKind :: Loop ( _, label, _, span) = parent. kind
577- && destination. label == label
587+ && ( destination. label == label || direct )
578588 {
579589 if let Some ( ( reason_span, message) ) =
580590 self . maybe_get_coercion_reason ( parent_id, parent. span )
@@ -588,20 +598,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
588598 // Locate all other `break` statements within the same `loop` that might
589599 // have affected inference.
590600 struct FindBreaks < ' tcx > {
591- destination : hir :: Destination ,
601+ label : Option < rustc_ast :: Label > ,
592602 uses : Vec < & ' tcx hir:: Expr < ' tcx > > ,
593603 }
594604 impl < ' tcx > Visitor < ' tcx > for FindBreaks < ' tcx > {
595605 fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr < ' tcx > ) {
596606 if let hir:: ExprKind :: Break ( destination, _) = ex. kind
597- && self . destination . label == destination. label
607+ && self . label == destination. label
598608 {
599609 self . uses . push ( ex) ;
600610 }
601611 hir:: intravisit:: walk_expr ( self , ex) ;
602612 }
603613 }
604- let mut expr_finder = FindBreaks { destination , uses : vec ! [ ] } ;
614+ let mut expr_finder = FindBreaks { label , uses : vec ! [ ] } ;
605615 expr_finder. visit_expr ( parent) ;
606616 for ex in expr_finder. uses {
607617 let hir:: ExprKind :: Break ( _, val) = ex. kind else {
@@ -624,7 +634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
624634 }
625635 }
626636 }
627- break ;
637+ break ' outer ;
628638 }
629639 }
630640 }
0 commit comments