@@ -13,6 +13,7 @@ use rustc_span::{ErrorGuaranteed, Span};
1313
1414use std:: collections:: VecDeque ;
1515use std:: fmt:: Write ;
16+ use std:: ops:: ControlFlow ;
1617
1718impl < ' tcx > Value < TyCtxt < ' tcx > > for Ty < ' _ > {
1819 fn from_cycle_error ( tcx : TyCtxt < ' tcx > , _: & CycleError , guar : ErrorGuaranteed ) -> Self {
@@ -130,16 +131,34 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>
130131 }
131132}
132133
134+ // Take a cycle of `Q` and try `try_cycle` on every permutation, falling back to `otherwise`.
135+ fn search_for_cycle_permutation < Q , T > (
136+ cycle : & [ Q ] ,
137+ try_cycle : impl Fn ( & mut VecDeque < & Q > ) -> ControlFlow < T , ( ) > ,
138+ otherwise : impl FnOnce ( ) -> T ,
139+ ) -> T {
140+ let mut cycle: VecDeque < _ > = cycle. iter ( ) . collect ( ) ;
141+ for _ in 0 ..cycle. len ( ) {
142+ match try_cycle ( & mut cycle) {
143+ ControlFlow :: Continue ( _) => {
144+ cycle. rotate_left ( 1 ) ;
145+ }
146+ ControlFlow :: Break ( t) => return t,
147+ }
148+ }
149+
150+ otherwise ( )
151+ }
152+
133153impl < ' tcx , T > Value < TyCtxt < ' tcx > > for Result < T , & ' _ ty:: layout:: LayoutError < ' _ > > {
134154 fn from_cycle_error (
135155 tcx : TyCtxt < ' tcx > ,
136156 cycle_error : & CycleError ,
137157 _guar : ErrorGuaranteed ,
138158 ) -> Self {
139- let mut cycle: VecDeque < _ > = cycle_error. cycle . iter ( ) . collect ( ) ;
140-
141- let guar = ' search: {
142- for _ in 0 ..cycle. len ( ) {
159+ let diag = search_for_cycle_permutation (
160+ & cycle_error. cycle ,
161+ |cycle| {
143162 if cycle[ 0 ] . query . dep_kind == dep_kinds:: layout_of
144163 && let Some ( def_id) = cycle[ 0 ] . query . ty_def_id
145164 && let Some ( def_id) = def_id. as_local ( )
@@ -204,13 +223,16 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
204223 ) {
205224 diag. note ( "a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future" ) ;
206225 }
207- break ' search diag. emit ( ) ;
226+
227+ ControlFlow :: Break ( diag)
208228 } else {
209- cycle . rotate_left ( 1 ) ;
229+ ControlFlow :: Continue ( ( ) )
210230 }
211- }
212- report_cycle ( tcx. sess , cycle_error) . emit ( )
213- } ;
231+ } ,
232+ || report_cycle ( tcx. sess , cycle_error) ,
233+ ) ;
234+
235+ let guar = diag. emit ( ) ;
214236
215237 // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
216238 // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
0 commit comments