use super::method::probe::ProbeScope;
use super::method::MethodCallee;
use super::{Expectation, FnCtxt, TupleArgumentsFlag};

use crate::errors;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::{
    infer,
    traits::{self, Obligation},
};
use rustc_infer::{infer::type_variable::TypeVariableOrigin, traits::ObligationCause};
use rustc_middle::ty::adjustment::{
    Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_target::spec::abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::DefIdOrName;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;

use std::{iter, slice};

/// Checks that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
/// method that is called).
pub fn check_legal_trait_for_method_call(
    tcx: TyCtxt<'_>,
    span: Span,
    receiver: Option<Span>,
    expr_span: Span,
    trait_id: DefId,
    body_id: DefId,
) -> Result<(), ErrorGuaranteed> {
    if tcx.lang_items().drop_trait() == Some(trait_id)
        && tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
    {
        let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
            errors::ExplicitDestructorCallSugg::Snippet {
                lo: expr_span.shrink_to_lo(),
                hi: receiver.shrink_to_hi().to(expr_span.shrink_to_hi()),
            }
        } else {
            errors::ExplicitDestructorCallSugg::Empty(span)
        };
        return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }));
    }
    tcx.ensure().coherent_trait(trait_id)
}

#[derive(Debug)]
enum CallStep<'tcx> {
    Builtin(Ty<'tcx>),
    DeferredClosure(LocalDefId, ty::FnSig<'tcx>),
    /// E.g., enum variant constructors.
    Overloaded(MethodCallee<'tcx>),
}

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
    pub fn check_call(
        &self,
        call_expr: &'tcx hir::Expr<'tcx>,
        callee_expr: &'tcx hir::Expr<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        let original_callee_ty = match &callee_expr.kind {
            hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
                .check_expr_with_expectation_and_args(
                    callee_expr,
                    Expectation::NoExpectation,
                    arg_exprs,
                    Some(call_expr),
                ),
            _ => self.check_expr(callee_expr),
        };

        let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty);

        let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
        let mut result = None;
        while result.is_none() && autoderef.next().is_some() {
            result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
        }
        self.register_predicates(autoderef.into_obligations());

        let output = match result {
            None => {
                // this will report an error since original_callee_ty is not a fn
                self.confirm_builtin_call(
                    call_expr,
                    callee_expr,
                    original_callee_ty,
                    arg_exprs,
                    expected,
                )
            }

            Some(CallStep::Builtin(callee_ty)) => {
                self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
            }

            Some(CallStep::DeferredClosure(def_id, fn_sig)) => {
                self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, def_id, fn_sig)
            }

            Some(CallStep::Overloaded(method_callee)) => {
                self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
            }
        };

        // we must check that return type of called functions is WF:
        self.register_wf_obligation(output.into(), call_expr.span, traits::WellFormed(None));

        output
    }

    #[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)]
    fn try_overloaded_call_step(
        &self,
        call_expr: &'tcx hir::Expr<'tcx>,
        callee_expr: &'tcx hir::Expr<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
        autoderef: &Autoderef<'a, 'tcx>,
    ) -> Option<CallStep<'tcx>> {
        let adjusted_ty =
            self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));

        // If the callee is a bare function or a closure, then we're all set.
        match *adjusted_ty.kind() {
            ty::FnDef(..) | ty::FnPtr(_) => {
                let adjustments = self.adjust_steps(autoderef);
                self.apply_adjustments(callee_expr, adjustments);
                return Some(CallStep::Builtin(adjusted_ty));
            }

            // Check whether this is a call to a closure where we
            // haven't yet decided on whether the closure is fn vs
            // fnmut vs fnonce. If so, we have to defer further processing.
            ty::Closure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => {
                let def_id = def_id.expect_local();
                let closure_sig = args.as_closure().sig();
                let closure_sig = self.instantiate_binder_with_fresh_vars(
                    call_expr.span,
                    infer::FnCall,
                    closure_sig,
                );
                let adjustments = self.adjust_steps(autoderef);
                self.record_deferred_call_resolution(
                    def_id,
                    DeferredCallResolution {
                        call_expr,
                        callee_expr,
                        closure_ty: adjusted_ty,
                        adjustments,
                        fn_sig: closure_sig,
                    },
                );
                return Some(CallStep::DeferredClosure(def_id, closure_sig));
            }

            // When calling a `CoroutineClosure` that is local to the body, we will
            // not know what its `closure_kind` is yet. Instead, just fill in the
            // signature with an infer var for the `tupled_upvars_ty` of the coroutine,
            // and record a deferred call resolution which will constrain that var
            // as part of `AsyncFn*` trait confirmation.
            ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => {
                let def_id = def_id.expect_local();
                let closure_args = args.as_coroutine_closure();
                let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars(
                    call_expr.span,
                    infer::FnCall,
                    closure_args.coroutine_closure_sig(),
                );
                let tupled_upvars_ty = self
                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
                // We may actually receive a coroutine back whose kind is different
                // from the closure that this dispatched from. This is because when
                // we have no captures, we automatically implement `FnOnce`. This
                // impl forces the closure kind to `FnOnce` i.e. `u8`.
                let kind_ty = self
                    .next_ty_var(TypeVariableOrigin { param_def_id: None, span: callee_expr.span });
                let call_sig = self.tcx.mk_fn_sig(
                    [coroutine_closure_sig.tupled_inputs_ty],
                    coroutine_closure_sig.to_coroutine(
                        self.tcx,
                        closure_args.parent_args(),
                        kind_ty,
                        self.tcx.coroutine_for_closure(def_id),
                        tupled_upvars_ty,
                    ),
                    coroutine_closure_sig.c_variadic,
                    coroutine_closure_sig.unsafety,
                    coroutine_closure_sig.abi,
                );
                let adjustments = self.adjust_steps(autoderef);
                self.record_deferred_call_resolution(
                    def_id,
                    DeferredCallResolution {
                        call_expr,
                        callee_expr,
                        closure_ty: adjusted_ty,
                        adjustments,
                        fn_sig: call_sig,
                    },
                );
                return Some(CallStep::DeferredClosure(def_id, call_sig));
            }

            // Hack: we know that there are traits implementing Fn for &F
            // where F:Fn and so forth. In the particular case of types
            // like `f: &mut FnMut()`, if there is a call `f()`, we would
            // normally translate to `FnMut::call_mut(&mut f, ())`, but
            // that winds up potentially requiring the user to mark their
            // variable as `mut` which feels unnecessary and unexpected.
            //
            //     fn foo(f: &mut impl FnMut()) { f() }
            //            ^ without this hack `f` would have to be declared as mutable
            //
            // The simplest fix by far is to just ignore this case and deref again,
            // so we wind up with `FnMut::call_mut(&mut *f, ())`.
            ty::Ref(..) if autoderef.step_count() == 0 => {
                return None;
            }

            ty::Error(_) => {
                return None;
            }

            _ => {}
        }

        // Now, we look for the implementation of a Fn trait on the object's type.
        // We first do it with the explicit instruction to look for an impl of
        // `Fn<Tuple>`, with the tuple `Tuple` having an arity corresponding
        // to the number of call parameters.
        // If that fails (or_else branch), we try again without specifying the
        // shape of the tuple (hence the None). This allows to detect an Fn trait
        // is implemented, and use this information for diagnostic.
        self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs))
            .or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None))
            .map(|(autoref, method)| {
                let mut adjustments = self.adjust_steps(autoderef);
                adjustments.extend(autoref);
                self.apply_adjustments(callee_expr, adjustments);
                CallStep::Overloaded(method)
            })
    }

    fn try_overloaded_call_traits(
        &self,
        call_expr: &hir::Expr<'_>,
        adjusted_ty: Ty<'tcx>,
        opt_arg_exprs: Option<&'tcx [hir::Expr<'tcx>]>,
    ) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> {
        // HACK(async_closures): For async closures, prefer `AsyncFn*`
        // over `Fn*`, since all async closures implement `FnOnce`, but
        // choosing that over `AsyncFn`/`AsyncFnMut` would be more restrictive.
        // For other callables, just prefer `Fn*` for perf reasons.
        //
        // The order of trait choices here is not that big of a deal,
        // since it just guides inference (and our choice of autoref).
        // Though in the future, I'd like typeck to choose:
        // `Fn > AsyncFn > FnMut > AsyncFnMut > FnOnce > AsyncFnOnce`
        // ...or *ideally*, we just have `LendingFn`/`LendingFnMut`, which
        // would naturally unify these two trait hierarchies in the most
        // general way.
        let call_trait_choices = if self.shallow_resolve(adjusted_ty).is_coroutine_closure() {
            [
                (self.tcx.lang_items().async_fn_trait(), sym::async_call, true),
                (self.tcx.lang_items().async_fn_mut_trait(), sym::async_call_mut, true),
                (self.tcx.lang_items().async_fn_once_trait(), sym::async_call_once, false),
                (self.tcx.lang_items().fn_trait(), sym::call, true),
                (self.tcx.lang_items().fn_mut_trait(), sym::call_mut, true),
                (self.tcx.lang_items().fn_once_trait(), sym::call_once, false),
            ]
        } else {
            [
                (self.tcx.lang_items().fn_trait(), sym::call, true),
                (self.tcx.lang_items().fn_mut_trait(), sym::call_mut, true),
                (self.tcx.lang_items().fn_once_trait(), sym::call_once, false),
                (self.tcx.lang_items().async_fn_trait(), sym::async_call, true),
                (self.tcx.lang_items().async_fn_mut_trait(), sym::async_call_mut, true),
                (self.tcx.lang_items().async_fn_once_trait(), sym::async_call_once, false),
            ]
        };

        // Try the options that are least restrictive on the caller first.
        for (opt_trait_def_id, method_name, borrow) in call_trait_choices {
            let Some(trait_def_id) = opt_trait_def_id else { continue };

            let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
                Ty::new_tup_from_iter(
                    self.tcx,
                    arg_exprs.iter().map(|e| {
                        self.next_ty_var(TypeVariableOrigin { param_def_id: None, span: e.span })
                    }),
                )
            });

            if let Some(ok) = self.lookup_method_in_trait(
                self.misc(call_expr.span),
                Ident::with_dummy_span(method_name),
                trait_def_id,
                adjusted_ty,
                opt_input_type.as_ref().map(slice::from_ref),
            ) {
                let method = self.register_infer_ok_obligations(ok);
                let mut autoref = None;
                if borrow {
                    // Check for &self vs &mut self in the method signature. Since this is either
                    // the Fn or FnMut trait, it should be one of those.
                    let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else {
                        bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
                    };

                    // For initial two-phase borrow
                    // deployment, conservatively omit
                    // overloaded function call ops.
                    let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::No);

                    autoref = Some(Adjustment {
                        kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)),
                        target: method.sig.inputs()[0],
                    });
                }

                return Some((autoref, method));
            }
        }

        None
    }

    /// Give appropriate suggestion when encountering `||{/* not callable */}()`, where the
    /// likely intention is to call the closure, suggest `(||{})()`. (#55851)
    fn identify_bad_closure_def_and_call(
        &self,
        err: &mut Diag<'_>,
        hir_id: hir::HirId,
        callee_node: &hir::ExprKind<'_>,
        callee_span: Span,
    ) {
        let hir::ExprKind::Block(..) = callee_node else {
            // Only calls on blocks suggested here.
            return;
        };

        let hir = self.tcx.hir();
        let fn_decl_span = if let hir::Node::Expr(hir::Expr {
            kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
            ..
        }) = self.tcx.parent_hir_node(hir_id)
        {
            fn_decl_span
        } else if let Some((
            _,
            hir::Node::Expr(&hir::Expr {
                hir_id: parent_hir_id,
                kind:
                    hir::ExprKind::Closure(&hir::Closure {
                        kind:
                            hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
                                hir::CoroutineDesugaring::Async,
                                hir::CoroutineSource::Closure,
                            )),
                        ..
                    }),
                ..
            }),
        )) = hir.parent_iter(hir_id).nth(3)
        {
            // Actually need to unwrap one more layer of HIR to get to
            // the _real_ closure...
            if let hir::Node::Expr(hir::Expr {
                kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
                ..
            }) = self.tcx.parent_hir_node(parent_hir_id)
            {
                fn_decl_span
            } else {
                return;
            }
        } else {
            return;
        };

        let start = fn_decl_span.shrink_to_lo();
        let end = callee_span.shrink_to_hi();
        err.multipart_suggestion(
            "if you meant to create this closure and immediately call it, surround the \
                closure with parentheses",
            vec![(start, "(".to_string()), (end, ")".to_string())],
            Applicability::MaybeIncorrect,
        );
    }

    /// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the
    /// likely intention is to create an array containing tuples.
    fn maybe_suggest_bad_array_definition(
        &self,
        err: &mut Diag<'_>,
        call_expr: &'tcx hir::Expr<'tcx>,
        callee_expr: &'tcx hir::Expr<'tcx>,
    ) -> bool {
        let parent_node = self.tcx.parent_hir_node(call_expr.hir_id);
        if let (
            hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }),
            hir::ExprKind::Tup(exp),
            hir::ExprKind::Call(_, args),
        ) = (parent_node, &callee_expr.kind, &call_expr.kind)
            && args.len() == exp.len()
        {
            let start = callee_expr.span.shrink_to_hi();
            err.span_suggestion(
                start,
                "consider separating array elements with a comma",
                ",",
                Applicability::MaybeIncorrect,
            );
            return true;
        }
        false
    }

    fn confirm_builtin_call(
        &self,
        call_expr: &'tcx hir::Expr<'tcx>,
        callee_expr: &'tcx hir::Expr<'tcx>,
        callee_ty: Ty<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        let (fn_sig, def_id) = match *callee_ty.kind() {
            ty::FnDef(def_id, args) => {
                self.enforce_context_effects(call_expr.span, def_id, args);
                let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);

                // Unit testing: function items annotated with
                // `#[rustc_evaluate_where_clauses]` trigger special output
                // to let us test the trait evaluation system.
                // Untranslatable diagnostics are okay for rustc internals
                #[allow(rustc::untranslatable_diagnostic)]
                #[allow(rustc::diagnostic_outside_of_impl)]
                if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
                    let predicates = self.tcx.predicates_of(def_id);
                    let predicates = predicates.instantiate(self.tcx, args);
                    for (predicate, predicate_span) in predicates {
                        let obligation = Obligation::new(
                            self.tcx,
                            ObligationCause::dummy_with_span(callee_expr.span),
                            self.param_env,
                            predicate,
                        );
                        let result = self.evaluate_obligation(&obligation);
                        self.dcx()
                            .struct_span_err(
                                callee_expr.span,
                                format!("evaluate({predicate:?}) = {result:?}"),
                            )
                            .with_span_label(predicate_span, "predicate")
                            .emit();
                    }
                }
                (fn_sig, Some(def_id))
            }
            // FIXME(effects): these arms should error because we can't enforce them
            ty::FnPtr(sig) => (sig, None),
            _ => {
                for arg in arg_exprs {
                    self.check_expr(arg);
                }

                if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
                    && let [segment] = path.segments
                {
                    self.dcx().try_steal_modify_and_emit_err(
                        segment.ident.span,
                        StashKey::CallIntoMethod,
                        |err| {
                            // Try suggesting `foo(a)` -> `a.foo()` if possible.
                            self.suggest_call_as_method(
                                err, segment, arg_exprs, call_expr, expected,
                            );
                        },
                    );
                }

                let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);

                return Ty::new_error(self.tcx, err);
            }
        };

        // Replace any late-bound regions that appear in the function
        // signature with region variables. We also have to
        // renormalize the associated types at this point, since they
        // previously appeared within a `Binder<>` and hence would not
        // have been normalized before.
        let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
        let fn_sig = self.normalize(call_expr.span, fn_sig);

        // Call the generic checker.
        let expected_arg_tys = self.expected_inputs_for_expected_output(
            call_expr.span,
            expected,
            fn_sig.output(),
            fn_sig.inputs(),
        );
        self.check_argument_types(
            call_expr.span,
            call_expr,
            fn_sig.inputs(),
            expected_arg_tys,
            arg_exprs,
            fn_sig.c_variadic,
            TupleArgumentsFlag::DontTupleArguments,
            def_id,
        );

        if fn_sig.abi == abi::Abi::RustCall {
            let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
            if let Some(ty) = fn_sig.inputs().last().copied() {
                self.register_bound(
                    ty,
                    self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
                    traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
                );
                self.require_type_is_sized(ty, sp, traits::RustCall);
            } else {
                self.dcx().emit_err(errors::RustCallIncorrectArgs { span: sp });
            }
        }

        if let Some(def_id) = def_id
            && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
            && self.tcx.is_intrinsic(def_id, sym::const_eval_select)
        {
            let fn_sig = self.resolve_vars_if_possible(fn_sig);
            for idx in 0..=1 {
                let arg_ty = fn_sig.inputs()[idx + 1];
                let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span);
                // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
                // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
                // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
                //
                // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
                if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
                    let fn_once_def_id =
                        self.tcx.require_lang_item(hir::LangItem::FnOnce, Some(span));
                    let fn_once_output_def_id =
                        self.tcx.require_lang_item(hir::LangItem::FnOnceOutput, Some(span));
                    if self.tcx.has_host_param(fn_once_def_id) {
                        let const_param: ty::GenericArg<'tcx> =
                            ([self.tcx.consts.false_, self.tcx.consts.true_])[idx].into();
                        self.register_predicate(traits::Obligation::new(
                            self.tcx,
                            self.misc(span),
                            self.param_env,
                            ty::TraitRef::new(
                                self.tcx,
                                fn_once_def_id,
                                [arg_ty.into(), fn_sig.inputs()[0].into(), const_param],
                            ),
                        ));

                        self.register_predicate(traits::Obligation::new(
                            self.tcx,
                            self.misc(span),
                            self.param_env,
                            ty::ProjectionPredicate {
                                projection_ty: ty::AliasTy::new(
                                    self.tcx,
                                    fn_once_output_def_id,
                                    [arg_ty.into(), fn_sig.inputs()[0].into(), const_param],
                                ),
                                term: fn_sig.output().into(),
                            },
                        ));

                        self.select_obligations_where_possible(|_| {});
                    } else if idx == 0 && !self.tcx.is_const_fn_raw(def_id) {
                        self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
                    }
                } else {
                    self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
                }
            }
        }

        fn_sig.output()
    }

    /// Attempts to reinterpret `method(rcvr, args...)` as `rcvr.method(args...)`
    /// and suggesting the fix if the method probe is successful.
    fn suggest_call_as_method(
        &self,
        diag: &mut Diag<'_>,
        segment: &'tcx hir::PathSegment<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
        call_expr: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
    ) {
        if let [callee_expr, rest @ ..] = arg_exprs {
            let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
            else {
                return;
            };

            // First, do a probe with `IsSuggestion(true)` to avoid emitting
            // any strange errors. If it's successful, then we'll do a true
            // method lookup.
            let Ok(pick) = self.lookup_probe_for_diagnostic(
                segment.ident,
                callee_ty,
                call_expr,
                // We didn't record the in scope traits during late resolution
                // so we need to probe AllTraits unfortunately
                ProbeScope::AllTraits,
                expected.only_has_type(self),
            ) else {
                return;
            };

            let pick = self.confirm_method(
                call_expr.span,
                callee_expr,
                call_expr,
                callee_ty,
                &pick,
                segment,
            );
            if pick.illegal_sized_bound.is_some() {
                return;
            }

            let Some(callee_expr_span) = callee_expr.span.find_ancestor_inside(call_expr.span)
            else {
                return;
            };
            let up_to_rcvr_span = segment.ident.span.until(callee_expr_span);
            let rest_span = callee_expr_span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
            let rest_snippet = if let Some(first) = rest.first() {
                self.tcx
                    .sess
                    .source_map()
                    .span_to_snippet(first.span.to(call_expr.span.shrink_to_hi()))
            } else {
                Ok(")".to_string())
            };

            if let Ok(rest_snippet) = rest_snippet {
                let sugg = if callee_expr.precedence().order() >= PREC_POSTFIX {
                    vec![
                        (up_to_rcvr_span, "".to_string()),
                        (rest_span, format!(".{}({rest_snippet}", segment.ident)),
                    ]
                } else {
                    vec![
                        (up_to_rcvr_span, "(".to_string()),
                        (rest_span, format!(").{}({rest_snippet}", segment.ident)),
                    ]
                };
                let self_ty = self.resolve_vars_if_possible(pick.callee.sig.inputs()[0]);
                diag.multipart_suggestion(
                    format!(
                        "use the `.` operator to call the method `{}{}` on `{self_ty}`",
                        self.tcx
                            .associated_item(pick.callee.def_id)
                            .trait_container(self.tcx)
                            .map_or_else(
                                || String::new(),
                                |trait_def_id| self.tcx.def_path_str(trait_def_id) + "::"
                            ),
                        segment.ident
                    ),
                    sugg,
                    Applicability::MaybeIncorrect,
                );
            }
        }
    }

    fn report_invalid_callee(
        &self,
        call_expr: &'tcx hir::Expr<'tcx>,
        callee_expr: &'tcx hir::Expr<'tcx>,
        callee_ty: Ty<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
    ) -> ErrorGuaranteed {
        // Callee probe fails when APIT references errors, so suppress those
        // errors here.
        if let Some((_, _, args)) = self.extract_callable_info(callee_ty)
            && let Err(err) = args.error_reported()
        {
            return err;
        }

        let mut unit_variant = None;
        if let hir::ExprKind::Path(qpath) = &callee_expr.kind
            && let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _)
                = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
            // Only suggest removing parens if there are no arguments
            && arg_exprs.is_empty()
            && call_expr.span.contains(callee_expr.span)
        {
            let descr = match kind {
                def::CtorOf::Struct => "struct",
                def::CtorOf::Variant => "enum variant",
            };
            let removal_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
            unit_variant =
                Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(&self.tcx, qpath)));
        }

        let callee_ty = self.resolve_vars_if_possible(callee_ty);
        let mut err = self.dcx().create_err(errors::InvalidCallee {
            span: callee_expr.span,
            ty: match &unit_variant {
                Some((_, kind, path)) => format!("{kind} `{path}`"),
                None => format!("`{callee_ty}`"),
            },
        });
        if callee_ty.references_error() {
            err.downgrade_to_delayed_bug();
        }

        self.identify_bad_closure_def_and_call(
            &mut err,
            call_expr.hir_id,
            &callee_expr.kind,
            callee_expr.span,
        );

        if let Some((removal_span, kind, path)) = &unit_variant {
            err.span_suggestion_verbose(
                *removal_span,
                format!(
                    "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
                ),
                "",
                Applicability::MachineApplicable,
            );
        }

        if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = callee_expr.kind
            && let Res::Local(_) = path.res
            && let [segment] = &path.segments
        {
            for id in self.tcx.hir().items() {
                if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into())
                    && let hir::Node::Item(item) = node
                    && let hir::ItemKind::Fn(..) = item.kind
                    && item.ident.name == segment.ident.name
                {
                    err.span_label(
                        self.tcx.def_span(id.owner_id),
                        "this function of the same name is available here, but it's shadowed by \
                         the local binding",
                    );
                }
            }
        }

        let mut inner_callee_path = None;
        let def = match callee_expr.kind {
            hir::ExprKind::Path(ref qpath) => {
                self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
            }
            hir::ExprKind::Call(inner_callee, _) => {
                if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
                    inner_callee_path = Some(inner_qpath);
                    self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
                } else {
                    Res::Err
                }
            }
            _ => Res::Err,
        };

        if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
            // If the call spans more than one line and the callee kind is
            // itself another `ExprCall`, that's a clue that we might just be
            // missing a semicolon (#51055, #106515).
            let call_is_multiline = self
                .tcx
                .sess
                .source_map()
                .is_multiline(call_expr.span.with_lo(callee_expr.span.hi()))
                && call_expr.span.eq_ctxt(callee_expr.span);
            if call_is_multiline {
                err.span_suggestion(
                    callee_expr.span.shrink_to_hi(),
                    "consider using a semicolon here to finish the statement",
                    ";",
                    Applicability::MaybeIncorrect,
                );
            }
            if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty)
                && !self.type_is_sized_modulo_regions(self.param_env, output_ty)
            {
                let descr = match maybe_def {
                    DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),
                    DefIdOrName::Name(name) => name,
                };
                err.span_label(
                    callee_expr.span,
                    format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
                );
                if let DefIdOrName::DefId(def_id) = maybe_def
                    && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
                {
                    err.span_label(def_span, "the callable type is defined here");
                }
            } else {
                err.span_label(call_expr.span, "call expression requires function");
            }
        }

        if let Some(span) = self.tcx.hir().res_span(def) {
            let callee_ty = callee_ty.to_string();
            let label = match (unit_variant, inner_callee_path) {
                (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
                (_, Some(hir::QPath::Resolved(_, path))) => self
                    .tcx
                    .sess
                    .source_map()
                    .span_to_snippet(path.span)
                    .ok()
                    .map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
                _ => {
                    match def {
                        // Emit a different diagnostic for local variables, as they are not
                        // type definitions themselves, but rather variables *of* that type.
                        Res::Local(hir_id) => Some(format!(
                            "`{}` has type `{}`",
                            self.tcx.hir().name(hir_id),
                            callee_ty
                        )),
                        Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
                            Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),))
                        }
                        _ => Some(format!("`{callee_ty}` defined here")),
                    }
                }
            };
            if let Some(label) = label {
                err.span_label(span, label);
            }
        }
        err.emit()
    }

    fn confirm_deferred_closure_call(
        &self,
        call_expr: &'tcx hir::Expr<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
        closure_def_id: LocalDefId,
        fn_sig: ty::FnSig<'tcx>,
    ) -> Ty<'tcx> {
        // `fn_sig` is the *signature* of the closure being called. We
        // don't know the full details yet (`Fn` vs `FnMut` etc), but we
        // do know the types expected for each argument and the return
        // type.

        let expected_arg_tys = self.expected_inputs_for_expected_output(
            call_expr.span,
            expected,
            fn_sig.output(),
            fn_sig.inputs(),
        );

        self.check_argument_types(
            call_expr.span,
            call_expr,
            fn_sig.inputs(),
            expected_arg_tys,
            arg_exprs,
            fn_sig.c_variadic,
            TupleArgumentsFlag::TupleArguments,
            Some(closure_def_id.to_def_id()),
        );

        fn_sig.output()
    }

    #[tracing::instrument(level = "debug", skip(self, span))]
    pub(super) fn enforce_context_effects(
        &self,
        span: Span,
        callee_did: DefId,
        callee_args: GenericArgsRef<'tcx>,
    ) {
        let tcx = self.tcx;

        // fast-reject if callee doesn't have the host effect param (non-const)
        let generics = tcx.generics_of(callee_did);
        let Some(host_effect_index) = generics.host_effect_index else { return };

        let effect = tcx.expected_host_effect_param_for_body(self.body_id);

        trace!(?effect, ?generics, ?callee_args);

        let param = callee_args.const_at(host_effect_index);
        let cause = self.misc(span);
        // We know the type of `effect` to be `bool`, there will be no opaque type inference.
        match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::Yes, effect, param) {
            Ok(infer::InferOk { obligations, value: () }) => {
                self.register_predicates(obligations);
            }
            Err(e) => {
                // FIXME(effects): better diagnostic
                self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit();
            }
        }
    }

    fn confirm_overloaded_call(
        &self,
        call_expr: &'tcx hir::Expr<'tcx>,
        arg_exprs: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
        method_callee: MethodCallee<'tcx>,
    ) -> Ty<'tcx> {
        let output_type = self.check_method_argument_types(
            call_expr.span,
            call_expr,
            Ok(method_callee),
            arg_exprs,
            TupleArgumentsFlag::TupleArguments,
            expected,
        );

        self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee);
        output_type
    }
}

