@@ -15,7 +15,7 @@ use rustc_middle::ty::adjustment::{
15
15
use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt , TypeVisitableExt } ;
16
16
use rustc_middle:: { bug, span_bug} ;
17
17
use rustc_span:: def_id:: LocalDefId ;
18
- use rustc_span:: { Span , sym} ;
18
+ use rustc_span:: { Span , Symbol , sym} ;
19
19
use rustc_target:: spec:: { AbiMap , AbiMapping } ;
20
20
use rustc_trait_selection:: error_reporting:: traits:: DefIdOrName ;
21
21
use rustc_trait_selection:: infer:: InferCtxtExt as _;
@@ -78,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
78
78
_ => self . check_expr ( callee_expr) ,
79
79
} ;
80
80
81
- let expr_ty = self . structurally_resolve_type ( call_expr. span , original_callee_ty) ;
81
+ let expr_ty = self . try_structurally_resolve_type ( call_expr. span , original_callee_ty) ;
82
82
83
83
let mut autoderef = self . autoderef ( callee_expr. span , expr_ty) ;
84
84
let mut result = None ;
@@ -200,7 +200,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
200
200
arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
201
201
autoderef : & Autoderef < ' a , ' tcx > ,
202
202
) -> Option < CallStep < ' tcx > > {
203
- let adjusted_ty = self . structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( ) ) ;
203
+ let adjusted_ty =
204
+ self . try_structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( ) ) ;
204
205
205
206
// If the callee is a function pointer or a closure, then we're all set.
206
207
match * adjusted_ty. kind ( ) {
@@ -297,6 +298,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
297
298
return None ;
298
299
}
299
300
301
+ ty:: Infer ( ty:: TyVar ( vid) ) => {
302
+ // If we end up with an inference variable which is not the hidden type of
303
+ // an opaque, emit an error.
304
+ let opaque_types = self . opaques_with_sub_unified_hidden_type ( vid) ;
305
+ if opaque_types. is_empty ( ) {
306
+ self . type_must_be_known_at_this_point ( autoderef. span ( ) , adjusted_ty) ;
307
+ return None ;
308
+ } else {
309
+ return self
310
+ . try_overloaded_call_traits_for_alias (
311
+ call_expr,
312
+ adjusted_ty,
313
+ opaque_types,
314
+ arg_exprs,
315
+ )
316
+ . map ( |( autoref, method) | {
317
+ let mut adjustments = self . adjust_steps ( autoderef) ;
318
+ adjustments. extend ( autoref) ;
319
+ self . apply_adjustments ( callee_expr, adjustments) ;
320
+ CallStep :: Overloaded ( method)
321
+ } ) ;
322
+ }
323
+ }
324
+
300
325
ty:: Error ( _) => {
301
326
return None ;
302
327
}
@@ -363,38 +388,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
363
388
for ( opt_trait_def_id, method_name, borrow) in call_trait_choices {
364
389
let Some ( trait_def_id) = opt_trait_def_id else { continue } ;
365
390
366
- let opt_input_type = opt_arg_exprs. map ( |arg_exprs| {
367
- Ty :: new_tup_from_iter ( self . tcx , arg_exprs. iter ( ) . map ( |e| self . next_ty_var ( e. span ) ) )
368
- } ) ;
369
-
370
- if let Some ( ok) = self . lookup_method_for_operator (
371
- self . misc ( call_expr. span ) ,
372
- method_name,
373
- trait_def_id,
391
+ if let Some ( result) = self . try_overloaded_call_trait (
392
+ call_expr,
374
393
adjusted_ty,
375
- opt_input_type,
394
+ opt_arg_exprs,
395
+ trait_def_id,
396
+ method_name,
397
+ borrow,
376
398
) {
377
- let method = self . register_infer_ok_obligations ( ok) ;
378
- let mut autoref = None ;
379
- if borrow {
380
- // Check for &self vs &mut self in the method signature. Since this is either
381
- // the Fn or FnMut trait, it should be one of those.
382
- let ty:: Ref ( _, _, mutbl) = method. sig . inputs ( ) [ 0 ] . kind ( ) else {
383
- bug ! ( "Expected `FnMut`/`Fn` to take receiver by-ref/by-mut" )
384
- } ;
385
-
386
- // For initial two-phase borrow
387
- // deployment, conservatively omit
388
- // overloaded function call ops.
389
- let mutbl = AutoBorrowMutability :: new ( * mutbl, AllowTwoPhase :: No ) ;
390
-
391
- autoref = Some ( Adjustment {
392
- kind : Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) ,
393
- target : method. sig . inputs ( ) [ 0 ] ,
394
- } ) ;
395
- }
399
+ return Some ( result) ;
400
+ }
401
+ }
402
+
403
+ None
404
+ }
405
+
406
+ fn try_overloaded_call_trait (
407
+ & self ,
408
+ call_expr : & hir:: Expr < ' _ > ,
409
+ call_ty : Ty < ' tcx > ,
410
+ opt_arg_exprs : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
411
+ trait_def_id : DefId ,
412
+ method_name : Symbol ,
413
+ borrow : bool ,
414
+ ) -> Option < ( Option < Adjustment < ' tcx > > , MethodCallee < ' tcx > ) > {
415
+ let opt_input_type = opt_arg_exprs. map ( |arg_exprs| {
416
+ Ty :: new_tup_from_iter ( self . tcx , arg_exprs. iter ( ) . map ( |e| self . next_ty_var ( e. span ) ) )
417
+ } ) ;
418
+
419
+ let Some ( ok) = self . lookup_method_for_operator (
420
+ self . misc ( call_expr. span ) ,
421
+ method_name,
422
+ trait_def_id,
423
+ call_ty,
424
+ opt_input_type,
425
+ ) else {
426
+ return None ;
427
+ } ;
428
+ let method = self . register_infer_ok_obligations ( ok) ;
429
+ let mut autoref = None ;
430
+ if borrow {
431
+ // Check for &self vs &mut self in the method signature. Since this is either
432
+ // the Fn or FnMut trait, it should be one of those.
433
+ let ty:: Ref ( _, _, mutbl) = * method. sig . inputs ( ) [ 0 ] . kind ( ) else {
434
+ bug ! ( "Expected `FnMut`/`Fn` to take receiver by-ref/by-mut" )
435
+ } ;
436
+
437
+ // For initial two-phase borrow
438
+ // deployment, conservatively omit
439
+ // overloaded function call ops.
440
+ let mutbl = AutoBorrowMutability :: new ( mutbl, AllowTwoPhase :: No ) ;
441
+
442
+ autoref = Some ( Adjustment {
443
+ kind : Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) ,
444
+ target : method. sig . inputs ( ) [ 0 ] ,
445
+ } ) ;
446
+ }
396
447
397
- return Some ( ( autoref, method) ) ;
448
+ Some ( ( autoref, method) )
449
+ }
450
+
451
+ fn try_overloaded_call_traits_for_alias (
452
+ & self ,
453
+ call_expr : & ' tcx hir:: Expr < ' tcx > ,
454
+ call_ty : Ty < ' tcx > ,
455
+ opaque_types : Vec < ty:: AliasTy < ' tcx > > ,
456
+ arg_exprs : & ' tcx [ rustc_hir:: Expr < ' tcx > ] ,
457
+ ) -> Option < ( Option < Adjustment < ' tcx > > , MethodCallee < ' tcx > ) > {
458
+ let call_traits = [
459
+ ( self . tcx . lang_items ( ) . fn_trait ( ) , sym:: call, true ) ,
460
+ ( self . tcx . lang_items ( ) . fn_mut_trait ( ) , sym:: call_mut, true ) ,
461
+ ( self . tcx . lang_items ( ) . fn_once_trait ( ) , sym:: call_once, false ) ,
462
+ ( self . tcx . lang_items ( ) . async_fn_trait ( ) , sym:: async_call, true ) ,
463
+ ( self . tcx . lang_items ( ) . async_fn_mut_trait ( ) , sym:: async_call_mut, true ) ,
464
+ ( self . tcx . lang_items ( ) . async_fn_once_trait ( ) , sym:: async_call_once, false ) ,
465
+ ] ;
466
+ // Test for iteration order.
467
+ for ( trait_def_id, method_name, borrow) in call_traits {
468
+ let Some ( trait_def_id) = trait_def_id else { continue } ;
469
+ for clause in opaque_types. iter ( ) . flat_map ( |alias_ty| {
470
+ self . tcx
471
+ . item_self_bounds ( alias_ty. def_id )
472
+ . iter_instantiated ( self . tcx , alias_ty. args )
473
+ } ) {
474
+ let Some ( poly_trait_ref) = clause. as_trait_clause ( ) else {
475
+ continue ;
476
+ } ;
477
+ if poly_trait_ref. def_id ( ) == trait_def_id {
478
+ if let Some ( confirmed) = self . try_overloaded_call_trait (
479
+ call_expr,
480
+ call_ty,
481
+ Some ( arg_exprs) ,
482
+ trait_def_id,
483
+ method_name,
484
+ borrow,
485
+ ) {
486
+ return Some ( confirmed) ;
487
+ }
488
+ }
398
489
}
399
490
}
400
491
0 commit comments