@@ -46,7 +46,6 @@ use rustc_ast::*;
4646use rustc_attr_parsing:: { AttributeParser , ShouldEmit } ;
4747use rustc_data_structures:: fx:: FxHashSet ;
4848use rustc_errors:: ErrorGuaranteed ;
49- use rustc_hir:: Target ;
5049use rustc_hir:: attrs:: { AttributeKind , InlineAttr } ;
5150use rustc_hir:: def_id:: { DefId , LocalDefId } ;
5251use rustc_middle:: span_bug;
@@ -56,9 +55,14 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
5655use smallvec:: SmallVec ;
5756use { rustc_ast as ast, rustc_hir as hir} ;
5857
59- use super :: { GenericArgsMode , ImplTraitContext , LoweringContext , ParamMode } ;
58+ use crate :: delegation :: generics :: { GenericsGenerationResult , GenericsGenerationResults } ;
6059use crate :: errors:: { CycleInDelegationSignatureResolution , UnresolvedDelegationCallee } ;
61- use crate :: { AllowReturnTypeNotation , ImplTraitPosition , ResolverAstLoweringExt } ;
60+ use crate :: {
61+ AllowReturnTypeNotation , GenericArgsMode , ImplTraitContext , ImplTraitPosition , LoweringContext ,
62+ ParamMode , ResolverAstLoweringExt ,
63+ } ;
64+
65+ mod generics;
6266
6367pub ( crate ) struct DelegationResults < ' hir > {
6468 pub body_id : hir:: BodyId ,
@@ -184,18 +188,48 @@ impl<'hir> LoweringContext<'_, 'hir> {
184188 // we need a function to extract this information
185189 let ( param_count, c_variadic) = self . param_count ( root_function_id) ;
186190
191+ let mut generics = self . lower_delegation_generics (
192+ delegation,
193+ ids. root_function_id ( ) ,
194+ item_id,
195+ span,
196+ ) ;
197+
198+ let body_id = self . lower_delegation_body (
199+ delegation,
200+ item_id,
201+ is_method,
202+ param_count,
203+ & mut generics,
204+ span,
205+ ) ;
206+
187207 // Here we use `delegee_id`, as this id will then be used to calculate parent for generics
188208 // inheritance, and we want this id to point on a delegee, not on the original
189209 // function (see https://github.com/rust-lang/rust/issues/150152#issuecomment-3674834654)
190- let decl = self . lower_delegation_decl ( delegee_id, param_count, c_variadic, span) ;
210+ let decl = self . lower_delegation_decl (
211+ delegee_id,
212+ param_count,
213+ c_variadic,
214+ span,
215+ & generics,
216+ ) ;
191217
192218 // Here we pass `root_function_id` as we want to inherit signature (including consts, async)
193219 // from the root function that started delegation
194220 let sig = self . lower_delegation_sig ( root_function_id, decl, span) ;
195-
196- let body_id = self . lower_delegation_body ( delegation, is_method, param_count, span) ;
197221 let ident = self . lower_ident ( delegation. ident ) ;
198- let generics = self . lower_delegation_generics ( span) ;
222+
223+ let generics = self . arena . alloc ( hir:: Generics {
224+ has_where_clause_predicates : false ,
225+ params : self . arena . alloc_from_iter ( generics. all_params ( item_id, span, self ) ) ,
226+ predicates : self
227+ . arena
228+ . alloc_from_iter ( generics. all_predicates ( item_id, span, self ) ) ,
229+ span,
230+ where_clause_span : span,
231+ } ) ;
232+
199233 DelegationResults { body_id, sig, ident, generics }
200234 }
201235 Err ( err) => self . generate_delegation_error ( err, span, delegation) ,
@@ -295,7 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
295329 self . tcx . sess ,
296330 attrs,
297331 None ,
298- Target :: Fn ,
332+ hir :: Target :: Fn ,
299333 DUMMY_SP ,
300334 DUMMY_NODE_ID ,
301335 Some ( self . tcx . features ( ) ) ,
@@ -364,16 +398,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
364398 self . resolver . get_partial_res ( node_id) . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) )
365399 }
366400
367- fn lower_delegation_generics ( & mut self , span : Span ) -> & ' hir hir:: Generics < ' hir > {
368- self . arena . alloc ( hir:: Generics {
369- params : & [ ] ,
370- predicates : & [ ] ,
371- has_where_clause_predicates : false ,
372- where_clause_span : span,
373- span,
374- } )
375- }
376-
377401 // Function parameter count, including C variadic `...` if present.
378402 fn param_count ( & self , def_id : DefId ) -> ( usize , bool /*c_variadic*/ ) {
379403 if let Some ( local_sig_id) = def_id. as_local ( ) {
@@ -393,6 +417,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
393417 param_count : usize ,
394418 c_variadic : bool ,
395419 span : Span ,
420+ generics : & GenericsGenerationResults < ' hir > ,
396421 ) -> & ' hir hir:: FnDecl < ' hir > {
397422 // The last parameter in C variadic functions is skipped in the signature,
398423 // like during regular lowering.
@@ -405,7 +430,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
405430
406431 let output = self . arena . alloc ( hir:: Ty {
407432 hir_id : self . next_id ( ) ,
408- kind : hir:: TyKind :: InferDelegation ( sig_id, hir:: InferDelegationKind :: Output ) ,
433+ kind : hir:: TyKind :: InferDelegation (
434+ sig_id,
435+ hir:: InferDelegationKind :: Output ( self . arena . alloc ( hir:: DelegationGenerics {
436+ child_args_segment_id : generics. child . args_segment_id ,
437+ parent_args_segment_id : generics. parent . args_segment_id ,
438+ } ) ) ,
439+ ) ,
409440 span,
410441 } ) ;
411442
@@ -460,6 +491,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
460491 abi : sig. abi ,
461492 }
462493 } ;
494+
463495 hir:: FnSig { decl, header, span }
464496 }
465497
@@ -501,6 +533,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
501533 } else {
502534 Symbol :: intern ( & format ! ( "arg{idx}" ) )
503535 } ;
536+
504537 let segments = self . arena . alloc_from_iter ( iter:: once ( hir:: PathSegment {
505538 ident : Ident :: with_dummy_span ( name) ,
506539 hir_id : self . next_id ( ) ,
@@ -516,8 +549,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
516549 fn lower_delegation_body (
517550 & mut self ,
518551 delegation : & Delegation ,
552+ item_id : NodeId ,
519553 is_method : bool ,
520554 param_count : usize ,
555+ generics : & mut GenericsGenerationResults < ' hir > ,
521556 span : Span ,
522557 ) -> BodyId {
523558 let block = delegation. body . as_deref ( ) ;
@@ -548,7 +583,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
548583 args. push ( arg) ;
549584 }
550585
551- let final_expr = this. finalize_body_lowering ( delegation, args, span) ;
586+ let final_expr = this. finalize_body_lowering ( delegation, item_id, args, generics, span) ;
587+
552588 ( this. arena . alloc_from_iter ( parameters) , final_expr)
553589 } )
554590 }
@@ -584,7 +620,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
584620 fn finalize_body_lowering (
585621 & mut self ,
586622 delegation : & Delegation ,
623+ item_id : NodeId ,
587624 args : Vec < hir:: Expr < ' hir > > ,
625+ generics : & mut GenericsGenerationResults < ' hir > ,
588626 span : Span ,
589627 ) -> hir:: Expr < ' hir > {
590628 let args = self . arena . alloc_from_iter ( args) ;
@@ -609,6 +647,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
609647 ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
610648 None ,
611649 ) ;
650+
651+ // FIXME(fn_delegation): proper support for parent generics propagation
652+ // in method call scenario.
653+ let segment = self . process_segment ( item_id, span, & segment, & mut generics. child , false ) ;
612654 let segment = self . arena . alloc ( segment) ;
613655
614656 self . arena . alloc ( hir:: Expr {
@@ -627,9 +669,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
627669 None ,
628670 ) ;
629671
630- let callee_path = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Path ( path) , span) ) ;
672+ let new_path = match path {
673+ hir:: QPath :: Resolved ( ty, path) => {
674+ let mut new_path = path. clone ( ) ;
675+ let len = new_path. segments . len ( ) ;
676+
677+ new_path. segments = self . arena . alloc_from_iter (
678+ new_path. segments . iter ( ) . enumerate ( ) . map ( |( idx, segment) | {
679+ let mut process_segment = |result, add_lifetimes| {
680+ self . process_segment ( item_id, span, segment, result, add_lifetimes)
681+ } ;
682+
683+ if idx + 2 == len {
684+ process_segment ( & mut generics. parent , true )
685+ } else if idx + 1 == len {
686+ process_segment ( & mut generics. child , false )
687+ } else {
688+ segment. clone ( )
689+ }
690+ } ) ,
691+ ) ;
692+
693+ hir:: QPath :: Resolved ( ty, self . arena . alloc ( new_path) )
694+ }
695+ hir:: QPath :: TypeRelative ( ty, segment) => {
696+ let segment =
697+ self . process_segment ( item_id, span, segment, & mut generics. child , false ) ;
698+
699+ hir:: QPath :: TypeRelative ( ty, self . arena . alloc ( segment) )
700+ }
701+ } ;
702+
703+ let callee_path = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Path ( new_path) , span) ) ;
631704 self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Call ( callee_path, args) , span) )
632705 } ;
706+
633707 let block = self . arena . alloc ( hir:: Block {
634708 stmts : & [ ] ,
635709 expr : Some ( call) ,
@@ -642,14 +716,40 @@ impl<'hir> LoweringContext<'_, 'hir> {
642716 self . mk_expr ( hir:: ExprKind :: Block ( block, None ) , span)
643717 }
644718
719+ fn process_segment (
720+ & mut self ,
721+ item_id : NodeId ,
722+ span : Span ,
723+ segment : & hir:: PathSegment < ' hir > ,
724+ result : & mut GenericsGenerationResult < ' hir > ,
725+ add_lifetimes : bool ,
726+ ) -> hir:: PathSegment < ' hir > {
727+ // The first condition is needed when there is SelfAndUserSpecified case,
728+ // we don't want to propagate generics params in this situation.
729+ let segment = if !result. generics . is_user_specified ( )
730+ && let Some ( args) = result
731+ . generics
732+ . into_hir_generics ( self , item_id, span)
733+ . into_generic_args ( self , add_lifetimes, span)
734+ {
735+ hir:: PathSegment { args : Some ( args) , ..segment. clone ( ) }
736+ } else {
737+ segment. clone ( )
738+ } ;
739+
740+ if result. generics . is_user_specified ( ) {
741+ result. args_segment_id = Some ( segment. hir_id ) ;
742+ }
743+
744+ segment
745+ }
746+
645747 fn generate_delegation_error (
646748 & mut self ,
647749 err : ErrorGuaranteed ,
648750 span : Span ,
649751 delegation : & Delegation ,
650752 ) -> DelegationResults < ' hir > {
651- let generics = self . lower_delegation_generics ( span) ;
652-
653753 let decl = self . arena . alloc ( hir:: FnDecl {
654754 inputs : & [ ] ,
655755 output : hir:: FnRetTy :: DefaultReturn ( span) ,
@@ -696,6 +796,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
696796 ( & [ ] , this. mk_expr ( body_expr, span) )
697797 } ) ;
698798
799+ let generics = hir:: Generics :: empty ( ) ;
699800 DelegationResults { ident, generics, body_id, sig }
700801 }
701802
0 commit comments