@@ -9,10 +9,10 @@ use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
99use rustc_hir as hir;
1010use rustc_hir:: def:: { DefKind , Res } ;
1111use rustc_middle:: dep_graph:: DepKind ;
12+ use rustc_middle:: queries:: QueryVTables ;
1213use rustc_middle:: query:: CycleError ;
1314use rustc_middle:: query:: erase:: erase_val;
1415use rustc_middle:: query:: plumbing:: CyclePlaceholder ;
15- use rustc_middle:: queries:: QueryVTables ;
1616use rustc_middle:: ty:: layout:: { LayoutError , TyAndLayout } ;
1717use rustc_middle:: ty:: { self , Representability , Ty , TyCtxt } ;
1818use rustc_middle:: { bug, span_bug} ;
@@ -42,102 +42,106 @@ pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) {
4242 |tcx, cycle, guar| erase_val ( layout_of ( tcx, cycle, guar) ) ;
4343}
4444
45- pub ( crate ) fn default < ' tcx > ( tcx : TyCtxt < ' tcx > , cycle_error : CycleError , query_name : & str ) -> ! {
46- let Some ( guar) = tcx. sess . dcx ( ) . has_errors ( ) else {
47- bug ! (
48- "`from_cycle_error_default` on query `{query_name}` called without errors: {:#?}" ,
49- cycle_error. cycle,
50- ) ;
51- } ;
52- guar. raise_fatal ( )
53- }
45+ pub ( crate ) fn default < ' tcx > ( tcx : TyCtxt < ' tcx > , cycle_error : CycleError , query_name : & str ) -> ! {
46+ let Some ( guar) = tcx. sess . dcx ( ) . has_errors ( ) else {
47+ bug ! (
48+ "`from_cycle_error_default` on query `{query_name}` called without errors: {:#?}" ,
49+ cycle_error. cycle,
50+ ) ;
51+ } ;
52+ guar. raise_fatal ( )
53+ }
5454
55- fn fn_sig < ' tcx > ( tcx : TyCtxt < ' tcx > , cycle_error : CycleError , guar : ErrorGuaranteed ) -> ty:: EarlyBinder < ' tcx , ty:: PolyFnSig < ' tcx > > {
56- let err = Ty :: new_error ( tcx, guar) ;
55+ fn fn_sig < ' tcx > (
56+ tcx : TyCtxt < ' tcx > ,
57+ cycle_error : CycleError ,
58+ guar : ErrorGuaranteed ,
59+ ) -> ty:: EarlyBinder < ' tcx , ty:: PolyFnSig < ' tcx > > {
60+ let err = Ty :: new_error ( tcx, guar) ;
5761
58- let arity = if let Some ( info) = cycle_error. cycle . get ( 0 )
59- && info. frame . dep_kind == DepKind :: fn_sig
60- && let Some ( def_id) = info. frame . def_id
61- && let Some ( node) = tcx. hir_get_if_local ( def_id)
62- && let Some ( sig) = node. fn_sig ( )
63- {
64- sig. decl . inputs . len ( )
65- } else {
66- tcx. dcx ( ) . abort_if_errors ( ) ;
67- unreachable ! ( )
68- } ;
62+ let arity = if let Some ( info) = cycle_error. cycle . get ( 0 )
63+ && info. frame . dep_kind == DepKind :: fn_sig
64+ && let Some ( def_id) = info. frame . def_id
65+ && let Some ( node) = tcx. hir_get_if_local ( def_id)
66+ && let Some ( sig) = node. fn_sig ( )
67+ {
68+ sig. decl . inputs . len ( )
69+ } else {
70+ tcx. dcx ( ) . abort_if_errors ( ) ;
71+ unreachable ! ( )
72+ } ;
6973
70- ty:: EarlyBinder :: bind ( ty:: Binder :: dummy ( tcx. mk_fn_sig (
71- std:: iter:: repeat_n ( err, arity) ,
72- err,
73- false ,
74- rustc_hir:: Safety :: Safe ,
75- rustc_abi:: ExternAbi :: Rust ,
76- ) ) )
77- }
74+ ty:: EarlyBinder :: bind ( ty:: Binder :: dummy ( tcx. mk_fn_sig (
75+ std:: iter:: repeat_n ( err, arity) ,
76+ err,
77+ false ,
78+ rustc_hir:: Safety :: Safe ,
79+ rustc_abi:: ExternAbi :: Rust ,
80+ ) ) )
81+ }
7882
79- fn check_representability < ' tcx > (
80- tcx : TyCtxt < ' tcx > ,
81- cycle_error : CycleError ,
82- _guar : ErrorGuaranteed ,
83- ) -> Representability {
84- let mut item_and_field_ids = Vec :: new ( ) ;
85- let mut representable_ids = FxHashSet :: default ( ) ;
86- for info in & cycle_error. cycle {
87- if info. frame . dep_kind == DepKind :: check_representability
88- && let Some ( field_id) = info. frame . def_id
89- && let Some ( field_id) = field_id. as_local ( )
90- && let Some ( DefKind :: Field ) = info. frame . info . def_kind
91- {
92- let parent_id = tcx. parent ( field_id. to_def_id ( ) ) ;
93- let item_id = match tcx. def_kind ( parent_id) {
94- DefKind :: Variant => tcx. parent ( parent_id) ,
95- _ => parent_id,
96- } ;
97- item_and_field_ids. push ( ( item_id. expect_local ( ) , field_id) ) ;
98- }
83+ fn check_representability < ' tcx > (
84+ tcx : TyCtxt < ' tcx > ,
85+ cycle_error : CycleError ,
86+ _guar : ErrorGuaranteed ,
87+ ) -> Representability {
88+ let mut item_and_field_ids = Vec :: new ( ) ;
89+ let mut representable_ids = FxHashSet :: default ( ) ;
90+ for info in & cycle_error. cycle {
91+ if info. frame . dep_kind == DepKind :: check_representability
92+ && let Some ( field_id) = info. frame . def_id
93+ && let Some ( field_id) = field_id. as_local ( )
94+ && let Some ( DefKind :: Field ) = info. frame . info . def_kind
95+ {
96+ let parent_id = tcx. parent ( field_id. to_def_id ( ) ) ;
97+ let item_id = match tcx. def_kind ( parent_id) {
98+ DefKind :: Variant => tcx. parent ( parent_id) ,
99+ _ => parent_id,
100+ } ;
101+ item_and_field_ids. push ( ( item_id. expect_local ( ) , field_id) ) ;
99102 }
100- for info in & cycle_error . cycle {
101- if info . frame . dep_kind == DepKind :: check_representability_adt_ty
102- && let Some ( def_id ) = info. frame . def_id_for_ty_in_cycle
103- && let Some ( def_id) = def_id . as_local ( )
104- && !item_and_field_ids . iter ( ) . any ( | & ( id , _ ) | id == def_id)
105- {
106- representable_ids . insert ( def_id ) ;
107- }
103+ }
104+ for info in & cycle_error . cycle {
105+ if info. frame . dep_kind == DepKind :: check_representability_adt_ty
106+ && let Some ( def_id) = info . frame . def_id_for_ty_in_cycle
107+ && let Some ( def_id ) = def_id. as_local ( )
108+ && !item_and_field_ids . iter ( ) . any ( | & ( id , _ ) | id == def_id )
109+ {
110+ representable_ids . insert ( def_id ) ;
108111 }
109- // We used to continue here, but the cycle error printed next is actually less useful than
110- // the error produced by `recursive_type_error`.
111- let guar = recursive_type_error ( tcx, item_and_field_ids, & representable_ids) ;
112- guar. raise_fatal ( )
113112 }
113+ // We used to continue here, but the cycle error printed next is actually less useful than
114+ // the error produced by `recursive_type_error`.
115+ let guar = recursive_type_error ( tcx, item_and_field_ids, & representable_ids) ;
116+ guar. raise_fatal ( )
117+ }
114118
115- fn variances_of < ' tcx > (
116- tcx : TyCtxt < ' tcx > ,
117- cycle_error : CycleError ,
118- _guar : ErrorGuaranteed ,
119- ) -> & ' tcx [ ty:: Variance ] {
120- search_for_cycle_permutation (
121- & cycle_error. cycle ,
122- |cycle| {
123- if let Some ( info) = cycle. get ( 0 )
124- && info. frame . dep_kind == DepKind :: variances_of
125- && let Some ( def_id) = info. frame . def_id
126- {
127- let n = tcx. generics_of ( def_id) . own_params . len ( ) ;
128- ControlFlow :: Break ( tcx. arena . alloc_from_iter ( iter:: repeat_n ( ty:: Bivariant , n) ) )
129- } else {
130- ControlFlow :: Continue ( ( ) )
131- }
132- } ,
133- || {
134- span_bug ! (
135- cycle_error. usage. as_ref( ) . unwrap( ) . 0 ,
136- "only `variances_of` returns `&[ty::Variance]`"
137- )
138- } ,
139- )
140- }
119+ fn variances_of < ' tcx > (
120+ tcx : TyCtxt < ' tcx > ,
121+ cycle_error : CycleError ,
122+ _guar : ErrorGuaranteed ,
123+ ) -> & ' tcx [ ty:: Variance ] {
124+ search_for_cycle_permutation (
125+ & cycle_error. cycle ,
126+ |cycle| {
127+ if let Some ( info) = cycle. get ( 0 )
128+ && info. frame . dep_kind == DepKind :: variances_of
129+ && let Some ( def_id) = info. frame . def_id
130+ {
131+ let n = tcx. generics_of ( def_id) . own_params . len ( ) ;
132+ ControlFlow :: Break ( tcx. arena . alloc_from_iter ( iter:: repeat_n ( ty:: Bivariant , n) ) )
133+ } else {
134+ ControlFlow :: Continue ( ( ) )
135+ }
136+ } ,
137+ || {
138+ span_bug ! (
139+ cycle_error. usage. as_ref( ) . unwrap( ) . 0 ,
140+ "only `variances_of` returns `&[ty::Variance]`"
141+ )
142+ } ,
143+ )
144+ }
141145
142146// Take a cycle of `Q` and try `try_cycle` on every permutation, falling back to `otherwise`.
143147fn search_for_cycle_permutation < Q , T > (
@@ -158,90 +162,89 @@ fn search_for_cycle_permutation<Q, T>(
158162 otherwise ( )
159163}
160164
161- fn layout_of < ' tcx > (
162- tcx : TyCtxt < ' tcx > ,
163- cycle_error : CycleError ,
164- _guar : ErrorGuaranteed ,
165- ) -> Result < TyAndLayout < ' tcx > , & ' tcx ty:: layout:: LayoutError < ' tcx > > {
166- let diag = search_for_cycle_permutation (
167- & cycle_error. cycle ,
168- |cycle| {
169- if cycle[ 0 ] . frame . dep_kind == DepKind :: layout_of
170- && let Some ( def_id) = cycle[ 0 ] . frame . def_id_for_ty_in_cycle
171- && let Some ( def_id) = def_id. as_local ( )
172- && let def_kind = tcx. def_kind ( def_id)
173- && matches ! ( def_kind, DefKind :: Closure )
174- && let Some ( coroutine_kind) = tcx. coroutine_kind ( def_id)
175- {
176- // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
177- // due to interactions between the desugaring into a closure expr and the
178- // def_span code. I'm not motivated to fix it, because I tried and it was
179- // not working, so just hack around it by grabbing the parent fn's span.
180- let span = if coroutine_kind. is_fn_like ( ) {
181- tcx. def_span ( tcx. local_parent ( def_id) )
182- } else {
183- tcx. def_span ( def_id)
165+ fn layout_of < ' tcx > (
166+ tcx : TyCtxt < ' tcx > ,
167+ cycle_error : CycleError ,
168+ _guar : ErrorGuaranteed ,
169+ ) -> Result < TyAndLayout < ' tcx > , & ' tcx ty:: layout:: LayoutError < ' tcx > > {
170+ let diag = search_for_cycle_permutation (
171+ & cycle_error. cycle ,
172+ |cycle| {
173+ if cycle[ 0 ] . frame . dep_kind == DepKind :: layout_of
174+ && let Some ( def_id) = cycle[ 0 ] . frame . def_id_for_ty_in_cycle
175+ && let Some ( def_id) = def_id. as_local ( )
176+ && let def_kind = tcx. def_kind ( def_id)
177+ && matches ! ( def_kind, DefKind :: Closure )
178+ && let Some ( coroutine_kind) = tcx. coroutine_kind ( def_id)
179+ {
180+ // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
181+ // due to interactions between the desugaring into a closure expr and the
182+ // def_span code. I'm not motivated to fix it, because I tried and it was
183+ // not working, so just hack around it by grabbing the parent fn's span.
184+ let span = if coroutine_kind. is_fn_like ( ) {
185+ tcx. def_span ( tcx. local_parent ( def_id) )
186+ } else {
187+ tcx. def_span ( def_id)
188+ } ;
189+ let mut diag = struct_span_code_err ! (
190+ tcx. sess. dcx( ) ,
191+ span,
192+ E0733 ,
193+ "recursion in {} {} requires boxing" ,
194+ tcx. def_kind_descr_article( def_kind, def_id. to_def_id( ) ) ,
195+ tcx. def_kind_descr( def_kind, def_id. to_def_id( ) ) ,
196+ ) ;
197+ for ( i, info) in cycle. iter ( ) . enumerate ( ) {
198+ if info. frame . dep_kind != DepKind :: layout_of {
199+ continue ;
200+ }
201+ let Some ( frame_def_id) = info. frame . def_id_for_ty_in_cycle else {
202+ continue ;
184203 } ;
185- let mut diag = struct_span_code_err ! (
186- tcx. sess. dcx( ) ,
187- span,
188- E0733 ,
189- "recursion in {} {} requires boxing" ,
190- tcx. def_kind_descr_article( def_kind, def_id. to_def_id( ) ) ,
191- tcx. def_kind_descr( def_kind, def_id. to_def_id( ) ) ,
192- ) ;
193- for ( i, info) in cycle. iter ( ) . enumerate ( ) {
194- if info. frame . dep_kind != DepKind :: layout_of {
195- continue ;
196- }
197- let Some ( frame_def_id) = info. frame . def_id_for_ty_in_cycle else {
198- continue ;
199- } ;
200- let Some ( frame_coroutine_kind) = tcx. coroutine_kind ( frame_def_id) else {
201- continue ;
202- } ;
203- let frame_span =
204- info. frame . info . default_span ( cycle[ ( i + 1 ) % cycle. len ( ) ] . span ) ;
205- if frame_span. is_dummy ( ) {
206- continue ;
207- }
208- if i == 0 {
209- diag. span_label ( frame_span, "recursive call here" ) ;
210- } else {
211- let coroutine_span: Span = if frame_coroutine_kind. is_fn_like ( ) {
212- tcx. def_span ( tcx. parent ( frame_def_id) )
213- } else {
214- tcx. def_span ( frame_def_id)
215- } ;
216- let mut multispan = MultiSpan :: from_span ( coroutine_span) ;
217- multispan
218- . push_span_label ( frame_span, "...leading to this recursive call" ) ;
219- diag. span_note (
220- multispan,
221- format ! ( "which leads to this {}" , tcx. def_descr( frame_def_id) ) ,
222- ) ;
223- }
204+ let Some ( frame_coroutine_kind) = tcx. coroutine_kind ( frame_def_id) else {
205+ continue ;
206+ } ;
207+ let frame_span =
208+ info. frame . info . default_span ( cycle[ ( i + 1 ) % cycle. len ( ) ] . span ) ;
209+ if frame_span. is_dummy ( ) {
210+ continue ;
224211 }
225- // FIXME: We could report a structured suggestion if we had
226- // enough info here... Maybe we can use a hacky HIR walker.
227- if matches ! (
228- coroutine_kind,
229- hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _)
230- ) {
231- diag. note ( "a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future" ) ;
212+ if i == 0 {
213+ diag. span_label ( frame_span, "recursive call here" ) ;
214+ } else {
215+ let coroutine_span: Span = if frame_coroutine_kind. is_fn_like ( ) {
216+ tcx. def_span ( tcx. parent ( frame_def_id) )
217+ } else {
218+ tcx. def_span ( frame_def_id)
219+ } ;
220+ let mut multispan = MultiSpan :: from_span ( coroutine_span) ;
221+ multispan. push_span_label ( frame_span, "...leading to this recursive call" ) ;
222+ diag. span_note (
223+ multispan,
224+ format ! ( "which leads to this {}" , tcx. def_descr( frame_def_id) ) ,
225+ ) ;
232226 }
233-
234- ControlFlow :: Break ( diag)
235- } else {
236- ControlFlow :: Continue ( ( ) )
237227 }
238- } ,
239- || report_cycle ( tcx. sess , & cycle_error) ,
240- ) ;
228+ // FIXME: We could report a structured suggestion if we had
229+ // enough info here... Maybe we can use a hacky HIR walker.
230+ if matches ! (
231+ coroutine_kind,
232+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _)
233+ ) {
234+ diag. note ( "a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future" ) ;
235+ }
241236
242- let guar = diag. emit ( ) ;
243- Err ( tcx. arena . alloc ( LayoutError :: Cycle ( guar) ) )
244- }
237+ ControlFlow :: Break ( diag)
238+ } else {
239+ ControlFlow :: Continue ( ( ) )
240+ }
241+ } ,
242+ || report_cycle ( tcx. sess , & cycle_error) ,
243+ ) ;
244+
245+ let guar = diag. emit ( ) ;
246+ Err ( tcx. arena . alloc ( LayoutError :: Cycle ( guar) ) )
247+ }
245248
246249// item_and_field_ids should form a cycle where each field contains the
247250// type in the next element in the list
0 commit comments