@@ -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,14 +131,43 @@ 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 :: Coroutine )
142
+ {
143
+ let hir = tcx. hir ( ) ;
144
+ let coroutine_kind = hir
145
+ . body ( hir. body_owned_by ( def_id) )
146
+ . coroutine_kind
147
+ . expect ( "expected coroutine to have a coroutine_kind" ) ;
148
+ // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
149
+ // due to interactions between the desugaring into a closure expr and the
150
+ // def_span code. I'm not motivated to fix it, because I tried and it was
151
+ // not working, so just hack around it by grabbing the parent fn's span.
152
+ let span = if coroutine_kind. is_fn_like ( ) {
153
+ tcx. def_span ( tcx. local_parent ( def_id) )
154
+ } else {
155
+ tcx. def_span ( def_id)
156
+ } ;
157
+ struct_span_err ! ( tcx. sess, span, E0733 , "recursion in an `async fn` requires boxing" )
158
+ . span_label ( span, "recursive `async fn`" )
159
+ . note ( "a recursive `async fn` must be rewritten to return a boxed `dyn Future`" )
160
+ . note (
161
+ "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion" ,
162
+ )
163
+ . emit ( )
164
+ } else {
165
+ report_cycle ( tcx. sess , cycle_error) . emit ( )
166
+ } ;
167
+
138
168
// tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
139
169
// min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
140
170
// tcx.arena.alloc is pretty much equal to leaking).
141
- // FIXME: `Cycle` should carry the ErrorGuaranteed
142
171
Err ( Box :: leak ( Box :: new ( ty:: layout:: LayoutError :: Cycle ( guar) ) ) )
143
172
}
144
173
}
0 commit comments