@@ -56,6 +56,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
5656use { rustc_ast as ast, rustc_hir as hir} ;
5757
5858use super :: { GenericArgsMode , ImplTraitContext , LoweringContext , ParamMode } ;
59+ use crate :: errors:: UnresolvedDelegationCallee ;
5960use crate :: { AllowReturnTypeNotation , ImplTraitPosition , ResolverAstLoweringExt } ;
6061
6162pub ( crate ) struct DelegationResults < ' hir > {
@@ -120,16 +121,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
120121 & mut self ,
121122 delegation : & Delegation ,
122123 item_id : NodeId ,
123- _is_in_trait_impl : bool ,
124124 ) -> DelegationResults < ' hir > {
125125 let span = self . lower_span ( delegation. path . segments . last ( ) . unwrap ( ) . ident . span ) ;
126126
127- let sig_id = self . get_resolution_id (
127+ let sig_id = self . resolve_callee_sig (
128128 self . resolver
129129 . delegation_resolution_info
130130 . get ( & self . local_def_id ( item_id) )
131131 . unwrap ( )
132- . resolution_id ,
132+ . sig_resolution_id ,
133133 span,
134134 ) ;
135135
@@ -246,44 +246,73 @@ impl<'hir> LoweringContext<'_, 'hir> {
246246 }
247247 }
248248
249- fn get_resolution_id ( & self , mut node_id : NodeId , span : Span ) -> Result < DefId , ErrorGuaranteed > {
250- let create_error = |node_id : NodeId | {
251- self . tcx . dcx ( ) . span_delayed_bug (
252- span,
253- format ! ( "LoweringContext: couldn't resolve node {:?} in delegation item" , node_id) ,
254- )
255- } ;
256-
257- let mut processed: FxHashSet < NodeId > = Default :: default ( ) ;
249+ fn resolve_callee_sig (
250+ & self ,
251+ mut node_id : NodeId ,
252+ span : Span ,
253+ ) -> Result < DefId , ErrorGuaranteed > {
254+ let mut visited: FxHashSet < NodeId > = Default :: default ( ) ;
258255
259256 loop {
260- processed . insert ( node_id) ;
257+ visited . insert ( node_id) ;
261258
262- let def_id = self
263- . resolver
264- . get_partial_res ( node_id)
265- . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) ) ;
259+ let def_id = self . opt_get_partial_res_id ( node_id) ;
266260
261+ // If def_id is in local crate and there is no signature in delegation_fn_sigs
262+ // it means that we refer to another delegation as a callee, so in order to obtain
263+ // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it.
267264 if let Some ( def_id) = def_id
268265 && let Some ( local_id) = def_id. as_local ( )
269266 && !self . resolver . delegation_fn_sigs . contains_key ( & local_id)
270267 {
271268 if let Some ( info) = self . resolver . delegation_resolution_info . get ( & local_id) {
272- node_id = info. resolution_id ;
273- if processed. contains ( & node_id) {
274- return Err ( create_error ( node_id) ) ;
269+ node_id = info. sig_resolution_id ;
270+ if visited. contains ( & node_id) {
271+ // We encountered a cycle in the resolution, or delegation callee refers to non-existent
272+ // entity, in this case emit an error.
273+ return Err ( self . dcx ( ) . emit_err ( UnresolvedDelegationCallee { span } ) ) ;
275274 }
276275
277276 continue ;
278277 } else {
279- return Err ( create_error ( node_id) ) ;
278+ // The LocalDefId for some reason refers not to another delegation, in this case
279+ // we will emit a bug (not an error), as we have to catch such cases on the resolve stage,
280+ // during smart_resolve_path in resolve_delegation.
281+ return Err ( self . tcx . dcx ( ) . span_delayed_bug ( span, format ! (
282+ "There is no information about delegation resolution node id for LocalDefId {:?}" ,
283+ local_id
284+ ) ) ) ;
280285 }
281286 }
282287
283- return def_id. ok_or_else ( || create_error ( node_id) ) ;
288+ // Def id is either None or is from non-local crate, fallback to the original routine.
289+ return self . def_id_or_guaranteed_err ( def_id, node_id, span) ;
284290 }
285291 }
286292
293+ fn opt_get_partial_res_id ( & self , node_id : NodeId ) -> Option < DefId > {
294+ self . resolver . get_partial_res ( node_id) . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) )
295+ }
296+
297+ fn def_id_or_guaranteed_err (
298+ & self ,
299+ def_id : Option < DefId > ,
300+ node_id : NodeId ,
301+ span : Span ,
302+ ) -> Result < DefId , ErrorGuaranteed > {
303+ def_id. ok_or_else ( || {
304+ self . tcx . dcx ( ) . span_delayed_bug (
305+ span,
306+ format ! ( "LoweringContext: couldn't resolve node {:?} in delegation item" , node_id) ,
307+ )
308+ } )
309+ }
310+
311+ fn get_resolution_id ( & mut self , node_id : NodeId , span : Span ) -> Result < DefId , ErrorGuaranteed > {
312+ let def_id = self . opt_get_partial_res_id ( node_id) ;
313+ self . def_id_or_guaranteed_err ( def_id, node_id, span)
314+ }
315+
287316 fn lower_delegation_generics ( & mut self , span : Span ) -> & ' hir hir:: Generics < ' hir > {
288317 self . arena . alloc ( hir:: Generics {
289318 params : & [ ] ,
0 commit comments