3838
3939use crate :: { ImplTraitPosition , ResolverAstLoweringExt } ;
4040
41- use super :: { ImplTraitContext , LoweringContext , ParamMode } ;
41+ use super :: { ImplTraitContext , LoweringContext , ParamMode , ParenthesizedGenericArgs } ;
4242
4343use ast:: visit:: Visitor ;
4444use hir:: def:: { DefKind , PartialRes , Res } ;
@@ -66,15 +66,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
6666 let Ok ( sig_id) = sig_id else {
6767 return false ;
6868 } ;
69- if let Some ( local_sig_id) = sig_id. as_local ( ) {
70- self . resolver . delegation_fn_sigs [ & local_sig_id] . has_self
71- } else {
72- match self . tcx . def_kind ( sig_id) {
73- DefKind :: Fn => false ,
74- DefKind :: AssocFn => self . tcx . associated_item ( sig_id) . fn_has_self_parameter ,
75- _ => span_bug ! ( span, "unexpected DefKind for delegation item" ) ,
76- }
77- }
69+ self . has_self ( sig_id, span)
7870 }
7971
8072 pub ( crate ) fn lower_delegation (
@@ -105,12 +97,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
10597 span : Span ,
10698 ) -> Result < DefId , ErrorGuaranteed > {
10799 let sig_id = if self . is_in_trait_impl { item_id } else { path_id } ;
108- let sig_id =
109- self . resolver . get_partial_res ( sig_id) . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) ) ;
110- sig_id. ok_or_else ( || {
111- self . tcx
112- . dcx ( )
113- . span_delayed_bug ( span, "LoweringContext: couldn't resolve delegation item" )
100+ self . get_resolution_id ( sig_id, span)
101+ }
102+
103+ fn has_self ( & self , def_id : DefId , span : Span ) -> bool {
104+ if let Some ( local_sig_id) = def_id. as_local ( ) {
105+ self . resolver . delegation_fn_sigs . get ( & local_sig_id) . map_or ( false , |sig| sig. has_self )
106+ } else {
107+ match self . tcx . def_kind ( def_id) {
108+ DefKind :: Fn => false ,
109+ DefKind :: AssocFn => self . tcx . associated_item ( def_id) . fn_has_self_parameter ,
110+ _ => span_bug ! ( span, "unexpected DefKind for delegation item" ) ,
111+ }
112+ }
113+ }
114+
115+ fn get_resolution_id ( & self , node_id : NodeId , span : Span ) -> Result < DefId , ErrorGuaranteed > {
116+ let def_id =
117+ self . resolver . get_partial_res ( node_id) . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) ) ;
118+ def_id. ok_or_else ( || {
119+ self . tcx . dcx ( ) . span_delayed_bug (
120+ span,
121+ format ! ( "LoweringContext: couldn't resolve node {:?} in delegation item" , node_id) ,
122+ )
114123 } )
115124 }
116125
@@ -120,7 +129,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
120129 predicates : & [ ] ,
121130 has_where_clause_predicates : false ,
122131 where_clause_span : span,
123- span : span ,
132+ span,
124133 } )
125134 }
126135
@@ -220,12 +229,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
220229 } ) ) ;
221230
222231 let path = self . arena . alloc ( hir:: Path { span, res : Res :: Local ( param_id) , segments } ) ;
223-
224- hir:: Expr {
225- hir_id : self . next_id ( ) ,
226- kind : hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) ,
227- span,
228- }
232+ self . mk_expr ( hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) , span)
229233 }
230234
231235 fn lower_delegation_body (
@@ -234,25 +238,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
234238 param_count : usize ,
235239 span : Span ,
236240 ) -> BodyId {
237- let path = self . lower_qpath (
238- delegation. id ,
239- & delegation. qself ,
240- & delegation. path ,
241- ParamMode :: Optional ,
242- ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
243- None ,
244- ) ;
245241 let block = delegation. body . as_deref ( ) ;
246242
247243 self . lower_body ( |this| {
248- let mut parameters: Vec < hir:: Param < ' _ > > = Vec :: new ( ) ;
249- let mut args: Vec < hir:: Expr < ' hir > > = Vec :: new ( ) ;
244+ let mut parameters: Vec < hir:: Param < ' _ > > = Vec :: with_capacity ( param_count) ;
245+ let mut args: Vec < hir:: Expr < ' _ > > = Vec :: with_capacity ( param_count) ;
246+ let mut target_expr = None ;
250247
251248 for idx in 0 ..param_count {
252249 let ( param, pat_node_id) = this. generate_param ( span) ;
253250 parameters. push ( param) ;
254251
255- let arg = if let Some ( block) = block
252+ if let Some ( block) = block
256253 && idx == 0
257254 {
258255 let mut self_resolver = SelfResolver {
@@ -261,56 +258,103 @@ impl<'hir> LoweringContext<'_, 'hir> {
261258 self_param_id : pat_node_id,
262259 } ;
263260 self_resolver. visit_block ( block) ;
264- let block = this. lower_block ( block, false ) ;
265- hir:: Expr {
266- hir_id : this. next_id ( ) ,
267- kind : hir:: ExprKind :: Block ( block, None ) ,
268- span : block. span ,
269- }
261+ target_expr = Some ( this. lower_block_noalloc ( block, false ) ) ;
270262 } else {
271263 let pat_hir_id = this. lower_node_id ( pat_node_id) ;
272- this. generate_arg ( pat_hir_id, span)
264+ let arg = this. generate_arg ( pat_hir_id, span) ;
265+ args. push ( arg) ;
273266 } ;
274- args. push ( arg) ;
275267 }
276268
277- let args = self . arena . alloc_from_iter ( args) ;
278- let final_expr = this. generate_call ( path, args) ;
269+ let final_expr = this. finalize_body_lowering ( delegation, target_expr, args, span) ;
279270 ( this. arena . alloc_from_iter ( parameters) , final_expr)
280271 } )
281272 }
282273
283- fn generate_call (
274+ // Generates expression for the resulting body. If possible, `MethodCall` is used
275+ // instead of fully qualified call for the self type coercion. See `consider_candidates`
276+ // for more information.
277+ fn finalize_body_lowering (
284278 & mut self ,
285- path : hir:: QPath < ' hir > ,
286- args : & ' hir [ hir:: Expr < ' hir > ] ,
279+ delegation : & Delegation ,
280+ target_expr : Option < hir:: Block < ' hir > > ,
281+ mut args : Vec < hir:: Expr < ' hir > > ,
282+ span : Span ,
287283 ) -> hir:: Expr < ' hir > {
288- let callee = self . arena . alloc ( hir:: Expr {
289- hir_id : self . next_id ( ) ,
290- kind : hir:: ExprKind :: Path ( path) ,
291- span : path. span ( ) ,
292- } ) ;
284+ let ( stmts, call, block_id) = if self
285+ . get_resolution_id ( delegation. id , span)
286+ . and_then ( |def_id| Ok ( self . has_self ( def_id, span) ) )
287+ . unwrap_or_default ( )
288+ && delegation. qself . is_none ( )
289+ {
290+ let ast_segment = delegation. path . segments . last ( ) . unwrap ( ) ;
291+ let segment = self . lower_path_segment (
292+ delegation. path . span ,
293+ ast_segment,
294+ ParamMode :: Optional ,
295+ ParenthesizedGenericArgs :: Err ,
296+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
297+ None ,
298+ None ,
299+ ) ;
300+ let segment = self . arena . alloc ( segment) ;
301+
302+ let args = & * self . arena . alloc_from_iter ( args) ;
303+ let ( stmts, receiver, args, block_id) = if let Some ( target_expr) = target_expr {
304+ // Use unit type as a receiver if no expression is provided.
305+ let receiver = target_expr. expr . unwrap_or_else ( || {
306+ self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Tup ( & [ ] ) , span) )
307+ } ) ;
308+ ( target_expr. stmts , receiver, args, target_expr. hir_id )
309+ } else {
310+ ( & * self . arena . alloc_from_iter ( [ ] ) , & args[ 0 ] , & args[ 1 ..] , self . next_id ( ) )
311+ } ;
293312
294- let expr = self . arena . alloc ( hir:: Expr {
295- hir_id : self . next_id ( ) ,
296- kind : hir:: ExprKind :: Call ( callee, args) ,
297- span : path. span ( ) ,
298- } ) ;
313+ let method_call_id = self . next_id ( ) ;
314+ if let Some ( traits) = self . resolver . delegation_trait_map . remove ( & delegation. id ) {
315+ self . trait_map . insert ( method_call_id. local_id , traits. into_boxed_slice ( ) ) ;
316+ }
317+
318+ let method_call = self . arena . alloc ( hir:: Expr {
319+ hir_id : method_call_id,
320+ kind : hir:: ExprKind :: MethodCall ( segment, receiver, args, span) ,
321+ span,
322+ } ) ;
323+
324+ ( stmts, method_call, block_id)
325+ } else {
326+ let path = self . lower_qpath (
327+ delegation. id ,
328+ & delegation. qself ,
329+ & delegation. path ,
330+ ParamMode :: Optional ,
331+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
332+ None ,
333+ ) ;
334+
335+ if let Some ( target_expr) = target_expr {
336+ let target_expr = self . arena . alloc ( target_expr) ;
337+ let fst_arg =
338+ self . mk_expr ( hir:: ExprKind :: Block ( target_expr, None ) , target_expr. span ) ;
339+ args. insert ( 0 , fst_arg) ;
340+ }
299341
342+ let args = self . arena . alloc_from_iter ( args) ;
343+ let callee_path = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Path ( path) , span) ) ;
344+
345+ let call = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Call ( callee_path, args) , span) ) ;
346+
347+ ( & * self . arena . alloc_from_iter ( [ ] ) , call, self . next_id ( ) )
348+ } ;
300349 let block = self . arena . alloc ( hir:: Block {
301- stmts : & [ ] ,
302- expr : Some ( expr ) ,
303- hir_id : self . next_id ( ) ,
350+ stmts,
351+ expr : Some ( call ) ,
352+ hir_id : block_id ,
304353 rules : hir:: BlockCheckMode :: DefaultBlock ,
305- span : path . span ( ) ,
354+ span,
306355 targeted_by_break : false ,
307356 } ) ;
308-
309- hir:: Expr {
310- hir_id : self . next_id ( ) ,
311- kind : hir:: ExprKind :: Block ( block, None ) ,
312- span : path. span ( ) ,
313- }
357+ self . mk_expr ( hir:: ExprKind :: Block ( block, None ) , span)
314358 }
315359
316360 fn generate_delegation_error (
@@ -331,11 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
331375 let header = self . generate_header_error ( ) ;
332376 let sig = hir:: FnSig { decl, header, span } ;
333377
334- let body_id = self . lower_body ( |this| {
335- let expr =
336- hir:: Expr { hir_id : this. next_id ( ) , kind : hir:: ExprKind :: Err ( err) , span : span } ;
337- ( & [ ] , expr)
338- } ) ;
378+ let body_id = self . lower_body ( |this| ( & [ ] , this. mk_expr ( hir:: ExprKind :: Err ( err) , span) ) ) ;
339379 DelegationResults { generics, body_id, sig }
340380 }
341381
@@ -347,6 +387,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
347387 abi : abi:: Abi :: Rust ,
348388 }
349389 }
390+
391+ #[ inline]
392+ fn mk_expr ( & mut self , kind : hir:: ExprKind < ' hir > , span : Span ) -> hir:: Expr < ' hir > {
393+ hir:: Expr { hir_id : self . next_id ( ) , kind, span }
394+ }
350395}
351396
352397struct SelfResolver < ' a > {
0 commit comments