@@ -44,22 +44,20 @@ use hir::{BodyId, HirId};
4444use rustc_abi:: ExternAbi ;
4545use rustc_ast as ast;
4646use rustc_ast:: * ;
47- use rustc_data_structures:: fx:: FxHashSet ;
48- use rustc_errors:: ErrorGuaranteed ;
47+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
4948use rustc_hir:: attrs:: { AttributeKind , InlineAttr } ;
50- use rustc_hir:: def_id:: DefId ;
49+ use rustc_hir:: def_id:: { DefId , LocalDefId } ;
5150use rustc_hir:: { self as hir, FnDeclFlags } ;
5251use rustc_middle:: span_bug;
53- use rustc_middle:: ty:: Asyncness ;
52+ use rustc_middle:: ty:: { Asyncness , TyCtxt } ;
5453use rustc_span:: symbol:: kw;
55- use rustc_span:: { Ident , Span , Symbol } ;
56- use smallvec:: SmallVec ;
54+ use rustc_span:: { ErrorGuaranteed , Ident , Span , Symbol } ;
5755
5856use crate :: delegation:: generics:: { GenericsGenerationResult , GenericsGenerationResults } ;
5957use crate :: errors:: { CycleInDelegationSignatureResolution , UnresolvedDelegationCallee } ;
6058use crate :: {
6159 AllowReturnTypeNotation , ImplTraitContext , ImplTraitPosition , LoweringContext , ParamMode ,
62- ResolverAstLoweringExt ,
60+ ResolverAstLoweringExt , index_crate ,
6361} ;
6462
6563mod generics;
@@ -105,6 +103,66 @@ static ATTRS_ADDITIONS: &[AttrAdditionInfo] = &[
105103 } ,
106104] ;
107105
106+ pub ( crate ) fn delegations_resolutions (
107+ tcx : TyCtxt < ' _ > ,
108+ _: ( ) ,
109+ ) -> FxIndexMap < LocalDefId , Result < DefId , ErrorGuaranteed > > {
110+ let krate = tcx. hir_crate ( ( ) ) ;
111+
112+ let ( resolver, ast_crate) = & * krate. delayed_resolver . borrow ( ) ;
113+
114+ // FIXME!!!(fn_delegation): make ast index lifetime same as resolver,
115+ // as it is too bad to reindex whole crate on each delegation lowering.
116+ let ast_index = index_crate ( resolver, ast_crate) ;
117+
118+ let mut result = FxIndexMap :: < LocalDefId , Result < DefId , ErrorGuaranteed > > :: default ( ) ;
119+
120+ for & def_id in & krate. delayed_ids {
121+ let delegation = ast_index[ def_id] . delegation ( ) . expect ( "processing delegations" ) ;
122+ let span = delegation. last_segment_span ( ) ;
123+
124+ if let Some ( info) = resolver. delegation_info ( def_id) {
125+ let res = info. resolution_id . map ( |id| check_for_cycles ( tcx, id, span) . map ( |_| id) ) ;
126+ result. insert ( def_id, res. flatten ( ) ) ;
127+ } else {
128+ tcx. dcx ( ) . span_delayed_bug (
129+ span,
130+ format ! ( "delegation resolution record was not found for {def_id:?}" ) ,
131+ ) ;
132+ }
133+ }
134+
135+ result
136+ }
137+
138+ fn check_for_cycles ( tcx : TyCtxt < ' _ > , mut def_id : DefId , span : Span ) -> Result < ( ) , ErrorGuaranteed > {
139+ let mut visited: FxHashSet < DefId > = Default :: default ( ) ;
140+
141+ let ( resolver, _) = & * tcx. hir_crate ( ( ) ) . delayed_resolver . borrow ( ) ;
142+
143+ loop {
144+ visited. insert ( def_id) ;
145+
146+ // If def_id is in local crate and it corresponds to another delegation
147+ // it means that we refer to another delegation as a callee, so in order to obtain
148+ // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it.
149+ if let Some ( local_id) = def_id. as_local ( )
150+ && let Some ( info) = resolver. delegation_info ( local_id)
151+ && let Ok ( id) = info. resolution_id
152+ {
153+ def_id = id;
154+ if visited. contains ( & def_id) {
155+ return Err ( match visited. len ( ) {
156+ 1 => tcx. dcx ( ) . emit_err ( UnresolvedDelegationCallee { span } ) ,
157+ _ => tcx. dcx ( ) . emit_err ( CycleInDelegationSignatureResolution { span } ) ,
158+ } ) ;
159+ }
160+ } else {
161+ return Ok ( ( ) ) ;
162+ }
163+ }
164+ }
165+
108166impl < ' hir > LoweringContext < ' _ , ' hir > {
109167 fn is_method ( & self , def_id : DefId , span : Span ) -> bool {
110168 match self . tcx . def_kind ( def_id) {
@@ -119,13 +177,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
119177 delegation : & Delegation ,
120178 item_id : NodeId ,
121179 ) -> DelegationResults < ' hir > {
122- let span = self . lower_span ( delegation. path . segments . last ( ) . unwrap ( ) . ident . span ) ;
180+ let span = self . lower_span ( delegation. last_segment_span ( ) ) ;
123181
124- // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356)
125- let sig_id = if let Some ( delegation_info ) = self . resolver . delegation_info ( self . owner . def_id )
126- {
127- self . get_sig_id ( delegation_info . resolution_id , span )
128- } else {
182+ let sig_id = self . tcx . delegations_resolutions ( ( ) ) . get ( & self . owner . def_id ) . copied ( ) ;
183+
184+ // Delegation can be missing from the `delegations_resolutions` table
185+ // in illegal places such as function bodies in extern blocks (see #151356).
186+ let Some ( Ok ( sig_id ) ) = sig_id else {
129187 self . dcx ( ) . span_delayed_bug (
130188 span,
131189 format ! ( "LoweringContext: the delegation {:?} is unresolved" , item_id) ,
@@ -134,49 +192,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
134192 return self . generate_delegation_error ( span, delegation) ;
135193 } ;
136194
137- match sig_id {
138- Ok ( sig_id) => {
139- self . add_attrs_if_needed ( span, sig_id) ;
195+ self . add_attrs_if_needed ( span, sig_id) ;
140196
141- let is_method = self . is_method ( sig_id, span) ;
197+ let is_method = self . is_method ( sig_id, span) ;
142198
143- let ( param_count, c_variadic) = self . param_count ( sig_id) ;
199+ let ( param_count, c_variadic) = self . param_count ( sig_id) ;
144200
145- let mut generics = self . uplift_delegation_generics ( delegation, sig_id, is_method) ;
201+ let mut generics = self . uplift_delegation_generics ( delegation, sig_id, is_method) ;
146202
147- let ( body_id, call_expr_id) = self . lower_delegation_body (
148- delegation,
149- is_method,
150- param_count,
151- & mut generics,
152- span,
153- ) ;
203+ let ( body_id, call_expr_id) =
204+ self . lower_delegation_body ( delegation, is_method, param_count, & mut generics, span) ;
154205
155- let decl = self . lower_delegation_decl (
156- sig_id,
157- param_count,
158- c_variadic,
159- span,
160- & generics,
161- delegation. id ,
162- call_expr_id,
163- ) ;
206+ let decl = self . lower_delegation_decl (
207+ sig_id,
208+ param_count,
209+ c_variadic,
210+ span,
211+ & generics,
212+ delegation. id ,
213+ call_expr_id,
214+ ) ;
164215
165- let sig = self . lower_delegation_sig ( sig_id, decl, span) ;
166- let ident = self . lower_ident ( delegation. ident ) ;
216+ let sig = self . lower_delegation_sig ( sig_id, decl, span) ;
217+ let ident = self . lower_ident ( delegation. ident ) ;
167218
168- let generics = self . arena . alloc ( hir:: Generics {
169- has_where_clause_predicates : false ,
170- params : self . arena . alloc_from_iter ( generics. all_params ( ) ) ,
171- predicates : self . arena . alloc_from_iter ( generics. all_predicates ( ) ) ,
172- span,
173- where_clause_span : span,
174- } ) ;
219+ let generics = self . arena . alloc ( hir:: Generics {
220+ has_where_clause_predicates : false ,
221+ params : self . arena . alloc_from_iter ( generics. all_params ( ) ) ,
222+ predicates : self . arena . alloc_from_iter ( generics. all_predicates ( ) ) ,
223+ span,
224+ where_clause_span : span,
225+ } ) ;
175226
176- DelegationResults { body_id, sig, ident, generics }
177- }
178- Err ( _) => self . generate_delegation_error ( span, delegation) ,
179- }
227+ DelegationResults { body_id, sig, ident, generics }
180228 }
181229
182230 fn add_attrs_if_needed ( & mut self , span : Span , sig_id : DefId ) {
@@ -230,36 +278,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
230278 . collect :: < Vec < _ > > ( )
231279 }
232280
233- fn get_sig_id ( & self , mut def_id : DefId , span : Span ) -> Result < DefId , ErrorGuaranteed > {
234- let mut visited: FxHashSet < DefId > = Default :: default ( ) ;
235- let mut path: SmallVec < [ DefId ; 1 ] > = Default :: default ( ) ;
236-
237- loop {
238- visited. insert ( def_id) ;
239-
240- path. push ( def_id) ;
241-
242- // If def_id is in local crate and it corresponds to another delegation
243- // it means that we refer to another delegation as a callee, so in order to obtain
244- // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it.
245- if let Some ( local_id) = def_id. as_local ( )
246- && let Some ( delegation_info) = self . resolver . delegation_info ( local_id)
247- {
248- def_id = delegation_info. resolution_id ;
249- if visited. contains ( & def_id) {
250- // We encountered a cycle in the resolution, or delegation callee refers to non-existent
251- // entity, in this case emit an error.
252- return Err ( match visited. len ( ) {
253- 1 => self . dcx ( ) . emit_err ( UnresolvedDelegationCallee { span } ) ,
254- _ => self . dcx ( ) . emit_err ( CycleInDelegationSignatureResolution { span } ) ,
255- } ) ;
256- }
257- } else {
258- return Ok ( path[ 0 ] ) ;
259- }
260- }
261- }
262-
263281 fn get_resolution_id ( & self , node_id : NodeId ) -> Option < DefId > {
264282 self . get_partial_res ( node_id) . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) )
265283 }
0 commit comments