@@ -6,7 +6,7 @@ use rustc_hir as hir;
66use rustc_hir:: def:: { DefKind , Res } ;
77use rustc_middle:: ty:: Representability ;
88use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
9- use rustc_query_system:: query:: CycleError ;
9+ use rustc_query_system:: query:: { report_cycle , CycleError } ;
1010use rustc_query_system:: Value ;
1111use rustc_span:: def_id:: LocalDefId ;
1212use rustc_span:: { ErrorGuaranteed , Span } ;
@@ -97,7 +97,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
9797 }
9898 for info in & cycle_error. cycle {
9999 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
101101 && let Some ( def_id) = def_id. as_local ( )
102102 && !item_and_field_ids. iter ( ) . any ( |& ( id, _) | id == def_id)
103103 {
@@ -131,10 +131,36 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>
131131
132132impl < ' tcx , T > Value < TyCtxt < ' tcx > > for Result < T , & ' _ ty:: layout:: LayoutError < ' _ > > {
133133 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 ,
137137 ) -> 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+
138164 // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
139165 // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
140166 // tcx.arena.alloc is pretty much equal to leaking).
0 commit comments