Skip to main content

hir_ty/infer/
callee.rs

1//! Inference of calls.
2
3use std::iter;
4
5use rustc_abi::ExternAbi;
6use tracing::debug;
7
8use hir_def::{CallableDefId, ConstParamId, hir::ExprId, signatures::FunctionSignature};
9use rustc_type_ir::{
10    InferTy, Interner,
11    inherent::{GenericArgs as _, IntoKind, Ty as _},
12};
13
14use crate::{
15    Adjust, Adjustment, AutoBorrow,
16    autoderef::{GeneralAutoderef, InferenceContextAutoderef},
17    infer::{
18        AllowTwoPhase, AutoBorrowMutability, Expectation, InferenceContext, InferenceDiagnostic,
19        expr::{ExprIsRead, TupleArgumentsFlag},
20    },
21    method_resolution::{MethodCallee, TreatNotYetDefinedOpaques},
22    next_solver::{
23        ConstKind, FnSig, Ty, TyKind,
24        infer::{BoundRegionConversionTime, traits::ObligationCause},
25    },
26};
27
28#[derive(Debug)]
29enum CallStep<'db> {
30    Builtin(Ty<'db>),
31    DeferredClosure(ExprId, FnSig<'db>),
32    /// Call overloading when callee implements one of the Fn* traits.
33    Overloaded(MethodCallee<'db>),
34}
35
36impl<'db> InferenceContext<'db> {
37    pub(crate) fn infer_call(
38        &mut self,
39        call_expr: ExprId,
40        callee_expr: ExprId,
41        arg_exprs: &[ExprId],
42        expected: &Expectation<'db>,
43    ) -> Ty<'db> {
44        let original_callee_ty = self.infer_expr_no_expect(callee_expr, ExprIsRead::Yes);
45
46        let expr_ty =
47            self.table.try_structurally_resolve_type(callee_expr.into(), original_callee_ty);
48
49        let mut autoderef =
50            GeneralAutoderef::new_from_inference_context(self, expr_ty, callee_expr.into());
51        let mut result = None;
52        let mut error_reported = false;
53        while result.is_none() && autoderef.next().is_some() {
54            result = Self::try_overloaded_call_step(
55                call_expr,
56                callee_expr,
57                arg_exprs,
58                &mut autoderef,
59                &mut error_reported,
60            );
61        }
62
63        // FIXME: rustc does some ABI checks here, but the ABI mapping is in rustc_target and we don't have access to that crate.
64
65        let obligations = autoderef.take_obligations();
66        self.table.register_predicates(obligations);
67
68        let output = match result {
69            None => {
70                // Check all of the arg expressions, but with no expectations
71                // since we don't have a signature to compare them to.
72                for &arg in arg_exprs {
73                    self.infer_expr_no_expect(arg, ExprIsRead::Yes);
74                }
75
76                if !error_reported {
77                    self.push_diagnostic(InferenceDiagnostic::ExpectedFunction {
78                        call_expr,
79                        found: original_callee_ty.store(),
80                    });
81                }
82
83                self.types.types.error
84            }
85
86            Some(CallStep::Builtin(callee_ty)) => {
87                self.confirm_builtin_call(callee_expr, call_expr, callee_ty, arg_exprs, expected)
88            }
89
90            Some(CallStep::DeferredClosure(_def_id, fn_sig)) => {
91                self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, fn_sig)
92            }
93
94            Some(CallStep::Overloaded(method_callee)) => {
95                self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
96            }
97        };
98
99        // we must check that return type of called functions is WF:
100        self.table.register_wf_obligation(output.into(), ObligationCause::new(call_expr));
101
102        output
103    }
104
105    fn try_overloaded_call_step(
106        call_expr: ExprId,
107        callee_expr: ExprId,
108        arg_exprs: &[ExprId],
109        autoderef: &mut InferenceContextAutoderef<'_, 'db>,
110        error_reported: &mut bool,
111    ) -> Option<CallStep<'db>> {
112        let final_ty = autoderef.final_ty();
113        let adjusted_ty =
114            autoderef.ctx().table.try_structurally_resolve_type(callee_expr.into(), final_ty);
115
116        // If the callee is a function pointer or a closure, then we're all set.
117        match adjusted_ty.kind() {
118            TyKind::FnDef(..) | TyKind::FnPtr(..) => {
119                let adjust_steps = autoderef.adjust_steps_as_infer_ok();
120                let adjustments =
121                    autoderef.ctx().table.register_infer_ok(adjust_steps).into_boxed_slice();
122                autoderef.ctx().write_expr_adj(callee_expr, adjustments);
123                return Some(CallStep::Builtin(adjusted_ty));
124            }
125
126            // Check whether this is a call to a closure where we
127            // haven't yet decided on whether the closure is fn vs
128            // fnmut vs fnonce. If so, we have to defer further processing.
129            TyKind::Closure(def_id, args)
130                if autoderef.ctx().infcx().closure_kind(adjusted_ty).is_none() =>
131            {
132                let closure_sig = args.as_closure().sig();
133                let closure_sig = autoderef.ctx().infcx().instantiate_binder_with_fresh_vars(
134                    callee_expr.into(),
135                    BoundRegionConversionTime::FnCall,
136                    closure_sig,
137                );
138                let adjust_steps = autoderef.adjust_steps_as_infer_ok();
139                let adjustments = autoderef.ctx().table.register_infer_ok(adjust_steps);
140                let def_id = def_id.0.loc(autoderef.ctx().db).expr;
141                autoderef.ctx().record_deferred_call_resolution(
142                    def_id,
143                    DeferredCallResolution {
144                        call_expr,
145                        callee_expr,
146                        closure_ty: adjusted_ty,
147                        adjustments,
148                        fn_sig: closure_sig,
149                    },
150                );
151                return Some(CallStep::DeferredClosure(def_id, closure_sig));
152            }
153
154            // When calling a `CoroutineClosure` that is local to the body, we will
155            // not know what its `closure_kind` is yet. Instead, just fill in the
156            // signature with an infer var for the `tupled_upvars_ty` of the coroutine,
157            // and record a deferred call resolution which will constrain that var
158            // as part of `AsyncFn*` trait confirmation.
159            TyKind::CoroutineClosure(def_id, args)
160                if autoderef.ctx().infcx().closure_kind(adjusted_ty).is_none() =>
161            {
162                let closure_args = args.as_coroutine_closure();
163                let coroutine_closure_sig =
164                    autoderef.ctx().infcx().instantiate_binder_with_fresh_vars(
165                        callee_expr.into(),
166                        BoundRegionConversionTime::FnCall,
167                        closure_args.coroutine_closure_sig(),
168                    );
169                let tupled_upvars_ty = autoderef.ctx().table.next_ty_var(call_expr.into());
170                // We may actually receive a coroutine back whose kind is different
171                // from the closure that this dispatched from. This is because when
172                // we have no captures, we automatically implement `FnOnce`. This
173                // impl forces the closure kind to `FnOnce` i.e. `u8`.
174                let kind_ty = autoderef.ctx().table.next_ty_var(call_expr.into());
175                let interner = autoderef.ctx().interner();
176
177                // Ignore splatting, it is unsupported on closures.
178                let call_sig = interner.mk_fn_sig(
179                    [coroutine_closure_sig.tupled_inputs_ty],
180                    coroutine_closure_sig.to_coroutine(
181                        interner,
182                        closure_args.parent_args(),
183                        kind_ty,
184                        interner.coroutine_for_closure(def_id),
185                        tupled_upvars_ty,
186                    ),
187                    coroutine_closure_sig.fn_sig_kind.c_variadic(),
188                    coroutine_closure_sig.fn_sig_kind.safety(),
189                    coroutine_closure_sig.fn_sig_kind.abi(),
190                );
191                let adjust_steps = autoderef.adjust_steps_as_infer_ok();
192                let adjustments = autoderef.ctx().table.register_infer_ok(adjust_steps);
193                let def_id = def_id.0.loc(autoderef.ctx().db).expr;
194                autoderef.ctx().record_deferred_call_resolution(
195                    def_id,
196                    DeferredCallResolution {
197                        call_expr,
198                        callee_expr,
199                        closure_ty: adjusted_ty,
200                        adjustments,
201                        fn_sig: call_sig,
202                    },
203                );
204                return Some(CallStep::DeferredClosure(def_id, call_sig));
205            }
206
207            // Hack: we know that there are traits implementing Fn for &F
208            // where F:Fn and so forth. In the particular case of types
209            // like `f: &mut FnMut()`, if there is a call `f()`, we would
210            // normally translate to `FnMut::call_mut(&mut f, ())`, but
211            // that winds up potentially requiring the user to mark their
212            // variable as `mut` which feels unnecessary and unexpected.
213            //
214            //     fn foo(f: &mut impl FnMut()) { f() }
215            //            ^ without this hack `f` would have to be declared as mutable
216            //
217            // The simplest fix by far is to just ignore this case and deref again,
218            // so we wind up with `FnMut::call_mut(&mut *f, ())`.
219            TyKind::Ref(..) if autoderef.step_count() == 0 => {
220                return None;
221            }
222
223            TyKind::Infer(InferTy::TyVar(vid))
224                // If we end up with an inference variable which is not the hidden type of
225                // an opaque, emit an error.
226                if !autoderef.ctx().infcx().has_opaques_with_sub_unified_hidden_type(vid) => {
227                    autoderef
228                        .ctx()
229                        .type_must_be_known_at_this_point(callee_expr.into(), adjusted_ty);
230                    *error_reported = true;
231                    return None;
232                }
233
234            TyKind::Error(_) => {
235                return None;
236            }
237
238            _ => {}
239        }
240
241        // Now, we look for the implementation of a Fn trait on the object's type.
242        // We first do it with the explicit instruction to look for an impl of
243        // `Fn<Tuple>`, with the tuple `Tuple` having an arity corresponding
244        // to the number of call parameters.
245        // If that fails (or_else branch), we try again without specifying the
246        // shape of the tuple (hence the None). This allows to detect an Fn trait
247        // is implemented, and use this information for diagnostic.
248        autoderef
249            .ctx()
250            .try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs))
251            .or_else(|| autoderef.ctx().try_overloaded_call_traits(call_expr, adjusted_ty, None))
252            .map(|(autoref, method)| {
253                let adjustments = autoderef.adjust_steps_as_infer_ok();
254                let mut adjustments = autoderef.ctx().table.register_infer_ok(adjustments);
255                adjustments.extend(autoref);
256                autoderef.ctx().write_expr_adj(callee_expr, adjustments.into_boxed_slice());
257                CallStep::Overloaded(method)
258            })
259    }
260
261    fn try_overloaded_call_traits(
262        &mut self,
263        call_expr: ExprId,
264        adjusted_ty: Ty<'db>,
265        opt_arg_exprs: Option<&[ExprId]>,
266    ) -> Option<(Option<Adjustment>, MethodCallee<'db>)> {
267        // HACK(async_closures): For async closures, prefer `AsyncFn*`
268        // over `Fn*`, since all async closures implement `FnOnce`, but
269        // choosing that over `AsyncFn`/`AsyncFnMut` would be more restrictive.
270        // For other callables, just prefer `Fn*` for perf reasons.
271        //
272        // The order of trait choices here is not that big of a deal,
273        // since it just guides inference (and our choice of autoref).
274        // Though in the future, I'd like typeck to choose:
275        // `Fn > AsyncFn > FnMut > AsyncFnMut > FnOnce > AsyncFnOnce`
276        // ...or *ideally*, we just have `LendingFn`/`LendingFnMut`, which
277        // would naturally unify these two trait hierarchies in the most
278        // general way.
279
280        let call_trait_choices = if self.shallow_resolve(adjusted_ty).is_coroutine_closure() {
281            [
282                (self.lang_items.AsyncFn, self.lang_items.AsyncFn_async_call, true),
283                (self.lang_items.AsyncFnMut, self.lang_items.AsyncFnMut_async_call_mut, true),
284                (self.lang_items.AsyncFnOnce, self.lang_items.AsyncFnOnce_async_call_once, false),
285                (self.lang_items.Fn, self.lang_items.Fn_call, true),
286                (self.lang_items.FnMut, self.lang_items.FnMut_call_mut, true),
287                (self.lang_items.FnOnce, self.lang_items.FnOnce_call_once, false),
288            ]
289        } else {
290            [
291                (self.lang_items.Fn, self.lang_items.Fn_call, true),
292                (self.lang_items.FnMut, self.lang_items.FnMut_call_mut, true),
293                (self.lang_items.FnOnce, self.lang_items.FnOnce_call_once, false),
294                (self.lang_items.AsyncFn, self.lang_items.AsyncFn_async_call, true),
295                (self.lang_items.AsyncFnMut, self.lang_items.AsyncFnMut_async_call_mut, true),
296                (self.lang_items.AsyncFnOnce, self.lang_items.AsyncFnOnce_async_call_once, false),
297            ]
298        };
299
300        // Try the options that are least restrictive on the caller first.
301        for (opt_trait_def_id, opt_method_def_id, borrow) in call_trait_choices {
302            let (Some(trait_def_id), Some(method_def_id)) = (opt_trait_def_id, opt_method_def_id)
303            else {
304                continue;
305            };
306
307            let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
308                Ty::new_tup_from_iter(
309                    self.interner(),
310                    arg_exprs.iter().map(|&arg| self.table.next_ty_var(arg.into())),
311                )
312            });
313
314            // We use `TreatNotYetDefinedOpaques::AsRigid` here so that if the `adjusted_ty`
315            // is `Box<impl FnOnce()>` we choose  `FnOnce` instead of `Fn`.
316            //
317            // We try all the different call traits in order and choose the first
318            // one which may apply. So if we treat opaques as inference variables
319            // `Box<impl FnOnce()>: Fn` is considered ambiguous and chosen.
320            if let Some(ok) = self.table.lookup_method_for_operator(
321                ObligationCause::new(call_expr),
322                trait_def_id,
323                method_def_id,
324                adjusted_ty,
325                opt_input_type,
326                TreatNotYetDefinedOpaques::AsRigid,
327            ) {
328                let method = self.table.register_infer_ok(ok);
329                let mut autoref = None;
330                if borrow {
331                    // Check for &self vs &mut self in the method signature. Since this is either
332                    // the Fn or FnMut trait, it should be one of those.
333                    let TyKind::Ref(_, _, mutbl) = method.sig.inputs_and_output.inputs()[0].kind()
334                    else {
335                        panic!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
336                    };
337
338                    // For initial two-phase borrow
339                    // deployment, conservatively omit
340                    // overloaded function call ops.
341                    let mutbl = AutoBorrowMutability::new(mutbl, AllowTwoPhase::No);
342
343                    autoref = Some(Adjustment {
344                        kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
345                        target: method.sig.inputs_and_output.inputs()[0].store(),
346                    });
347                }
348
349                return Some((autoref, method));
350            }
351        }
352
353        None
354    }
355
356    /// Returns the argument indices to skip.
357    fn check_legacy_const_generics(
358        &mut self,
359        callee: Option<CallableDefId>,
360        callee_ty: Ty<'db>,
361        args: &[ExprId],
362    ) -> Box<[u32]> {
363        let (func, fn_generic_args) = match (callee, callee_ty.kind()) {
364            (Some(CallableDefId::FunctionId(func)), TyKind::FnDef(_, fn_generic_args)) => {
365                (func, fn_generic_args)
366            }
367            _ => return Default::default(),
368        };
369        let generics = crate::generics::generics(self.db, func.into());
370        let const_params = generics
371            .iter_self_type_or_consts()
372            .filter(|(_, param_data)| param_data.const_param().is_some())
373            .map(|(id, _)| ConstParamId::from_unchecked(id))
374            .collect::<Vec<_>>();
375
376        let data = FunctionSignature::of(self.db, func);
377        let Some(legacy_const_generics_indices) = data.legacy_const_generics_indices(self.db, func)
378        else {
379            return Default::default();
380        };
381        let mut legacy_const_generics_indices = Box::<[u32]>::from(legacy_const_generics_indices);
382
383        // only use legacy const generics if the param count matches with them
384        if data.params.len() + legacy_const_generics_indices.len() != args.len() {
385            if args.len() <= data.params.len() {
386                return Default::default();
387            } else {
388                // there are more parameters than there should be without legacy
389                // const params; use them
390                legacy_const_generics_indices.sort_unstable();
391                return legacy_const_generics_indices;
392            }
393        }
394
395        // check legacy const parameters
396        for (const_idx, arg_idx) in legacy_const_generics_indices.iter().copied().enumerate() {
397            if arg_idx >= args.len() as u32 {
398                continue;
399            }
400
401            if let Some(const_arg) = fn_generic_args.get(const_idx).and_then(|it| it.konst())
402                && let ConstKind::Infer(_) = const_arg.kind()
403            {
404                // Instantiate the generic arg with an error type, to prevent errors from it.
405                // FIXME: Actually lower the expression as const.
406                _ = self
407                    .table
408                    .at(&ObligationCause::dummy())
409                    .eq(self.types.consts.error, const_arg)
410                    .map(|infer_ok| self.table.register_infer_ok(infer_ok));
411            }
412
413            let expected = if let Some(&const_param) = const_params.get(const_idx) {
414                Expectation::has_type(self.db.const_param_ty(const_param))
415            } else {
416                Expectation::None
417            };
418
419            self.infer_expr(args[arg_idx as usize], &expected, ExprIsRead::Yes);
420            // FIXME: evaluate and unify with the const
421        }
422        legacy_const_generics_indices.sort_unstable();
423        legacy_const_generics_indices
424    }
425
426    fn confirm_builtin_call(
427        &mut self,
428        callee_expr: ExprId,
429        call_expr: ExprId,
430        callee_ty: Ty<'db>,
431        arg_exprs: &[ExprId],
432        expected: &Expectation<'db>,
433    ) -> Ty<'db> {
434        let (fn_sig, def_id) = match callee_ty.kind() {
435            TyKind::FnDef(def_id, args) => {
436                let fn_sig = self
437                    .db
438                    .callable_item_signature(def_id.0)
439                    .instantiate(self.interner(), args)
440                    .skip_norm_wip();
441                (fn_sig, Some(def_id.0))
442            }
443
444            // FIXME(const_trait_impl): these arms should error because we can't enforce them
445            TyKind::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None),
446
447            _ => unreachable!(),
448        };
449
450        // Replace any late-bound regions that appear in the function
451        // signature with region variables. We also have to
452        // renormalize the associated types at this point, since they
453        // previously appeared within a `Binder<>` and hence would not
454        // have been normalized before.
455        let fn_sig = self.infcx().instantiate_binder_with_fresh_vars(
456            callee_expr.into(),
457            BoundRegionConversionTime::FnCall,
458            fn_sig,
459        );
460
461        let indices_to_skip = self.check_legacy_const_generics(def_id, callee_ty, arg_exprs);
462        self.check_call_arguments(
463            call_expr,
464            fn_sig.inputs(),
465            fn_sig.output(),
466            expected,
467            arg_exprs,
468            &indices_to_skip,
469            fn_sig.c_variadic(),
470            TupleArgumentsFlag::DontTupleArguments,
471        );
472
473        if fn_sig.abi() == ExternAbi::RustCall
474            && let Some(ty) = fn_sig.inputs().last().copied()
475            && let Some(tuple_trait) = self.lang_items.Tuple
476        {
477            let span = arg_exprs.last().copied().unwrap_or(call_expr);
478            self.table.register_bound(ty, tuple_trait, ObligationCause::new(span));
479            self.require_type_is_sized(ty, span.into());
480        }
481
482        fn_sig.output()
483    }
484
485    fn confirm_deferred_closure_call(
486        &mut self,
487        call_expr: ExprId,
488        arg_exprs: &[ExprId],
489        expected: &Expectation<'db>,
490        fn_sig: FnSig<'db>,
491    ) -> Ty<'db> {
492        // `fn_sig` is the *signature* of the closure being called. We
493        // don't know the full details yet (`Fn` vs `FnMut` etc), but we
494        // do know the types expected for each argument and the return
495        // type.
496        self.check_call_arguments(
497            call_expr,
498            fn_sig.inputs(),
499            fn_sig.output(),
500            expected,
501            arg_exprs,
502            &[],
503            fn_sig.c_variadic(),
504            TupleArgumentsFlag::TupleArguments,
505        );
506
507        fn_sig.output()
508    }
509
510    fn confirm_overloaded_call(
511        &mut self,
512        call_expr: ExprId,
513        arg_exprs: &[ExprId],
514        expected: &Expectation<'db>,
515        method: MethodCallee<'db>,
516    ) -> Ty<'db> {
517        self.check_call_arguments(
518            call_expr,
519            &method.sig.inputs()[1..],
520            method.sig.output(),
521            expected,
522            arg_exprs,
523            &[],
524            method.sig.c_variadic(),
525            TupleArgumentsFlag::TupleArguments,
526        );
527
528        self.write_method_resolution(call_expr, method.def_id, method.args);
529
530        method.sig.output()
531    }
532}
533
534#[derive(Debug, Clone)]
535pub(crate) struct DeferredCallResolution<'db> {
536    call_expr: ExprId,
537    callee_expr: ExprId,
538    closure_ty: Ty<'db>,
539    adjustments: Vec<Adjustment>,
540    fn_sig: FnSig<'db>,
541}
542
543impl<'db> DeferredCallResolution<'db> {
544    pub(crate) fn resolve(self, ctx: &mut InferenceContext<'db>) {
545        debug!("DeferredCallResolution::resolve() {:?}", self);
546
547        // we should not be invoked until the closure kind has been
548        // determined by upvar inference
549        assert!(ctx.infcx().closure_kind(self.closure_ty).is_some());
550
551        // We may now know enough to figure out fn vs fnmut etc.
552        match ctx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) {
553            Some((autoref, method_callee)) => {
554                // One problem is that when we get here, we are going
555                // to have a newly instantiated function signature
556                // from the call trait. This has to be reconciled with
557                // the older function signature we had before. In
558                // principle we *should* be able to fn_sigs(), but we
559                // can't because of the annoying need for a TypeTrace.
560                // (This always bites me, should find a way to
561                // refactor it.)
562                let method_sig = method_callee.sig;
563
564                debug!("attempt_resolution: method_callee={:?}", method_callee);
565
566                for (method_arg_ty, self_arg_ty) in
567                    iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs())
568                {
569                    _ = ctx.demand_eqtype(self.call_expr.into(), *self_arg_ty, *method_arg_ty);
570                }
571
572                _ = ctx.demand_eqtype(
573                    self.call_expr.into(),
574                    method_sig.output(),
575                    self.fn_sig.output(),
576                );
577
578                let mut adjustments = self.adjustments;
579                adjustments.extend(autoref);
580                ctx.write_expr_adj(self.callee_expr, adjustments.into_boxed_slice());
581
582                ctx.write_method_resolution(
583                    self.call_expr,
584                    method_callee.def_id,
585                    method_callee.args,
586                );
587            }
588            None => {}
589        }
590    }
591}