@@ -6,7 +6,7 @@ use rustc_hir as hir;
6
6
use rustc_hir:: def:: { DefKind , Res } ;
7
7
use rustc_middle:: ty:: Representability ;
8
8
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
9
- use rustc_query_system:: query:: CycleError ;
9
+ use rustc_query_system:: query:: { report_cycle , CycleError } ;
10
10
use rustc_query_system:: Value ;
11
11
use rustc_span:: def_id:: LocalDefId ;
12
12
use rustc_span:: { ErrorGuaranteed , Span } ;
@@ -97,7 +97,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
97
97
}
98
98
for info in & cycle_error. cycle {
99
99
if info. query . dep_kind == dep_kinds:: representability_adt_ty
100
- && let Some ( def_id) = info. query . ty_adt_id
100
+ && let Some ( def_id) = info. query . ty_def_id
101
101
&& let Some ( def_id) = def_id. as_local ( )
102
102
&& !item_and_field_ids. iter ( ) . any ( |& ( id, _) | id == def_id)
103
103
{
@@ -131,10 +131,36 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>
131
131
132
132
impl < ' tcx , T > Value < TyCtxt < ' tcx > > for Result < T , & ' _ ty:: layout:: LayoutError < ' _ > > {
133
133
fn from_cycle_error (
134
- _tcx : TyCtxt < ' tcx > ,
135
- _cycle_error : & CycleError ,
136
- guar : ErrorGuaranteed ,
134
+ tcx : TyCtxt < ' tcx > ,
135
+ cycle_error : & CycleError ,
136
+ _guar : ErrorGuaranteed ,
137
137
) -> Self {
138
+ let guar = if cycle_error. cycle [ 0 ] . query . dep_kind == dep_kinds:: layout_of
139
+ && let Some ( def_id) = cycle_error. cycle [ 0 ] . query . ty_def_id
140
+ && let Some ( def_id) = def_id. as_local ( )
141
+ && matches ! ( tcx. def_kind( def_id) , DefKind :: Closure )
142
+ && let Some ( coroutine_kind) = tcx. coroutine_kind ( def_id)
143
+ {
144
+ // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
145
+ // due to interactions between the desugaring into a closure expr and the
146
+ // def_span code. I'm not motivated to fix it, because I tried and it was
147
+ // not working, so just hack around it by grabbing the parent fn's span.
148
+ let span = if coroutine_kind. is_fn_like ( ) {
149
+ tcx. def_span ( tcx. local_parent ( def_id) )
150
+ } else {
151
+ tcx. def_span ( def_id)
152
+ } ;
153
+ struct_span_err ! ( tcx. sess. dcx( ) , span, E0733 , "recursion in an `async fn` requires boxing" )
154
+ . span_label ( span, "recursive `async fn`" )
155
+ . note ( "a recursive `async fn` must be rewritten to return a boxed `dyn Future`" )
156
+ . note (
157
+ "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion" ,
158
+ )
159
+ . emit ( )
160
+ } else {
161
+ report_cycle ( tcx. sess , cycle_error) . emit ( )
162
+ } ;
163
+
138
164
// tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
139
165
// min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
140
166
// tcx.arena.alloc is pretty much equal to leaking).
0 commit comments