@@ -15,7 +15,7 @@ use rustc_middle::ty::adjustment::{
1515use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt , TypeVisitableExt } ;
1616use rustc_middle:: { bug, span_bug} ;
1717use rustc_span:: def_id:: LocalDefId ;
18- use rustc_span:: { Span , sym} ;
18+ use rustc_span:: { Span , Symbol , sym} ;
1919use rustc_target:: spec:: { AbiMap , AbiMapping } ;
2020use rustc_trait_selection:: error_reporting:: traits:: DefIdOrName ;
2121use rustc_trait_selection:: infer:: InferCtxtExt as _;
@@ -78,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7878 _ => self . check_expr ( callee_expr) ,
7979 } ;
8080
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) ;
8282
8383 let mut autoderef = self . autoderef ( callee_expr. span , expr_ty) ;
8484 let mut result = None ;
@@ -200,7 +200,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
200200 arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
201201 autoderef : & Autoderef < ' a , ' tcx > ,
202202 ) -> 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 ( ) ) ;
204205
205206 // If the callee is a function pointer or a closure, then we're all set.
206207 match * adjusted_ty. kind ( ) {
@@ -297,6 +298,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
297298 return None ;
298299 }
299300
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+
300325 ty:: Error ( _) => {
301326 return None ;
302327 }
@@ -363,38 +388,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
363388 for ( opt_trait_def_id, method_name, borrow) in call_trait_choices {
364389 let Some ( trait_def_id) = opt_trait_def_id else { continue } ;
365390
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,
374393 adjusted_ty,
375- opt_input_type,
394+ opt_arg_exprs,
395+ trait_def_id,
396+ method_name,
397+ borrow,
376398 ) {
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+ }
396447
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+ }
398489 }
399490 }
400491
0 commit comments