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