@@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::{
1414use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt , TypeVisitableExt } ;
1515use rustc_middle:: { bug, span_bug} ;
1616use rustc_span:: def_id:: LocalDefId ;
17- use rustc_span:: { Span , sym} ;
17+ use rustc_span:: { Span , Symbol , sym} ;
1818use rustc_trait_selection:: error_reporting:: traits:: DefIdOrName ;
1919use rustc_trait_selection:: infer:: InferCtxtExt as _;
2020use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -66,7 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6666 arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
6767 expected : Expectation < ' tcx > ,
6868 ) -> Ty < ' tcx > {
69- let original_callee_ty = match & callee_expr. kind {
69+ let expr_ty = match & callee_expr. kind {
7070 hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( ..) | hir:: QPath :: TypeRelative ( ..) ) => self
7171 . check_expr_with_expectation_and_args (
7272 callee_expr,
@@ -76,8 +76,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7676 _ => self . check_expr ( callee_expr) ,
7777 } ;
7878
79- let expr_ty = self . structurally_resolve_type ( call_expr. span , original_callee_ty) ;
80-
8179 let mut autoderef = self . autoderef ( callee_expr. span , expr_ty) ;
8280 let mut result = None ;
8381 while result. is_none ( ) && autoderef. next ( ) . is_some ( ) {
@@ -144,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
144142 autoderef : & Autoderef < ' a , ' tcx > ,
145143 ) -> Option < CallStep < ' tcx > > {
146144 let adjusted_ty =
147- self . structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
145+ self . try_structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
148146
149147 // If the callee is a bare function or a closure, then we're all set.
150148 match * adjusted_ty. kind ( ) {
@@ -241,6 +239,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
241239 return None ;
242240 }
243241
242+ // We only want to confirm a call step here if the infer var
243+ // originated from the defining use of an opaque.
244+ ty:: Infer ( ty:: TyVar ( vid) )
245+ if let Some ( alias_ty) = self . find_sup_as_registered_opaque ( vid) =>
246+ {
247+ return self
248+ . try_overloaded_call_traits_for_alias ( call_expr, alias_ty, arg_exprs)
249+ . map ( |( autoref, method) | {
250+ let mut adjustments = self . adjust_steps ( autoderef) ;
251+ adjustments. extend ( autoref) ;
252+ self . apply_adjustments ( callee_expr, adjustments) ;
253+ CallStep :: Overloaded ( method)
254+ } ) ;
255+ }
256+
257+ ty:: Infer ( _) => {
258+ return None ;
259+ }
260+
244261 ty:: Error ( _) => {
245262 return None ;
246263 }
@@ -305,40 +322,111 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
305322
306323 // Try the options that are least restrictive on the caller first.
307324 for ( opt_trait_def_id, method_name, borrow) in call_trait_choices {
308- let Some ( trait_def_id) = opt_trait_def_id else { continue } ;
325+ if let Some ( confirmed) = self . try_overloaded_call_trait (
326+ call_expr,
327+ adjusted_ty,
328+ opt_arg_exprs,
329+ opt_trait_def_id,
330+ method_name,
331+ borrow,
332+ ) {
333+ return Some ( confirmed) ;
334+ }
335+ }
336+
337+ None
338+ }
339+
340+ fn try_overloaded_call_trait (
341+ & self ,
342+ call_expr : & hir:: Expr < ' _ > ,
343+ call_ty : Ty < ' tcx > ,
344+ opt_arg_exprs : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
345+ opt_trait_def_id : Option < DefId > ,
346+ method_name : Symbol ,
347+ borrow : bool ,
348+ ) -> Option < ( Option < Adjustment < ' tcx > > , MethodCallee < ' tcx > ) > {
349+ let Some ( trait_def_id) = opt_trait_def_id else {
350+ return None ;
351+ } ;
352+
353+ let opt_input_type = opt_arg_exprs. map ( |arg_exprs| {
354+ Ty :: new_tup_from_iter ( self . tcx , arg_exprs. iter ( ) . map ( |e| self . next_ty_var ( e. span ) ) )
355+ } ) ;
356+
357+ let Some ( ok) = self . lookup_method_for_operator (
358+ self . misc ( call_expr. span ) ,
359+ method_name,
360+ trait_def_id,
361+ call_ty,
362+ opt_input_type,
363+ ) else {
364+ return None ;
365+ } ;
366+ let method = self . register_infer_ok_obligations ( ok) ;
367+ let mut autoref = None ;
368+ if borrow {
369+ // Check for &self vs &mut self in the method signature. Since this is either
370+ // the Fn or FnMut trait, it should be one of those.
371+ let ty:: Ref ( _, _, mutbl) = * method. sig . inputs ( ) [ 0 ] . kind ( ) else {
372+ bug ! ( "Expected `FnMut`/`Fn` to take receiver by-ref/by-mut" )
373+ } ;
309374
310- let opt_input_type = opt_arg_exprs. map ( |arg_exprs| {
311- Ty :: new_tup_from_iter ( self . tcx , arg_exprs. iter ( ) . map ( |e| self . next_ty_var ( e. span ) ) )
375+ // For initial two-phase borrow
376+ // deployment, conservatively omit
377+ // overloaded function call ops.
378+ let mutbl = AutoBorrowMutability :: new ( mutbl, AllowTwoPhase :: No ) ;
379+
380+ autoref = Some ( Adjustment {
381+ kind : Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) ,
382+ target : method. sig . inputs ( ) [ 0 ] ,
312383 } ) ;
384+ }
313385
314- if let Some ( ok) = self . lookup_method_for_operator (
315- self . misc ( call_expr. span ) ,
316- method_name,
317- trait_def_id,
318- adjusted_ty,
319- opt_input_type,
320- ) {
321- let method = self . register_infer_ok_obligations ( ok) ;
322- let mut autoref = None ;
323- if borrow {
324- // Check for &self vs &mut self in the method signature. Since this is either
325- // the Fn or FnMut trait, it should be one of those.
326- let ty:: Ref ( _, _, mutbl) = method. sig . inputs ( ) [ 0 ] . kind ( ) else {
327- bug ! ( "Expected `FnMut`/`Fn` to take receiver by-ref/by-mut" )
328- } ;
329-
330- // For initial two-phase borrow
331- // deployment, conservatively omit
332- // overloaded function call ops.
333- let mutbl = AutoBorrowMutability :: new ( * mutbl, AllowTwoPhase :: No ) ;
334-
335- autoref = Some ( Adjustment {
336- kind : Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) ,
337- target : method. sig . inputs ( ) [ 0 ] ,
338- } ) ;
339- }
386+ Some ( ( autoref, method) )
387+ }
340388
341- return Some ( ( autoref, method) ) ;
389+ fn try_overloaded_call_traits_for_alias (
390+ & self ,
391+ call_expr : & ' tcx hir:: Expr < ' tcx > ,
392+ alias_ty : ty:: AliasTy < ' tcx > ,
393+ arg_exprs : & ' tcx [ rustc_hir:: Expr < ' tcx > ] ,
394+ ) -> Option < ( Option < Adjustment < ' tcx > > , MethodCallee < ' tcx > ) > {
395+ let call_ty = alias_ty. to_ty ( self . tcx ) ;
396+
397+ let call_traits = [
398+ ( self . tcx . lang_items ( ) . fn_trait ( ) , sym:: call, true ) ,
399+ ( self . tcx . lang_items ( ) . fn_mut_trait ( ) , sym:: call_mut, true ) ,
400+ ( self . tcx . lang_items ( ) . fn_once_trait ( ) , sym:: call_once, false ) ,
401+ ( self . tcx . lang_items ( ) . async_fn_trait ( ) , sym:: async_call, true ) ,
402+ ( self . tcx . lang_items ( ) . async_fn_mut_trait ( ) , sym:: async_call_mut, true ) ,
403+ ( self . tcx . lang_items ( ) . async_fn_once_trait ( ) , sym:: async_call_once, false ) ,
404+ ] ;
405+ // We only want to try a call trait if it shows up in the bounds
406+ // of the opaque. We confirm the first one that shows up in the
407+ // bounds list, which can lead to inference weirdness but doesn't
408+ // matter today.
409+ for clause in
410+ self . tcx . item_self_bounds ( alias_ty. def_id ) . iter_instantiated ( self . tcx , alias_ty. args )
411+ {
412+ let Some ( poly_trait_ref) = clause. as_trait_clause ( ) else {
413+ continue ;
414+ } ;
415+
416+ if let Some ( & ( opt_trait_def_id, method_name, borrow) ) =
417+ call_traits. iter ( ) . find ( |( trait_def_id, _, _) | {
418+ trait_def_id. is_some_and ( |trait_def_id| trait_def_id == poly_trait_ref. def_id ( ) )
419+ } )
420+ && let Some ( confirmed) = self . try_overloaded_call_trait (
421+ call_expr,
422+ call_ty,
423+ Some ( arg_exprs) ,
424+ opt_trait_def_id,
425+ method_name,
426+ borrow,
427+ )
428+ {
429+ return Some ( confirmed) ;
342430 }
343431 }
344432
0 commit comments