@@ -13,6 +13,7 @@ use rustc_span::{ErrorGuaranteed, Span};
13
13
14
14
use std:: collections:: VecDeque ;
15
15
use std:: fmt:: Write ;
16
+ use std:: ops:: ControlFlow ;
16
17
17
18
impl < ' tcx > Value < TyCtxt < ' tcx > > for Ty < ' _ > {
18
19
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<'_>>
130
131
}
131
132
}
132
133
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
+
133
153
impl < ' tcx , T > Value < TyCtxt < ' tcx > > for Result < T , & ' _ ty:: layout:: LayoutError < ' _ > > {
134
154
fn from_cycle_error (
135
155
tcx : TyCtxt < ' tcx > ,
136
156
cycle_error : & CycleError ,
137
157
_guar : ErrorGuaranteed ,
138
158
) -> 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| {
143
162
if cycle[ 0 ] . query . dep_kind == dep_kinds:: layout_of
144
163
&& let Some ( def_id) = cycle[ 0 ] . query . ty_def_id
145
164
&& let Some ( def_id) = def_id. as_local ( )
@@ -204,13 +223,16 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
204
223
) {
205
224
diag. note ( "a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future" ) ;
206
225
}
207
- break ' search diag. emit ( ) ;
226
+
227
+ ControlFlow :: Break ( diag)
208
228
} else {
209
- cycle . rotate_left ( 1 ) ;
229
+ ControlFlow :: Continue ( ( ) )
210
230
}
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 ( ) ;
214
236
215
237
// tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
216
238
// min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
0 commit comments