38
38
39
39
use crate :: { ImplTraitPosition , ResolverAstLoweringExt } ;
40
40
41
- use super :: { ImplTraitContext , LoweringContext , ParamMode } ;
41
+ use super :: { ImplTraitContext , LoweringContext , ParamMode , ParenthesizedGenericArgs } ;
42
42
43
43
use ast:: visit:: Visitor ;
44
44
use hir:: def:: { DefKind , PartialRes , Res } ;
@@ -66,17 +66,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
66
66
let Ok ( sig_id) = sig_id else {
67
67
return false ;
68
68
} ;
69
- if let Some ( local_sig_id) = sig_id. as_local ( ) {
70
- // The value may be missing due to recursive delegation.
71
- // Error will be emmited later during HIR ty lowering.
72
- self . resolver . delegation_fn_sigs . get ( & local_sig_id) . map_or ( false , |sig| sig. has_self )
73
- } else {
74
- match self . tcx . def_kind ( sig_id) {
75
- DefKind :: Fn => false ,
76
- DefKind :: AssocFn => self . tcx . associated_item ( sig_id) . fn_has_self_parameter ,
77
- _ => span_bug ! ( span, "unexpected DefKind for delegation item" ) ,
78
- }
79
- }
69
+ self . has_self ( sig_id, span)
80
70
}
81
71
82
72
pub ( crate ) fn lower_delegation (
@@ -107,12 +97,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
107
97
span : Span ,
108
98
) -> Result < DefId , ErrorGuaranteed > {
109
99
let sig_id = if self . is_in_trait_impl { item_id } else { path_id } ;
110
- let sig_id =
111
- self . resolver . get_partial_res ( sig_id) . and_then ( |r| r. expect_full_res ( ) . opt_def_id ( ) ) ;
112
- sig_id. ok_or_else ( || {
113
- self . tcx
114
- . dcx ( )
115
- . 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
+ )
116
123
} )
117
124
}
118
125
@@ -122,7 +129,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
122
129
predicates : & [ ] ,
123
130
has_where_clause_predicates : false ,
124
131
where_clause_span : span,
125
- span : span ,
132
+ span,
126
133
} )
127
134
}
128
135
@@ -222,12 +229,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
222
229
} ) ) ;
223
230
224
231
let path = self . arena . alloc ( hir:: Path { span, res : Res :: Local ( param_id) , segments } ) ;
225
-
226
- hir:: Expr {
227
- hir_id : self . next_id ( ) ,
228
- kind : hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) ,
229
- span,
230
- }
232
+ self . mk_expr ( hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) , span)
231
233
}
232
234
233
235
fn lower_delegation_body (
@@ -236,25 +238,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
236
238
param_count : usize ,
237
239
span : Span ,
238
240
) -> BodyId {
239
- let path = self . lower_qpath (
240
- delegation. id ,
241
- & delegation. qself ,
242
- & delegation. path ,
243
- ParamMode :: Optional ,
244
- ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
245
- None ,
246
- ) ;
247
241
let block = delegation. body . as_deref ( ) ;
248
242
249
243
self . lower_body ( |this| {
250
- let mut parameters: Vec < hir:: Param < ' _ > > = Vec :: new ( ) ;
251
- 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 ;
252
247
253
248
for idx in 0 ..param_count {
254
249
let ( param, pat_node_id) = this. generate_param ( span) ;
255
250
parameters. push ( param) ;
256
251
257
- let arg = if let Some ( block) = block
252
+ if let Some ( block) = block
258
253
&& idx == 0
259
254
{
260
255
let mut self_resolver = SelfResolver {
@@ -263,56 +258,103 @@ impl<'hir> LoweringContext<'_, 'hir> {
263
258
self_param_id : pat_node_id,
264
259
} ;
265
260
self_resolver. visit_block ( block) ;
266
- let block = this. lower_block ( block, false ) ;
267
- hir:: Expr {
268
- hir_id : this. next_id ( ) ,
269
- kind : hir:: ExprKind :: Block ( block, None ) ,
270
- span : block. span ,
271
- }
261
+ target_expr = Some ( this. lower_block_noalloc ( block, false ) ) ;
272
262
} else {
273
263
let pat_hir_id = this. lower_node_id ( pat_node_id) ;
274
- this. generate_arg ( pat_hir_id, span)
264
+ let arg = this. generate_arg ( pat_hir_id, span) ;
265
+ args. push ( arg) ;
275
266
} ;
276
- args. push ( arg) ;
277
267
}
278
268
279
- let args = self . arena . alloc_from_iter ( args) ;
280
- let final_expr = this. generate_call ( path, args) ;
269
+ let final_expr = this. finalize_body_lowering ( delegation, target_expr, args, span) ;
281
270
( this. arena . alloc_from_iter ( parameters) , final_expr)
282
271
} )
283
272
}
284
273
285
- 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 (
286
278
& mut self ,
287
- path : hir:: QPath < ' hir > ,
288
- 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 ,
289
283
) -> hir:: Expr < ' hir > {
290
- let callee = self . arena . alloc ( hir:: Expr {
291
- hir_id : self . next_id ( ) ,
292
- kind : hir:: ExprKind :: Path ( path) ,
293
- span : path. span ( ) ,
294
- } ) ;
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
+ } ;
295
312
296
- let expr = self . arena . alloc ( hir:: Expr {
297
- hir_id : self . next_id ( ) ,
298
- kind : hir:: ExprKind :: Call ( callee, args) ,
299
- span : path. span ( ) ,
300
- } ) ;
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
+ }
301
341
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
+ } ;
302
349
let block = self . arena . alloc ( hir:: Block {
303
- stmts : & [ ] ,
304
- expr : Some ( expr ) ,
305
- hir_id : self . next_id ( ) ,
350
+ stmts,
351
+ expr : Some ( call ) ,
352
+ hir_id : block_id ,
306
353
rules : hir:: BlockCheckMode :: DefaultBlock ,
307
- span : path . span ( ) ,
354
+ span,
308
355
targeted_by_break : false ,
309
356
} ) ;
310
-
311
- hir:: Expr {
312
- hir_id : self . next_id ( ) ,
313
- kind : hir:: ExprKind :: Block ( block, None ) ,
314
- span : path. span ( ) ,
315
- }
357
+ self . mk_expr ( hir:: ExprKind :: Block ( block, None ) , span)
316
358
}
317
359
318
360
fn generate_delegation_error (
@@ -333,11 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
333
375
let header = self . generate_header_error ( ) ;
334
376
let sig = hir:: FnSig { decl, header, span } ;
335
377
336
- let body_id = self . lower_body ( |this| {
337
- let expr =
338
- hir:: Expr { hir_id : this. next_id ( ) , kind : hir:: ExprKind :: Err ( err) , span : span } ;
339
- ( & [ ] , expr)
340
- } ) ;
378
+ let body_id = self . lower_body ( |this| ( & [ ] , this. mk_expr ( hir:: ExprKind :: Err ( err) , span) ) ) ;
341
379
DelegationResults { generics, body_id, sig }
342
380
}
343
381
@@ -349,6 +387,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
349
387
abi : abi:: Abi :: Rust ,
350
388
}
351
389
}
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
+ }
352
395
}
353
396
354
397
struct SelfResolver < ' a > {
0 commit comments