#[derive(Debug)]
pub struct DeferredCallResolution<'tcx> {
    call_expr: &'tcx hir::Expr<'tcx>,
    callee_expr: &'tcx hir::Expr<'tcx>,
    closure_ty: Ty<'tcx>,
    adjustments: Vec<Adjustment<'tcx>>,
    fn_sig: ty::FnSig<'tcx>,
}

impl<'a, 'tcx> DeferredCallResolution<'tcx> {
    pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) {
        debug!("DeferredCallResolution::resolve() {:?}", self);

        // we should not be invoked until the closure kind has been
        // determined by upvar inference
        assert!(fcx.closure_kind(self.closure_ty).is_some());

        // We may now know enough to figure out fn vs fnmut etc.
        match fcx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) {
            Some((autoref, method_callee)) => {
                // One problem is that when we get here, we are going
                // to have a newly instantiated function signature
                // from the call trait. This has to be reconciled with
                // the older function signature we had before. In
                // principle we *should* be able to fn_sigs(), but we
                // can't because of the annoying need for a TypeTrace.
                // (This always bites me, should find a way to
                // refactor it.)
                let method_sig = method_callee.sig;

                debug!("attempt_resolution: method_callee={:?}", method_callee);

                for (method_arg_ty, self_arg_ty) in
                    iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs())
                {
                    fcx.demand_eqtype(self.call_expr.span, *self_arg_ty, *method_arg_ty);
                }

                fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());

                let mut adjustments = self.adjustments;
                adjustments.extend(autoref);
                fcx.apply_adjustments(self.callee_expr, adjustments);

                fcx.write_method_call_and_enforce_effects(
                    self.call_expr.hir_id,
                    self.call_expr.span,
                    method_callee,
                );
            }
            None => {
                span_bug!(
                    self.call_expr.span,
                    "Expected to find a suitable `Fn`/`FnMut`/`FnOnce` implementation for `{}`",
                    self.closure_ty
                )
            }
        }
    }
}
