11use std:: iter;
22
33use rustc_ast:: util:: parser:: ExprPrecedence ;
4- use rustc_errors:: { Applicability , Diag , ErrorGuaranteed , StashKey } ;
4+ use rustc_errors:: { Applicability , Diag , ErrorGuaranteed } ;
55use rustc_hir:: def:: { self , CtorKind , Namespace , Res } ;
66use rustc_hir:: def_id:: DefId ;
77use rustc_hir:: { self as hir, HirId , LangItem } ;
@@ -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 _;
@@ -58,6 +58,7 @@ enum CallStep<'tcx> {
5858 Overloaded ( MethodCallee < ' tcx > ) ,
5959}
6060
61+ #[ allow( unused) ] // TODO
6162impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
6263 pub ( crate ) fn check_expr_call (
6364 & self ,
@@ -66,7 +67,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6667 arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
6768 expected : Expectation < ' tcx > ,
6869 ) -> Ty < ' tcx > {
69- let original_callee_ty = match & callee_expr. kind {
70+ let expr_ty = match & callee_expr. kind {
7071 hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( ..) | hir:: QPath :: TypeRelative ( ..) ) => self
7172 . check_expr_with_expectation_and_args (
7273 callee_expr,
@@ -76,8 +77,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7677 _ => self . check_expr ( callee_expr) ,
7778 } ;
7879
79- let expr_ty = self . structurally_resolve_type ( call_expr. span , original_callee_ty) ;
80-
8180 let mut autoderef = self . autoderef ( callee_expr. span , expr_ty) ;
8281 let mut result = None ;
8382 while result. is_none ( ) && autoderef. next ( ) . is_some ( ) {
@@ -87,29 +86,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8786
8887 let output = match result {
8988 None => {
90- // Check all of the arg expressions, but with no expectations
91- // since we don't have a signature to compare them to.
92- for arg in arg_exprs {
93- self . check_expr ( arg) ;
94- }
89+ // First report an ambiguity error if possible.
90+ let expr_ty = self . structurally_resolve_type ( call_expr. span , expr_ty) ;
9591
96- if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = & callee_expr. kind
97- && let [ segment] = path. segments
98- {
99- self . dcx ( ) . try_steal_modify_and_emit_err (
100- segment. ident . span ,
101- StashKey :: CallIntoMethod ,
102- |err| {
103- // Try suggesting `foo(a)` -> `a.foo()` if possible.
104- self . suggest_call_as_method (
105- err, segment, arg_exprs, call_expr, expected,
106- ) ;
107- } ,
108- ) ;
109- }
110-
111- let guar = self . report_invalid_callee ( call_expr, callee_expr, expr_ty, arg_exprs) ;
112- Ty :: new_error ( self . tcx , guar)
92+ // this will report an error since original_callee_ty is not a fn
93+ self . confirm_builtin_call ( call_expr, callee_expr, expr_ty, arg_exprs, expected)
11394 }
11495
11596 Some ( CallStep :: Builtin ( callee_ty) ) => {
@@ -144,7 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
144125 autoderef : & Autoderef < ' a , ' tcx > ,
145126 ) -> Option < CallStep < ' tcx > > {
146127 let adjusted_ty =
147- self . structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
128+ self . try_structurally_resolve_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
148129
149130 // If the callee is a bare function or a closure, then we're all set.
150131 match * adjusted_ty. kind ( ) {
@@ -241,6 +222,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
241222 return None ;
242223 }
243224
225+ // We only want to confirm a call step here if the infer var
226+ // originated from the defining use of an opaque.
227+ ty:: Infer ( ty:: TyVar ( vid) )
228+ if let Some ( alias_ty) = self . find_sup_as_registered_opaque ( vid) =>
229+ {
230+ return self
231+ . try_overloaded_call_traits_for_alias ( call_expr, alias_ty, arg_exprs)
232+ . map ( |( autoref, method) | {
233+ let mut adjustments = self . adjust_steps ( autoderef) ;
234+ adjustments. extend ( autoref) ;
235+ self . apply_adjustments ( callee_expr, adjustments) ;
236+ CallStep :: Overloaded ( method)
237+ } ) ;
238+ }
239+
240+ ty:: Infer ( _) => {
241+ return None ;
242+ }
243+
244244 ty:: Error ( _) => {
245245 return None ;
246246 }
@@ -305,40 +305,111 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
305305
306306 // Try the options that are least restrictive on the caller first.
307307 for ( opt_trait_def_id, method_name, borrow) in call_trait_choices {
308- let Some ( trait_def_id) = opt_trait_def_id else { continue } ;
308+ if let Some ( confirmed) = self . try_overloaded_call_trait (
309+ call_expr,
310+ adjusted_ty,
311+ opt_arg_exprs,
312+ opt_trait_def_id,
313+ method_name,
314+ borrow,
315+ ) {
316+ return Some ( confirmed) ;
317+ }
318+ }
309319
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 ) ) )
320+ None
321+ }
322+
323+ fn try_overloaded_call_trait (
324+ & self ,
325+ call_expr : & hir:: Expr < ' _ > ,
326+ call_ty : Ty < ' tcx > ,
327+ opt_arg_exprs : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
328+ opt_trait_def_id : Option < DefId > ,
329+ method_name : Symbol ,
330+ borrow : bool ,
331+ ) -> Option < ( Option < Adjustment < ' tcx > > , MethodCallee < ' tcx > ) > {
332+ let Some ( trait_def_id) = opt_trait_def_id else {
333+ return None ;
334+ } ;
335+
336+ let opt_input_type = opt_arg_exprs. map ( |arg_exprs| {
337+ Ty :: new_tup_from_iter ( self . tcx , arg_exprs. iter ( ) . map ( |e| self . next_ty_var ( e. span ) ) )
338+ } ) ;
339+
340+ let Some ( ok) = self . lookup_method_for_operator (
341+ self . misc ( call_expr. span ) ,
342+ method_name,
343+ trait_def_id,
344+ call_ty,
345+ opt_input_type,
346+ ) else {
347+ return None ;
348+ } ;
349+ let method = self . register_infer_ok_obligations ( ok) ;
350+ let mut autoref = None ;
351+ if borrow {
352+ // Check for &self vs &mut self in the method signature. Since this is either
353+ // the Fn or FnMut trait, it should be one of those.
354+ let ty:: Ref ( _, _, mutbl) = method. sig . inputs ( ) [ 0 ] . kind ( ) else {
355+ bug ! ( "Expected `FnMut`/`Fn` to take receiver by-ref/by-mut" )
356+ } ;
357+
358+ // For initial two-phase borrow
359+ // deployment, conservatively omit
360+ // overloaded function call ops.
361+ let mutbl = AutoBorrowMutability :: new ( * mutbl, AllowTwoPhase :: No ) ;
362+
363+ autoref = Some ( Adjustment {
364+ kind : Adjust :: Borrow ( AutoBorrow :: Ref ( mutbl) ) ,
365+ target : method. sig . inputs ( ) [ 0 ] ,
312366 } ) ;
367+ }
313368
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- }
369+ Some ( ( autoref, method) )
370+ }
371+
372+ fn try_overloaded_call_traits_for_alias (
373+ & self ,
374+ call_expr : & ' tcx hir:: Expr < ' tcx > ,
375+ alias_ty : ty:: AliasTy < ' tcx > ,
376+ arg_exprs : & ' tcx [ rustc_hir:: Expr < ' tcx > ] ,
377+ ) -> Option < ( Option < Adjustment < ' tcx > > , MethodCallee < ' tcx > ) > {
378+ let call_ty = alias_ty. to_ty ( self . tcx ) ;
379+
380+ let call_traits = [
381+ ( self . tcx . lang_items ( ) . fn_trait ( ) , sym:: call, true ) ,
382+ ( self . tcx . lang_items ( ) . fn_mut_trait ( ) , sym:: call_mut, true ) ,
383+ ( self . tcx . lang_items ( ) . fn_once_trait ( ) , sym:: call_once, false ) ,
384+ ( self . tcx . lang_items ( ) . async_fn_trait ( ) , sym:: async_call, true ) ,
385+ ( self . tcx . lang_items ( ) . async_fn_mut_trait ( ) , sym:: async_call_mut, true ) ,
386+ ( self . tcx . lang_items ( ) . async_fn_once_trait ( ) , sym:: async_call_once, false ) ,
387+ ] ;
388+ // We only want to try a call trait if it shows up in the bounds
389+ // of the opaque. We confirm the first one that shows up in the
390+ // bounds list, which can lead to inference weirdness but doesn't
391+ // matter today.
392+ for clause in
393+ self . tcx . item_self_bounds ( alias_ty. def_id ) . iter_instantiated ( self . tcx , alias_ty. args )
394+ {
395+ let Some ( poly_trait_ref) = clause. as_trait_clause ( ) else {
396+ continue ;
397+ } ;
340398
341- return Some ( ( autoref, method) ) ;
399+ if let Some ( & ( opt_trait_def_id, method_name, borrow) ) =
400+ call_traits. iter ( ) . find ( |( trait_def_id, _, _) | {
401+ trait_def_id. is_some_and ( |trait_def_id| trait_def_id == poly_trait_ref. def_id ( ) )
402+ } )
403+ && let Some ( confirmed) = self . try_overloaded_call_trait (
404+ call_expr,
405+ call_ty,
406+ Some ( arg_exprs) ,
407+ opt_trait_def_id,
408+ method_name,
409+ borrow,
410+ )
411+ {
412+ return Some ( confirmed) ;
342413 }
343414 }
344415
0 commit comments