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 } ;
@@ -245,12 +245,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
245245 self . lower_body ( |this| {
246246 let mut parameters: Vec < hir:: Param < ' _ > > = Vec :: with_capacity ( param_count) ;
247247 let mut args: Vec < hir:: Expr < ' _ > > = Vec :: with_capacity ( param_count) ;
248+ let mut target_expr = None ;
248249
249250 for idx in 0 ..param_count {
250251 let ( param, pat_node_id) = this. generate_param ( span) ;
251252 parameters. push ( param) ;
252253
253- let arg = if let Some ( block) = block
254+ if let Some ( block) = block
254255 && idx == 0
255256 {
256257 let mut self_resolver = SelfResolver {
@@ -259,44 +260,105 @@ impl<'hir> LoweringContext<'_, 'hir> {
259260 self_param_id : pat_node_id,
260261 } ;
261262 self_resolver. visit_block ( block) ;
262- let block = this. lower_block ( block, false ) ;
263- this. mk_expr ( hir:: ExprKind :: Block ( block, None ) , block. span )
263+ let mut block = this. lower_block_noalloc ( block, false ) ;
264+ if block. expr . is_none ( ) {
265+ let pat_hir_id = this. lower_node_id ( pat_node_id) ;
266+ let arg = & * this. arena . alloc ( this. generate_arg ( pat_hir_id, span) ) ;
267+ // Use `self` as a first argument if no expression is provided.
268+ block. expr = Some ( arg) ;
269+ }
270+ target_expr = Some ( block) ;
264271 } else {
265272 let pat_hir_id = this. lower_node_id ( pat_node_id) ;
266- this. generate_arg ( pat_hir_id, span)
273+ let arg = this. generate_arg ( pat_hir_id, span) ;
274+ args. push ( arg) ;
267275 } ;
268- args. push ( arg) ;
269276 }
270277
271- let final_expr = this. finalize_body_lowering ( delegation, args, span) ;
278+ let final_expr = this. finalize_body_lowering ( delegation, target_expr , args, span) ;
272279 ( this. arena . alloc_from_iter ( parameters) , final_expr)
273280 } )
274281 }
275282
276- // Generates fully qualified call for the resulting body.
283+ // Generates expression for the resulting body. If possible, `MethodCall` is used
284+ // instead of fully qualified call for the self type coercion.
277285 fn finalize_body_lowering (
278286 & mut self ,
279287 delegation : & Delegation ,
280- args : Vec < hir:: Expr < ' hir > > ,
288+ target_expr : Option < hir:: Block < ' hir > > ,
289+ mut args : Vec < hir:: Expr < ' hir > > ,
281290 span : Span ,
282291 ) -> hir:: Expr < ' hir > {
283- let path = self . lower_qpath (
284- delegation. id ,
285- & delegation. qself ,
286- & delegation. path ,
287- ParamMode :: Optional ,
288- ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
289- None ,
290- ) ;
291-
292- let args = self . arena . alloc_from_iter ( args) ;
293- let path_expr = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Path ( path) , span) ) ;
294- let call = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Call ( path_expr, args) , span) ) ;
292+ let has_generic_args =
293+ delegation. path . segments . iter ( ) . rev ( ) . skip ( 1 ) . any ( |segment| segment. args . is_some ( ) ) ;
294+
295+ let ( stmts, call, block_id) = if self
296+ . get_resolution_id ( delegation. id , span)
297+ . and_then ( |def_id| Ok ( self . has_self ( def_id, span) ) )
298+ . unwrap_or_default ( )
299+ && delegation. qself . is_none ( )
300+ && !has_generic_args
301+ {
302+ let ast_segment = delegation. path . segments . last ( ) . unwrap ( ) ;
303+ let segment = self . lower_path_segment (
304+ delegation. path . span ,
305+ ast_segment,
306+ ParamMode :: Optional ,
307+ ParenthesizedGenericArgs :: Err ,
308+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
309+ None ,
310+ None ,
311+ ) ;
312+ let segment = self . arena . alloc ( segment) ;
313+
314+ let args = & * self . arena . alloc_from_iter ( args) ;
315+ let ( stmts, receiver, args, block_id) = if let Some ( target_expr) = target_expr {
316+ let receiver = target_expr. expr . unwrap ( ) ;
317+ ( Some ( target_expr. stmts ) , receiver, args, target_expr. hir_id )
318+ } else {
319+ ( None , & args[ 0 ] , & args[ 1 ..] , self . next_id ( ) )
320+ } ;
321+
322+ let method_call_id = self . next_id ( ) ;
323+ if let Some ( traits) = self . resolver . trait_map . remove ( & delegation. id ) {
324+ self . trait_map . insert ( method_call_id. local_id , traits. into_boxed_slice ( ) ) ;
325+ }
295326
327+ let method_call = self . arena . alloc ( hir:: Expr {
328+ hir_id : method_call_id,
329+ kind : hir:: ExprKind :: MethodCall ( segment, receiver, args, span) ,
330+ span,
331+ } ) ;
332+
333+ ( stmts, method_call, block_id)
334+ } else {
335+ let path = self . lower_qpath (
336+ delegation. id ,
337+ & delegation. qself ,
338+ & delegation. path ,
339+ ParamMode :: Optional ,
340+ ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
341+ None ,
342+ ) ;
343+
344+ if let Some ( target_expr) = target_expr {
345+ let target_expr = self . arena . alloc ( target_expr) ;
346+ let fst_arg =
347+ self . mk_expr ( hir:: ExprKind :: Block ( target_expr, None ) , target_expr. span ) ;
348+ args. insert ( 0 , fst_arg) ;
349+ }
350+
351+ let args = self . arena . alloc_from_iter ( args) ;
352+ let callee_path = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Path ( path) , span) ) ;
353+
354+ let call = self . arena . alloc ( self . mk_expr ( hir:: ExprKind :: Call ( callee_path, args) , span) ) ;
355+
356+ ( None , call, self . next_id ( ) )
357+ } ;
296358 let block = self . arena . alloc ( hir:: Block {
297- stmts : & [ ] ,
359+ stmts : stmts . unwrap_or ( & [ ] ) ,
298360 expr : Some ( call) ,
299- hir_id : self . next_id ( ) ,
361+ hir_id : block_id ,
300362 rules : hir:: BlockCheckMode :: DefaultBlock ,
301363 span,
302364 targeted_by_break : false ,
0 commit comments