Skip to main content

rustc_hir_typeck/fn_ctxt/
checks.rs

1use std::ops::Deref;
2use std::{fmt, iter};
3
4use itertools::Itertools;
5use rustc_ast as ast;
6use rustc_data_structures::fx::FxIndexSet;
7use rustc_errors::codes::*;
8use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
9use rustc_hir as hir;
10use rustc_hir::attrs::DivergingBlockBehavior;
11use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
12use rustc_hir::def_id::DefId;
13use rustc_hir::intravisit::Visitor;
14use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal};
15use rustc_hir_analysis::check::potentially_plural_count;
16use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath};
17use rustc_index::IndexVec;
18use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace};
19use rustc_middle::ty::adjustment::AllowTwoPhase;
20use rustc_middle::ty::error::TypeError;
21use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
22use rustc_middle::{bug, span_bug};
23use rustc_session::Session;
24use rustc_session::errors::ExprParenthesesNeeded;
25use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
26use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
27use rustc_trait_selection::infer::InferCtxtExt;
28use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
29use smallvec::SmallVec;
30use tracing::debug;
31
32use crate::Expectation::*;
33use crate::TupleArgumentsFlag::*;
34use crate::coercion::CoerceMany;
35use crate::diagnostics::SuggestPtrNullMut;
36use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
37use crate::gather_locals::Declaration;
38use crate::inline_asm::InlineAsmCtxt;
39use crate::method::probe::IsSuggestion;
40use crate::method::probe::Mode::MethodCall;
41use crate::method::probe::ProbeScope::TraitsInScope;
42use crate::{
43    BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
44    TupleArgumentsFlag, diagnostics, struct_span_code_err,
45};
46
47impl ::std::fmt::Debug for GenericIdx {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("GenericIdx({0})", self.as_u32()))
    }
}rustc_index::newtype_index! {
48    #[orderable]
49    #[debug_format = "GenericIdx({})"]
50    pub(crate) struct GenericIdx {}
51}
52
53/// Outcome of checking arguments that are tupled by "rust-call" or `#[splat]`.
54#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for TupledArgCheckOutcome<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "TupledArgCheckOutcome", "new_err_code", &self.new_err_code,
            "untupled_formal_input_tys", &self.untupled_formal_input_tys,
            "untupled_expected_input_tys", &&self.untupled_expected_input_tys)
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TupledArgCheckOutcome<'tcx> {
    #[inline]
    fn clone(&self) -> TupledArgCheckOutcome<'tcx> {
        TupledArgCheckOutcome {
            new_err_code: ::core::clone::Clone::clone(&self.new_err_code),
            untupled_formal_input_tys: ::core::clone::Clone::clone(&self.untupled_formal_input_tys),
            untupled_expected_input_tys: ::core::clone::Clone::clone(&self.untupled_expected_input_tys),
        }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for TupledArgCheckOutcome<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Option<ErrCode>>;
        let _: ::core::cmp::AssertParamIsEq<Vec<Ty<'tcx>>>;
        let _: ::core::cmp::AssertParamIsEq<Option<Vec<Ty<'tcx>>>>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for TupledArgCheckOutcome<'tcx> {
    #[inline]
    fn eq(&self, other: &TupledArgCheckOutcome<'tcx>) -> bool {
        self.new_err_code == other.new_err_code &&
                self.untupled_formal_input_tys ==
                    other.untupled_formal_input_tys &&
            self.untupled_expected_input_tys ==
                other.untupled_expected_input_tys
    }
}PartialEq)]
55struct TupledArgCheckOutcome<'tcx> {
56    /// The error code to emit if the arguments are not compatible.
57    new_err_code: Option<ErrCode>,
58
59    /// The formal input types after checking.
60    untupled_formal_input_tys: Vec<Ty<'tcx>>,
61
62    /// The expected input types after checking.
63    untupled_expected_input_tys: Option<Vec<Ty<'tcx>>>,
64}
65
66impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
67    pub(in super::super) fn check_casts(&mut self) {
68        let mut deferred_cast_checks = self.root_ctxt.deferred_cast_checks.borrow_mut();
69        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:69",
                        "rustc_hir_typeck::fn_ctxt::checks",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
                        ::tracing_core::__macro_support::Option::Some(69u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_casts: {0} deferred checks",
                                                    deferred_cast_checks.len()) as &dyn Value))])
            });
    } else { ; }
};debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
70        for cast in deferred_cast_checks.drain(..) {
71            let body_id = std::mem::replace(&mut self.body_id, cast.body_id);
72            cast.check(self);
73            self.body_id = body_id;
74        }
75    }
76
77    pub(in super::super) fn check_asms(&self) {
78        let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
79        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:79",
                        "rustc_hir_typeck::fn_ctxt::checks",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
                        ::tracing_core::__macro_support::Option::Some(79u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_asm: {0} deferred checks",
                                                    deferred_asm_checks.len()) as &dyn Value))])
            });
    } else { ; }
};debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
80        for (asm, hir_id) in deferred_asm_checks.drain(..) {
81            let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
82            InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
83        }
84    }
85
86    pub(in super::super) fn check_repeat_exprs(&self) {
87        let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
88        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:88",
                        "rustc_hir_typeck::fn_ctxt::checks",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
                        ::tracing_core::__macro_support::Option::Some(88u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_repeat_exprs: {0} deferred checks",
                                                    deferred_repeat_expr_checks.len()) as &dyn Value))])
            });
    } else { ; }
};debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
89
90        let deferred_repeat_expr_checks = deferred_repeat_expr_checks
91            .drain(..)
92            .flat_map(|(element, element_ty, count)| {
93                // Actual constants as the repeat element are inserted repeatedly instead
94                // of being copied via `Copy`, so we don't need to attempt to structurally
95                // resolve the repeat count which may unnecessarily error.
96                match &element.kind {
97                    hir::ExprKind::ConstBlock(..) => return None,
98                    hir::ExprKind::Path(qpath) => {
99                        let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
100                        if let Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, _) = res
101                        {
102                            return None;
103                        }
104                    }
105                    _ => {}
106                }
107
108                // We want to emit an error if the const is not structurally resolvable
109                // as otherwise we can wind up conservatively proving `Copy` which may
110                // infer the repeat expr count to something that never required `Copy` in
111                // the first place.
112                let count = self.structurally_resolve_const(
113                    element.span,
114                    self.normalize(element.span, Unnormalized::new_wip(count)),
115                );
116
117                // Avoid run on "`NotCopy: Copy` is not implemented" errors when the
118                // repeat expr count is erroneous/unknown. The user might wind up
119                // specifying a repeat count of 0/1.
120                if count.references_error() {
121                    return None;
122                }
123
124                Some((element, element_ty, count))
125            })
126            // We collect to force the side effects of structurally resolving the repeat
127            // count to happen in one go, to avoid side effects from proving `Copy`
128            // affecting whether repeat counts are known or not. If we did not do this we
129            // would get results that depend on the order that we evaluate each repeat
130            // expr's `Copy` check.
131            .collect::<Vec<_>>();
132
133        let enforce_copy_bound = |element: &hir::Expr<'_>, element_ty| {
134            // If someone calls a const fn or constructs a const value, they can extract that
135            // out into a separate constant (or a const block in the future), so we check that
136            // to tell them that in the diagnostic. Does not affect typeck.
137            let is_constable = match element.kind {
138                hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
139                    ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
140                        traits::IsConstable::Fn
141                    }
142                    _ => traits::IsConstable::No,
143                },
144                hir::ExprKind::Path(qpath) => {
145                    match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
146                        Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
147                        _ => traits::IsConstable::No,
148                    }
149                }
150                _ => traits::IsConstable::No,
151            };
152
153            let lang_item = self.tcx.require_lang_item(LangItem::Copy, element.span);
154            let code = traits::ObligationCauseCode::RepeatElementCopy {
155                is_constable,
156                elt_span: element.span,
157            };
158            self.require_type_meets(element_ty, element.span, code, lang_item);
159        };
160
161        for (element, element_ty, count) in deferred_repeat_expr_checks {
162            match count.kind() {
163                ty::ConstKind::Value(val) => {
164                    if val.try_to_target_usize(self.tcx).is_none_or(|count| count > 1) {
165                        enforce_copy_bound(element, element_ty)
166                    } else {
167                        // If the length is 0 or 1 we don't actually copy the element, we either don't create it
168                        // or we just use the one value.
169                    }
170                }
171
172                // If the length is a generic parameter or some rigid alias then conservatively
173                // require `element_ty: Copy` as it may wind up being `>1` after monomorphization.
174                ty::ConstKind::Param(_)
175                | ty::ConstKind::Expr(_)
176                | ty::ConstKind::Placeholder(_)
177                | ty::ConstKind::Alias(_, _) => enforce_copy_bound(element, element_ty),
178
179                ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => {
180                    ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
181                }
182            }
183        }
184    }
185
186    /// Generic function that factors out common logic from function calls,
187    /// method calls and overloaded operators.
188    pub(in super::super) fn check_argument_types(
189        &self,
190        // Span enclosing the call site
191        call_span: Span,
192        // Expression of the call site
193        call_expr: &'tcx hir::Expr<'tcx>,
194        // Types (as defined in the *signature* of the target function)
195        formal_input_tys: &[Ty<'tcx>],
196        formal_output: Ty<'tcx>,
197        // Expected output from the parent expression or statement
198        expectation: Expectation<'tcx>,
199        // The expressions for each provided argument
200        provided_args: &'tcx [hir::Expr<'tcx>],
201        // Whether the function is variadic (e.g. from C)
202        c_variadic: bool,
203        // Whether all the arguments have been bundled in a tuple (ex: closures), or one has been splatted
204        tuple_arguments: TupleArgumentsFlag,
205        // The DefId for the function being called, for better error messages
206        fn_def_id: Option<DefId>,
207        // The generics of the function being called. Only used for splatting
208        callee_generic_args: Option<ty::GenericArgsRef<'tcx>>,
209    ) {
210        let tcx = self.tcx;
211
212        // Conceptually, we've got some number of expected inputs, and some number of provided arguments
213        // and we can form a grid of whether each argument could satisfy a given input:
214        //      in1 | in2 | in3 | ...
215        // arg1  ?  |     |     |
216        // arg2     |  ?  |     |
217        // arg3     |     |  ?  |
218        // ...
219        // Initially, we just check the diagonal, because in the case of correct code
220        // these are the only checks that matter
221        // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
222        // better error messages about invalid method calls.
223
224        // All the input types from the fn signature must outlive the call
225        // so as to validate implied bounds.
226        for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
227            self.register_wf_obligation(
228                fn_input_ty.into(),
229                arg_expr.span,
230                ObligationCauseCode::WellFormed(None),
231            );
232
233            self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
234        }
235
236        // First, let's unify the formal method signature with the expectation eagerly.
237        // We use this to guide coercion inference; its output is "fudged" which means
238        // any remaining type variables are assigned to new, unrelated variables. This
239        // is because the inference guidance here is only speculative.
240        // FIXME(splat): do we need to splat arguments before this type inference?
241        let formal_output = self.resolve_vars_with_obligations(formal_output);
242        let mut expected_input_tys: Option<Vec<_>> = expectation
243            .only_has_type(self)
244            .and_then(|expected_output| {
245                // FIXME(#149379): This operation results in expected input
246                // types which are potentially not well-formed or for whom the
247                // function where-bounds don't actually hold. This results
248                // in weird bugs when later treating these expectations as if
249                // they were actually correct.
250                self.fudge_inference_if_ok(|| {
251                    let ocx = ObligationCtxt::new(self);
252
253                    // Attempt to apply a subtyping relationship between the formal
254                    // return type (likely containing type variables if the function
255                    // is polymorphic) and the expected return type.
256                    // No argument expectations are produced if unification fails.
257                    let origin = self.misc(call_span);
258                    ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
259
260                    // Check the well-formedness of expected input tys, as using ill-formed
261                    // expectation may cause type inference errors, see #150316.
262                    for &ty in formal_input_tys {
263                        ocx.register_obligation(traits::Obligation::new(
264                            self.tcx,
265                            self.misc(call_span),
266                            self.param_env,
267                            ty::ClauseKind::WellFormed(ty.into()),
268                        ));
269                    }
270
271                    if !ocx.try_evaluate_obligations().is_empty() {
272                        return Err(TypeError::Mismatch);
273                    }
274
275                    // Record all the argument types, with the args
276                    // produced from the above subtyping unification.
277                    Ok(Some(
278                        formal_input_tys
279                            .iter()
280                            .map(|&ty| self.resolve_vars_if_possible(ty))
281                            .collect(),
282                    ))
283                })
284                .ok()
285            })
286            .unwrap_or_default();
287
288        let mut err_code = E0061;
289
290        let mut formal_input_tys = formal_input_tys.to_vec();
291
292        // If the arguments should be wrapped in a tuple (ex: closures, splats), unwrap them here
293        if tuple_arguments.is_tupled() {
294            // Caller arguments are tupled before typechecking, starting at the given index.
295            // Tupling makes the callee and caller argument counts match.
296            let outcome = self.check_tupled_arguments(
297                call_span,
298                call_expr,
299                formal_input_tys,
300                provided_args,
301                expected_input_tys,
302                c_variadic,
303                tuple_arguments,
304                fn_def_id,
305                callee_generic_args,
306            );
307            let TupledArgCheckOutcome {
308                new_err_code,
309                untupled_formal_input_tys,
310                untupled_expected_input_tys,
311            } = outcome;
312            if let Some(new_err_code) = new_err_code {
313                err_code = new_err_code;
314            }
315            formal_input_tys = untupled_formal_input_tys;
316            expected_input_tys = untupled_expected_input_tys;
317        }
318
319        // If there are no external expectations at the call site, just use the types from the function defn
320        let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
321            {
    match (&expected_input_tys.len(), &formal_input_tys.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(expected_input_tys.len(), formal_input_tys.len());
322            expected_input_tys
323        } else {
324            formal_input_tys.clone()
325        };
326
327        let minimum_input_count = expected_input_tys.len();
328        let provided_arg_count = provided_args.len();
329
330        // We introduce a helper function to demand that a given argument satisfy a given input
331        // This is more complicated than just checking type equality, as arguments could be coerced
332        // This version writes those types back so further type checking uses the narrowed types
333        let demand_compatible = |idx| {
334            let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
335            let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
336            let provided_arg: &hir::Expr<'tcx> = &provided_args[idx];
337
338            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:338",
                        "rustc_hir_typeck::fn_ctxt::checks",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
                        ::tracing_core::__macro_support::Option::Some(338u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("checking argument {0}: {1:?} = {2:?}",
                                                    idx, provided_arg, formal_input_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
339
340            // We're on the happy path here, so we'll do a more involved check and write back types
341            // To check compatibility, we'll do 3 things:
342            // 1. Unify the provided argument with the expected type
343            let expectation = Expectation::rvalue_hint(self, expected_input_ty);
344
345            // If we are processing first arg of delegation then we could have adjusted it
346            // in `execute_delegation_aware_arguments_check`.
347            let checked_ty = self
348                .tcx
349                .hir_opt_delegation_info(self.body_id)
350                .and_then(|_| self.typeck_results.borrow().node_type_opt(provided_arg.hir_id))
351                .unwrap_or_else(|| self.check_expr_with_expectation(provided_arg, expectation));
352
353            // 2. Coerce to the most detailed type that could be coerced
354            //    to, which is `expected_ty` if `rvalue_hint` returns an
355            //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
356            let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
357
358            // Cause selection errors caused by resolving a single argument to point at the
359            // argument and not the call. This lets us customize the span pointed to in the
360            // fulfillment error to be more accurate.
361            let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
362
363            let coerce_error =
364                self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
365            if coerce_error.is_some() {
366                return Compatibility::Incompatible(coerce_error);
367            }
368
369            // 3. Check if the formal type is actually equal to the checked one
370            //    and register any such obligations for future type checks.
371            let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
372                DefineOpaqueTypes::Yes,
373                formal_input_ty,
374                coerced_ty,
375            );
376
377            // If neither check failed, the types are compatible
378            match formal_ty_error {
379                Ok(InferOk { obligations, value: () }) => {
380                    self.register_predicates(obligations);
381                    Compatibility::Compatible
382                }
383                Err(err) => Compatibility::Incompatible(Some(err)),
384            }
385        };
386
387        // To start, we only care "along the diagonal", where we expect every
388        // provided arg to be in the right spot
389        let mut compatibility_diagonal =
390            ::alloc::vec::from_elem(Compatibility::Incompatible(None),
    provided_args.len())vec![Compatibility::Incompatible(None); provided_args.len()];
391
392        // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
393        // if the wrong number of arguments were supplied, we CAN'T be satisfied,
394        // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
395        // otherwise, they need to be identical, because rust doesn't currently support variadic functions
396        let mut call_appears_satisfied = if c_variadic {
397            provided_arg_count >= minimum_input_count
398        } else {
399            provided_arg_count == minimum_input_count
400        };
401
402        // Check the arguments.
403        // We do this in a pretty awful way: first we type-check any arguments
404        // that are not closures, then we type-check the closures. This is so
405        // that we have more information about the types of arguments when we
406        // type-check the functions. This isn't really the right way to do this.
407        for check_closures in [false, true] {
408            // More awful hacks: before we check argument types, try to do
409            // an "opportunistic" trait resolution of any trait bounds on
410            // the call. This helps coercions.
411            if check_closures {
412                self.select_obligations_where_possible(|_| {})
413            }
414
415            // Check each argument, to satisfy the input it was provided for
416            // Visually, we're traveling down the diagonal of the compatibility matrix
417            for (idx, arg) in provided_args.iter().enumerate() {
418                // Warn only for the first loop (the "no closures" one).
419                // Closure arguments themselves can't be diverging, but
420                // a previous argument can, e.g., `foo(panic!(), || {})`.
421                if !check_closures {
422                    self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
423                }
424
425                // For C-variadic functions, we don't have a declared type for all of
426                // the arguments hence we only do our usual type checking with
427                // the arguments who's types we do know. However, we *can* check
428                // for unreachable expressions (see above).
429                // FIXME: unreachable warning current isn't emitted
430                if idx >= minimum_input_count {
431                    continue;
432                }
433
434                // For this check, we do *not* want to treat async coroutine closures (async blocks)
435                // as proper closures. Doing so would regress type inference when feeding
436                // the return value of an argument-position async block to an argument-position
437                // closure wrapped in a block.
438                // See <https://github.com/rust-lang/rust/issues/112225>.
439                let is_closure = if let ExprKind::Closure(closure) = arg.kind {
440                    !tcx.coroutine_is_async(closure.def_id.to_def_id())
441                } else {
442                    false
443                };
444                if is_closure != check_closures {
445                    continue;
446                }
447
448                let compatible = demand_compatible(idx);
449                let is_compatible = #[allow(non_exhaustive_omitted_patterns)] match compatible {
    Compatibility::Compatible => true,
    _ => false,
}matches!(compatible, Compatibility::Compatible);
450                compatibility_diagonal[idx] = compatible;
451
452                if !is_compatible {
453                    call_appears_satisfied = false;
454                }
455            }
456        }
457
458        if c_variadic && provided_arg_count < minimum_input_count {
459            err_code = E0060;
460        }
461
462        for arg in provided_args.iter().skip(minimum_input_count) {
463            // Make sure we've checked this expr at least once.
464            let arg_ty = self.check_expr(arg);
465
466            // If the function is c-style variadic, we skipped a bunch of arguments
467            // so we need to check those, and write out the types
468            // Ideally this would be folded into the above, for uniform style
469            // but c-variadic is already a corner case
470            if c_variadic {
471                fn variadic_error<'tcx>(
472                    sess: &'tcx Session,
473                    span: Span,
474                    ty: Ty<'tcx>,
475                    cast_ty: &str,
476                ) {
477                    sess.dcx().emit_err(diagnostics::PassToVariadicFunction {
478                        span,
479                        ty,
480                        cast_ty,
481                        sugg_span: span.shrink_to_hi(),
482                        teach: sess.teach(E0617),
483                    });
484                }
485
486                // There are a few types which get autopromoted when passed via varargs
487                // in C but we just error out instead and require explicit casts.
488                //
489                // We use implementations of VaArgSafe as the source of truth. On some embedded
490                // targets, c_double is f32 and c_int/c_uing are i16/u16, and these types implement
491                // VaArgSafe there. On all other targets, these types do not implement VaArgSafe.
492                //
493                // cfg(bootstrap): change the if let to an unwrap.
494                let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
495                if let Some(trait_def_id) = tcx.lang_items().va_arg_safe()
496                    && self
497                        .type_implements_trait(trait_def_id, [arg_ty], self.param_env)
498                        .must_apply_modulo_regions()
499                {
500                    continue;
501                }
502
503                match arg_ty.kind() {
504                    ty::Float(ty::FloatTy::F32) => {
505                        variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
506                    }
507                    ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
508                        variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
509                    }
510                    ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
511                        variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
512                    }
513                    ty::FnDef(..) => {
514                        let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
515                        let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
516
517                        let fn_item_spa = arg.span;
518                        tcx.sess.dcx().emit_err(diagnostics::PassFnItemToVariadicFunction {
519                            span: fn_item_spa,
520                            sugg_span: fn_item_spa.shrink_to_hi(),
521                            replace: fn_ptr,
522                        });
523                    }
524                    _ => {}
525                }
526            }
527        }
528
529        if !call_appears_satisfied {
530            let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
531            let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
532                minimum_input_count
533            } else {
534                provided_arg_count
535            }));
536            if true {
    {
        match (&formal_input_tys.len(), &expected_input_tys.len()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val,
                        ::core::option::Option::Some(format_args!("expected formal_input_tys to be the same size as expected_input_tys")));
                }
            }
        }
    };
};debug_assert_eq!(
537                formal_input_tys.len(),
538                expected_input_tys.len(),
539                "expected formal_input_tys to be the same size as expected_input_tys"
540            );
541            let formal_and_expected_inputs = IndexVec::from_iter(
542                formal_input_tys
543                    .iter()
544                    .copied()
545                    .zip_eq(expected_input_tys.iter().copied())
546                    .map(|vars| self.resolve_vars_if_possible(vars)),
547            );
548
549            self.report_arg_errors(
550                compatibility_diagonal,
551                formal_and_expected_inputs,
552                provided_args,
553                c_variadic,
554                err_code,
555                fn_def_id,
556                call_span,
557                call_expr,
558                tuple_arguments,
559            );
560        }
561    }
562
563    /// Check arguments that are tupled by "rust-call" or `#[splat]`.
564    fn check_tupled_arguments(
565        &self,
566        // Span enclosing the call site
567        call_span: Span,
568        // Expression of the call site
569        call_expr: &'tcx hir::Expr<'tcx>,
570        // Types (as defined in the *signature* of the target function)
571        mut formal_input_tys: Vec<Ty<'tcx>>,
572        // The expressions for each provided argument
573        provided_args: &'tcx [hir::Expr<'tcx>],
574        // The expected input types from the context of the call site
575        mut expected_input_tys: Option<Vec<Ty<'tcx>>>,
576        // Whether the function is variadic (e.g. from C)
577        c_variadic: bool,
578        // Whether all the arguments have been bundled in a tuple (ex: closures).
579        // Splatting is handled separately.
580        tuple_arguments: TupleArgumentsFlag,
581        // The DefId for the function being called, for better error messages
582        fn_def_id: Option<DefId>,
583        // The generics of the function being called. Only used for splatting
584        callee_generic_args: Option<ty::GenericArgsRef<'tcx>>,
585    ) -> TupledArgCheckOutcome<'tcx> {
586        let (first_tupled_arg_index, is_self_splatted) = tuple_arguments.tupled_arg_index();
587        let Some(first_tupled_arg_index) = first_tupled_arg_index else {
588            // If we're not tupling any of the current arguments, we're done.
589            return TupledArgCheckOutcome {
590                new_err_code: None,
591                untupled_formal_input_tys: formal_input_tys,
592                untupled_expected_input_tys: expected_input_tys,
593            };
594        };
595
596        // The argument difference can range from -1 to u16::MAX - 1, so we count the number
597        // of tupled arguments instead.
598        // (An empty argument list becomes a unit tuple in the callee.)
599        // 0: f() -> f(#[splat] _: ())
600        // 1: f(a) -> f(#[splat] _: (A,))
601        // 2: f(a, b) -> f(#[splat] _: (A, B))
602        // The Fn* traits ensure this by construction, and `#[splat]` can only be applied to
603        // an actual argument.
604        let tupled_args_count = (1 + provided_args.len()).checked_sub(formal_input_tys.len());
605        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:605",
                        "rustc_hir_typeck::fn_ctxt::checks",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
                        ::tracing_core::__macro_support::Option::Some(605u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
                        ::tracing_core::field::FieldSet::new(&["first_tupled_arg_index",
                                        "is_self_splatted", "tupled_args_count", "tuple_arguments",
                                        "c_variadic", "provided_args_len", "formal_input_tys_len"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&first_tupled_arg_index)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&is_self_splatted)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&tupled_args_count)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&tuple_arguments)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&c_variadic)
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&provided_args.len())
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&formal_input_tys.len())
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(
606            ?first_tupled_arg_index, ?is_self_splatted,
607            ?tupled_args_count, ?tuple_arguments, ?c_variadic,
608            provided_args_len = ?provided_args.len(), formal_input_tys_len = ?formal_input_tys.len()
609        );
610
611        // If earlier code has modified the FnSig argument list without adjusting the splatted
612        // argument, indexing into the formal input types will panic.
613        if first_tupled_arg_index >= formal_input_tys.len() {
614            ::rustc_middle::util::bug::span_bug_fmt(call_span,
    format_args!("splatted argument index is out of bounds: {2:?} >= {0}, is_self_splatted = {3:?}, tupled_args_count = {4:?}, {5:?}, c_variadic = {6:?}, provided_args: {1}",
        formal_input_tys.len(), provided_args.len(), first_tupled_arg_index,
        is_self_splatted, tupled_args_count, tuple_arguments, c_variadic));span_bug!(
615                call_span,
616                "splatted argument index is out of bounds: {first_tupled_arg_index:?} >= {}, \
617                is_self_splatted = {is_self_splatted:?}, \
618                tupled_args_count = {tupled_args_count:?}, {tuple_arguments:?}, \
619                c_variadic = {c_variadic:?}, provided_args: {}",
620                formal_input_tys.len(),
621                provided_args.len(),
622            );
623        }
624
625        // Keep the type variable if the argument is splatted, so we can force it to be a tuple later.
626        let tuple_type = if tuple_arguments.is_splatted() {
627            let callee_tuple_type =
628                self.resolve_vars_with_obligations(formal_input_tys[first_tupled_arg_index]);
629            if callee_tuple_type.is_ty_var()
630                && let Some(tupled_args_count) = tupled_args_count
631            {
632                // Make the original type variable resolve to a tuple containing new type variables
633                let ocx = ObligationCtxt::new(self);
634                let origin = self.misc(call_span);
635
636                let new_tupled_type = Ty::new_tup_from_iter(
637                    self.tcx,
638                    iter::repeat_with(|| self.next_ty_var(call_span)).take(tupled_args_count),
639                );
640
641                // FIXME(splat): should this be a sub/super type relationship?
642                let ocx_error = ocx.eq(&origin, self.param_env, callee_tuple_type, new_tupled_type);
643                if let Err(ocx_error) = ocx_error {
644                    // FIXME(splat): add a test for this error and the one below, if they are reachable
645                    {
    self.dcx().struct_span_err(call_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("cannot resolve splatted arguments; splatted type parameters must be a tuple or unit type: {0:?}",
                            ocx_error))
                })).with_code(E0277)
}struct_span_code_err!(
646                        self.dcx(),
647                        call_span,
648                        // FIXME(splat): add a new error code before stabilization (and below as well)
649                        E0277,
650                        "cannot resolve splatted arguments; splatted type parameters \
651                        must be a tuple or unit type: {:?}",
652                        ocx_error,
653                    )
654                    .emit();
655                }
656
657                let type_errors = ocx.try_evaluate_obligations();
658                if type_errors.is_empty() {
659                    new_tupled_type
660                } else {
661                    let guar = {
    self.dcx().struct_span_err(call_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("cannot resolve splatted arguments; splatted type parameters must be a tuple or unit type: {0:?}",
                            type_errors))
                })).with_code(E0277)
}struct_span_code_err!(
662                        self.dcx(),
663                        call_span,
664                        E0277,
665                        "cannot resolve splatted arguments; splatted type parameters \
666                        must be a tuple or unit type: {:?}",
667                        type_errors,
668                    )
669                    .emit();
670                    Ty::new_error(self.tcx, guar)
671                }
672            } else {
673                // Otherwise, just let the argument type checker make a suggestion
674                callee_tuple_type
675            }
676        } else {
677            self.structurally_resolve_type(call_span, formal_input_tys[first_tupled_arg_index])
678        };
679
680        // We expected a tuple and got a tuple (or made one ourselves).
681        // If it's not a tuple, we error out in the next block.
682        let mut err_code = None;
683        if let ty::Tuple(detup_formal_arg_tys) = tuple_type.kind() {
684            // Argument length differs
685            // FIXME(splat): update the error code E0057 docs when splat is stabilized
686            if Some(detup_formal_arg_tys.len()) != tupled_args_count {
687                err_code = Some(E0057);
688            }
689            if let Some(ref mut expected_input_tys) = expected_input_tys
690                && let Some(ty) = expected_input_tys.get(first_tupled_arg_index)
691                && let ty::Tuple(detup_expected_arg_tys) = ty.kind()
692            {
693                let substitute_tys = if Some(detup_expected_arg_tys.len()) == tupled_args_count {
694                    detup_expected_arg_tys.iter()
695                } else {
696                    // Just fall back to the formal argument types
697                    detup_formal_arg_tys.iter()
698                };
699
700                expected_input_tys
701                    .splice(first_tupled_arg_index..=first_tupled_arg_index, substitute_tys);
702            } else {
703                expected_input_tys = None;
704            }
705            // If splatting, record this call in a side-table, so MIR lowering can tuple the caller's arguments
706            if tuple_arguments.is_splatted() {
707                // FIXME(const_trait_impl): does not enforce constness yet
708                self.write_splatted_call(
709                    call_expr.hir_id,
710                    call_span,
711                    fn_def_id,
712                    callee_generic_args,
713                    first_tupled_arg_index.try_into().unwrap(),
714                    tupled_args_count.unwrap().try_into().unwrap(),
715                );
716            }
717
718            formal_input_tys.splice(
719                first_tupled_arg_index..=first_tupled_arg_index,
720                detup_formal_arg_tys.iter(),
721            );
722            if let Some(ref expected_input_tys) = expected_input_tys {
723                {
    match (&formal_input_tys.len(), &expected_input_tys.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("incorrectly constructed input type tuples, argument counts must match: tuple_arguments: {0:?}",
                            tuple_arguments)));
            }
        }
    }
}assert_eq!(
724                    formal_input_tys.len(),
725                    expected_input_tys.len(),
726                    "incorrectly constructed input type tuples, argument counts must match: \
727                    tuple_arguments: {tuple_arguments:?}",
728                )
729            }
730        }
731
732        // Otherwise, there's a mismatch during splatting or a rust-call.
733        // So clear out what we're expecting, and set our input types to err_args so we don't
734        // blow up the error messages.
735        let guar =
736            if tuple_arguments == TupleAllCallArgs && !#[allow(non_exhaustive_omitted_patterns)] match tuple_type.kind() {
    ty::Tuple(_) => true,
    _ => false,
}matches!(tuple_type.kind(), ty::Tuple(_)) {
737                let guar = {
    self.dcx().struct_span_err(call_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit"))
                })).with_code(E0059)
}struct_span_code_err!(
738                    self.dcx(),
739                    call_span,
740                    E0059,
741                    "cannot use call notation; the first type parameter \
742                    for the function trait is neither a tuple nor unit"
743                )
744                .emit();
745
746                Some(guar)
747            } else if tuple_arguments.is_splatted() {
748                // If we don't check argument counts here, and there's a subtle bug in the code above,
749                // later compilation stages can fail in unrelated places with confusing errors.
750                if !#[allow(non_exhaustive_omitted_patterns)] match tuple_type.kind() {
    ty::Tuple(_) => true,
    _ => false,
}matches!(tuple_type.kind(), ty::Tuple(_)) {
751                    let spans = if let Some(def_id) = fn_def_id
752                        && let Some(hir_node) = self.tcx.hir_get_if_local(def_id)
753                        && let Some(fn_decl) = hir_node.fn_decl()
754                        && let Some(arg_ty) = fn_decl.inputs.get(first_tupled_arg_index)
755                    {
756                        let arg_def_span = arg_ty.span;
757                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [call_span, arg_def_span]))vec![call_span, arg_def_span]
758                    } else {
759                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [call_span]))vec![call_span]
760                    };
761                    let guar = {
    self.dcx().struct_span_err(spans,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("cannot use splat attribute; the splatted argument type must be a tuple or unit, not a {0:?} ({1:?})",
                            tuple_type.kind(),
                            self.structurally_resolve_type(call_span,
                                    formal_input_tys[first_tupled_arg_index]).kind()))
                })).with_code(E0277)
}struct_span_code_err!(
762                        self.dcx(),
763                        spans,
764                        // FIXME(splat): add a new error code before stabilization
765                        E0277,
766                        "cannot use splat attribute; the splatted argument type \
767                        must be a tuple or unit, not a {:?} ({:?})",
768                        tuple_type.kind(),
769                        self.structurally_resolve_type(
770                            call_span,
771                            formal_input_tys[first_tupled_arg_index]
772                        )
773                        .kind(),
774                    )
775                    .emit();
776
777                    Some(guar)
778                } else if formal_input_tys.len() != provided_args.len() {
779                    // FIXME(splat): suggest alternative argument counts, if there are any
780                    let guar = {
    self.dcx().struct_span_err(call_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("this splatted function takes {0} arguments, but {1} {2} provided",
                            formal_input_tys.len(), provided_args.len(),
                            if provided_args.len() == 1 { "was" } else { "were" }))
                })).with_code(E0057)
}struct_span_code_err!(
781                        self.dcx(),
782                        call_span,
783                        E0057,
784                        "this splatted function takes {} arguments, but {} {} provided",
785                        formal_input_tys.len(),
786                        provided_args.len(),
787                        if provided_args.len() == 1 { "was" } else { "were" },
788                    )
789                    .emit();
790
791                    Some(guar)
792                } else {
793                    None
794                }
795            } else {
796                None
797            };
798
799        if let Some(guar) = guar {
800            TupledArgCheckOutcome {
801                new_err_code: err_code,
802                untupled_formal_input_tys: self.err_args(provided_args.len(), guar),
803                untupled_expected_input_tys: None,
804            }
805        } else {
806            TupledArgCheckOutcome {
807                new_err_code: err_code,
808                untupled_formal_input_tys: formal_input_tys,
809                untupled_expected_input_tys: expected_input_tys,
810            }
811        }
812    }
813
814    /// If `unsized_fn_params` is active, check that unsized values are place expressions. Since
815    /// the removal of `unsized_locals` in <https://github.com/rust-lang/rust/pull/142911> we can't
816    /// store them in MIR locals as temporaries.
817    ///
818    /// If `unsized_fn_params` is inactive, this will be checked in borrowck instead.
819    fn check_place_expr_if_unsized(&self, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
820        if self.tcx.features().unsized_fn_params() && !expr.is_syntactic_place_expr() {
821            self.require_type_is_sized(
822                ty,
823                expr.span,
824                ObligationCauseCode::UnsizedNonPlaceExpr(expr.span),
825            );
826        }
827    }
828
829    fn report_arg_errors(
830        &self,
831        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
832        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
833        provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
834        c_variadic: bool,
835        err_code: ErrCode,
836        fn_def_id: Option<DefId>,
837        call_span: Span,
838        call_expr: &'tcx hir::Expr<'tcx>,
839        // FIXME(splat): when the feature design is settled, improve the errors here
840        tuple_arguments: TupleArgumentsFlag,
841    ) -> ErrorGuaranteed {
842        // Next, let's construct the error
843
844        let mut fn_call_diag_ctxt = FnCallDiagCtxt::new(
845            self,
846            compatibility_diagonal,
847            formal_and_expected_inputs,
848            provided_args,
849            c_variadic,
850            err_code,
851            fn_def_id,
852            call_span,
853            call_expr,
854            tuple_arguments,
855        );
856
857        // First, check if we just need to wrap some arguments in a tuple.
858        if let Some(err) = fn_call_diag_ctxt.check_wrap_args_in_tuple() {
859            return err;
860        }
861
862        if let Some(fallback_error) = fn_call_diag_ctxt.ensure_has_errors() {
863            return fallback_error;
864        }
865
866        // Okay, so here's where it gets complicated in regards to what errors
867        // we emit and how.
868        // There are 3 different "types" of errors we might encounter.
869        //   1) Missing/extra/swapped arguments
870        //   2) Valid but incorrect arguments
871        //   3) Invalid arguments
872        //      - Currently I think this only comes up with `CyclicTy`
873
874        // We first need to go through, remove those from (3) and emit those
875        // as their own error, particularly since they're error code and
876        // message is special. From what I can tell, we *must* emit these
877        // here (vs somewhere prior to this function) since the arguments
878        // become invalid *because* of how they get used in the function.
879        // It is what it is.
880        if let Some(err) = fn_call_diag_ctxt.filter_out_invalid_arguments()
881            && fn_call_diag_ctxt.errors.is_empty()
882        {
883            // We're done if we found errors, but we already emitted them.
884            return err;
885        }
886
887        if !!fn_call_diag_ctxt.errors.is_empty() {
    ::core::panicking::panic("assertion failed: !fn_call_diag_ctxt.errors.is_empty()")
};assert!(!fn_call_diag_ctxt.errors.is_empty());
888
889        // Last special case: if there is only one "Incompatible" error, just emit that
890        if let Some(err) = fn_call_diag_ctxt.check_single_incompatible() {
891            return err;
892        }
893
894        // Okay, now that we've emitted the special errors separately, we
895        // are only left missing/extra/swapped and mismatched arguments, both
896        // can be collated pretty easily if needed.
897
898        // Special case, we found an extra argument is provided, which is very common in practice.
899        // but there is a obviously better removing suggestion compared to the current one,
900        // try to find the argument with Error type, if we removed it all the types will become good,
901        // then we will replace the current suggestion.
902        fn_call_diag_ctxt.maybe_optimize_extra_arg_suggestion();
903
904        let mut err = fn_call_diag_ctxt.initial_final_diagnostic();
905        fn_call_diag_ctxt.suggest_confusable(&mut err);
906
907        // As we encounter issues, keep track of what we want to provide for the suggestion.
908
909        let (mut suggestions, labels, suggestion_text) =
910            fn_call_diag_ctxt.labels_and_suggestion_text(&mut err);
911
912        fn_call_diag_ctxt.label_generic_mismatches(&mut err);
913        fn_call_diag_ctxt.append_arguments_changes(&mut suggestions);
914
915        // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
916        if labels.len() <= 5 {
917            for (span, label) in labels {
918                err.span_label(span, label);
919            }
920        }
921
922        // Call out where the function is defined
923        fn_call_diag_ctxt.label_fn_like(
924            &mut err,
925            fn_def_id,
926            fn_call_diag_ctxt.callee_ty,
927            call_expr,
928            None,
929            None,
930            &fn_call_diag_ctxt.matched_inputs,
931            &fn_call_diag_ctxt.formal_and_expected_inputs,
932            fn_call_diag_ctxt.call_metadata.is_method,
933            tuple_arguments,
934        );
935
936        // And add a suggestion block for all of the parameters
937        if let Some(suggestion_message) =
938            FnCallDiagCtxt::format_suggestion_text(&mut err, suggestions, suggestion_text)
939            && !fn_call_diag_ctxt.call_is_in_macro()
940        {
941            let (suggestion_span, suggestion_code) = fn_call_diag_ctxt.suggestion_code();
942
943            err.span_suggestion_verbose(
944                suggestion_span,
945                suggestion_message,
946                suggestion_code,
947                Applicability::HasPlaceholders,
948            );
949        }
950
951        err.emit()
952    }
953
954    fn suggest_ptr_null_mut(
955        &self,
956        expected_ty: Ty<'tcx>,
957        provided_ty: Ty<'tcx>,
958        arg: &hir::Expr<'tcx>,
959        err: &mut Diag<'_>,
960    ) {
961        if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
962            && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
963            && let hir::ExprKind::Call(callee, _) = arg.kind
964            && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
965            && let Res::Def(_, def_id) = path.res
966            && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
967        {
968            // The user provided `ptr::null()`, but the function expects
969            // `ptr::null_mut()`.
970            err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
971        }
972    }
973
974    // AST fragment checking
975    pub(in super::super) fn check_expr_lit(
976        &self,
977        lit: &hir::Lit,
978        lint_id: HirId,
979        expected: Expectation<'tcx>,
980    ) -> Ty<'tcx> {
981        let tcx = self.tcx;
982
983        match lit.node {
984            ast::LitKind::Str(..) => Ty::new_static_str(tcx),
985            ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
986                tcx,
987                tcx.lifetimes.re_static,
988                Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
989            ),
990            ast::LitKind::Byte(_) => tcx.types.u8,
991            ast::LitKind::Char(_) => tcx.types.char,
992            ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, t),
993            ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, t),
994            ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
995                let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
996                    ty::Int(_) | ty::Uint(_) => Some(ty),
997                    // These exist to direct casts like `0x61 as char` to use
998                    // the right integer type to cast from, instead of falling back to
999                    // i32 due to no further constraints.
1000                    ty::Char => Some(tcx.types.u8),
1001                    ty::RawPtr(..) => Some(tcx.types.usize),
1002                    ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1003                    &ty::Pat(base, _) if base.is_integral() => {
1004                        let layout = tcx
1005                            .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1006                            .ok()?;
1007                        if !!layout.uninhabited {
    ::core::panicking::panic("assertion failed: !layout.uninhabited")
};assert!(!layout.uninhabited);
1008
1009                        match layout.backend_repr {
1010                            rustc_abi::BackendRepr::Scalar(scalar) => {
1011                                scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1012                            }
1013                            _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1014                        }
1015                    }
1016                    _ => None,
1017                });
1018                opt_ty.unwrap_or_else(|| self.next_int_var())
1019            }
1020            ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => Ty::new_float(tcx, t),
1021            ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1022                let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1023                    ty::Float(_) => Some(ty),
1024                    _ => None,
1025                });
1026                opt_ty.unwrap_or_else(|| self.next_float_var(lit.span, Some(lint_id)))
1027            }
1028            ast::LitKind::Bool(_) => tcx.types.bool,
1029            ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1030                tcx,
1031                tcx.lifetimes.re_static,
1032                tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, lit.span)).skip_binder(),
1033            ),
1034            ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1035        }
1036    }
1037
1038    pub(crate) fn check_struct_path(
1039        &self,
1040        qpath: &QPath<'tcx>,
1041        hir_id: HirId,
1042    ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1043        let path_span = qpath.span();
1044        let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1045        let variant = match def {
1046            Res::Err => {
1047                let guar =
1048                    self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1049                self.set_tainted_by_errors(guar);
1050                return Err(guar);
1051            }
1052            Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1053                Some(adt) => {
1054                    Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1055                }
1056                _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type: {0:?}",
        ty.normalized))bug!("unexpected type: {:?}", ty.normalized),
1057            },
1058            Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1059            | Res::SelfTyParam { .. }
1060            | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1061                Some(adt) if !adt.is_enum() => {
1062                    Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1063                }
1064                _ => None,
1065            },
1066            _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected definition: {0:?}",
        def))bug!("unexpected definition: {:?}", def),
1067        };
1068
1069        if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1070            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:1070",
                        "rustc_hir_typeck::fn_ctxt::checks",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
                        ::tracing_core::__macro_support::Option::Some(1070u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("check_struct_path: did={0:?} args={1:?}",
                                                    did, args) as &dyn Value))])
            });
    } else { ; }
};debug!("check_struct_path: did={:?} args={:?}", did, args);
1071
1072            // Register type annotation.
1073            self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1074
1075            // Check bounds on type arguments used in the path.
1076            self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1077
1078            Ok((variant, ty.normalized))
1079        } else {
1080            Err(match *ty.normalized.kind() {
1081                ty::Error(guar) => {
1082                    // E0071 might be caused by a spelling error, which will have
1083                    // already caused an error message and probably a suggestion
1084                    // elsewhere. Refrain from emitting more unhelpful errors here
1085                    // (issue #88844).
1086                    guar
1087                }
1088                _ => {
    self.dcx().struct_span_err(path_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("expected struct, variant or union type, found {0}",
                            ty.normalized.sort_string(self.tcx)))
                })).with_code(E0071)
}struct_span_code_err!(
1089                    self.dcx(),
1090                    path_span,
1091                    E0071,
1092                    "expected struct, variant or union type, found {}",
1093                    ty.normalized.sort_string(self.tcx)
1094                )
1095                .with_span_label(path_span, "not a struct")
1096                .emit(),
1097            })
1098        }
1099    }
1100
1101    fn check_decl_initializer(
1102        &self,
1103        hir_id: HirId,
1104        pat: &'tcx hir::Pat<'tcx>,
1105        init: &'tcx hir::Expr<'tcx>,
1106    ) -> Ty<'tcx> {
1107        // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
1108        // for #42640 (default match binding modes).
1109        //
1110        // See #44848.
1111        let ref_bindings = pat.contains_explicit_ref_binding();
1112
1113        let local_ty = self.local_ty(init.span, hir_id);
1114        if let Some(m) = ref_bindings {
1115            // Somewhat subtle: if we have a `ref` binding in the pattern,
1116            // we want to avoid introducing coercions for the RHS. This is
1117            // both because it helps preserve sanity and, in the case of
1118            // ref mut, for soundness (issue #23116). In particular, in
1119            // the latter case, we need to be clear that the type of the
1120            // referent for the reference that results is *equal to* the
1121            // type of the place it is referencing, and not some
1122            // supertype thereof.
1123            let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1124            if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1125                self.emit_type_mismatch_suggestions(
1126                    &mut diag,
1127                    init.peel_drop_temps(),
1128                    init_ty,
1129                    local_ty,
1130                    None,
1131                    None,
1132                );
1133                diag.emit();
1134            }
1135            init_ty
1136        } else {
1137            self.check_expr_coercible_to_type(init, local_ty, None)
1138        }
1139    }
1140
1141    pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1142        // Determine and write the type which we'll check the pattern against.
1143        let decl_ty = self.local_ty(decl.span, decl.hir_id);
1144
1145        // Type check the initializer.
1146        if let Some(init) = decl.init {
1147            let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1148            self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1149        }
1150
1151        // Does the expected pattern type originate from an expression and what is the span?
1152        let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1153            (Some(ty), _) => (None, Some(ty.span)), // Bias towards the explicit user type.
1154            (_, Some(init)) => {
1155                (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1156            } // No explicit type; so use the scrutinee.
1157            _ => (None, None), // We have `let $pat;`, so the expected type is unconstrained.
1158        };
1159
1160        // Type check the pattern. Override if necessary to avoid knock-on errors.
1161        self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1162        let pat_ty = self.node_ty(decl.pat.hir_id);
1163        self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1164
1165        if let Some(blk) = decl.origin.try_get_else() {
1166            let previous_diverges = self.diverges.get();
1167            let else_ty = self.check_expr_block(blk, NoExpectation);
1168            let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1169            if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1170            {
1171                err.emit();
1172            }
1173            self.diverges.set(previous_diverges);
1174        }
1175        decl_ty
1176    }
1177
1178    /// Type check a `let` statement.
1179    fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1180        GatherLocalsVisitor::gather_from_local(self, local);
1181
1182        let ty = self.check_decl(local.into());
1183        self.write_ty(local.hir_id, ty);
1184        if local.pat.is_never_pattern() {
1185            self.diverges.set(Diverges::Always {
1186                span: local.pat.span,
1187                custom_note: Some("any code following a never pattern is unreachable"),
1188            });
1189        }
1190    }
1191
1192    fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1193        // Don't do all the complex logic below for `DeclItem`.
1194        match stmt.kind {
1195            hir::StmtKind::Item(..) => return,
1196            hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1197        }
1198
1199        self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1200
1201        // Hide the outer diverging flags.
1202        let old_diverges = self.diverges.replace(Diverges::Maybe);
1203
1204        match stmt.kind {
1205            hir::StmtKind::Let(l) => {
1206                self.check_decl_local(l);
1207            }
1208            // Ignore for now.
1209            hir::StmtKind::Item(_) => {}
1210            hir::StmtKind::Expr(expr) => {
1211                // Check with expected type of `()`.
1212                self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1213                    if self.is_next_stmt_expr_continuation(stmt.hir_id)
1214                        && let hir::ExprKind::Match(..) | hir::ExprKind::If(..) = expr.kind
1215                    {
1216                        // We have something like `match () { _ => true } && true`. Suggest
1217                        // wrapping in parentheses. We find the statement or expression
1218                        // following the `match` (`&& true`) and see if it is something that
1219                        // can reasonably be interpreted as a binop following an expression.
1220                        err.subdiagnostic(ExprParenthesesNeeded::surrounding(expr.span));
1221                    } else if expr.can_have_side_effects() {
1222                        self.suggest_semicolon_at_end(expr.span, err);
1223                    }
1224                });
1225            }
1226            hir::StmtKind::Semi(expr) => {
1227                let ty = self.check_expr(expr);
1228                self.check_place_expr_if_unsized(ty, expr);
1229            }
1230        }
1231
1232        // Combine the diverging and `has_error` flags.
1233        self.diverges.set(self.diverges.get() | old_diverges);
1234    }
1235
1236    pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1237        let unit = self.tcx.types.unit;
1238        let ty = self.check_expr_block(blk, ExpectHasType(unit));
1239
1240        // if the block produces a `!` value, that can always be
1241        // (effectively) coerced to unit.
1242        if !ty.is_never() {
1243            self.demand_suptype(blk.span, unit, ty);
1244        }
1245    }
1246
1247    pub(in super::super) fn check_expr_block(
1248        &self,
1249        blk: &'tcx hir::Block<'tcx>,
1250        expected: Expectation<'tcx>,
1251    ) -> Ty<'tcx> {
1252        // In some cases, blocks have just one exit, but other blocks
1253        // can be targeted by multiple breaks. This can happen both
1254        // with labeled blocks as well as when we desugar
1255        // a `try { ... }` expression.
1256        //
1257        // Example 1:
1258        //
1259        //    'a: { if true { break 'a Err(()); } Ok(()) }
1260        //
1261        // Here we would wind up with two coercions, one from
1262        // `Err(())` and the other from the tail expression
1263        // `Ok(())`. If the tail expression is omitted, that's a
1264        // "forced unit" -- unless the block diverges, in which
1265        // case we can ignore the tail expression (e.g., `'a: {
1266        // break 'a 22; }` would not force the type of the block
1267        // to be `()`).
1268        let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1269        let coerce = CoerceMany::new(coerce_to_ty);
1270
1271        let prev_diverges = self.diverges.get();
1272        let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1273
1274        let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1275            for s in blk.stmts {
1276                self.check_stmt(s);
1277            }
1278
1279            // check the tail expression **without** holding the
1280            // `enclosing_breakables` lock below.
1281            let tail_expr_ty =
1282                blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1283
1284            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1285            let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1286            let coerce = ctxt.coerce.as_mut().unwrap();
1287            if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1288                let span = self.get_expr_coercion_span(tail_expr);
1289                let cause = self.cause(
1290                    span,
1291                    ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1292                );
1293                let ty_for_diagnostic = coerce.merged_ty();
1294                // We use coerce_inner here because we want to augment the error
1295                // suggesting to wrap the block in square brackets if it might've
1296                // been mistaken array syntax
1297                coerce.coerce_inner(
1298                    self,
1299                    &cause,
1300                    Some(tail_expr),
1301                    tail_expr_ty,
1302                    |diag| {
1303                        self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1304                    },
1305                    false,
1306                );
1307            } else {
1308                // Subtle: if there is no explicit tail expression,
1309                // that is typically equivalent to a tail expression
1310                // of `()` -- except if the block diverges. In that
1311                // case, there is no value supplied from the tail
1312                // expression (assuming there are no other breaks,
1313                // this implies that the type of the block will be
1314                // `!`).
1315                //
1316                // #41425 -- label the implicit `()` as being the
1317                // "found type" here, rather than the "expected type".
1318                if !self.diverges.get().is_always()
1319                    || #[allow(non_exhaustive_omitted_patterns)] match self.diverging_block_behavior
    {
    DivergingBlockBehavior::Unit => true,
    _ => false,
}matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1320                {
1321                    // #50009 -- Do not point at the entire fn block span, point at the return type
1322                    // span, as it is the cause of the requirement, and
1323                    // `consider_hint_about_removing_semicolon` will point at the last expression
1324                    // if it were a relevant part of the error. This improves usability in editors
1325                    // that highlight errors inline.
1326                    let mut sp = blk.span;
1327                    let mut fn_span = None;
1328                    if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1329                        let ret_sp = decl.output.span();
1330                        if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1331                            // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
1332                            // output would otherwise be incorrect and even misleading. Make sure
1333                            // the span we're aiming at correspond to a `fn` body.
1334                            if block_sp == blk.span {
1335                                sp = ret_sp;
1336                                fn_span = self.tcx.def_ident_span(fn_def_id);
1337                            }
1338                        }
1339                    }
1340                    coerce.coerce_forced_unit(
1341                        self,
1342                        &self.misc(sp),
1343                        |err| {
1344                            if let Some(expected_ty) = expected.only_has_type(self) {
1345                                if blk.stmts.is_empty() && blk.expr.is_none() {
1346                                    self.suggest_boxing_when_appropriate(
1347                                        err,
1348                                        blk.span,
1349                                        blk.hir_id,
1350                                        expected_ty,
1351                                        self.tcx.types.unit,
1352                                    );
1353                                }
1354                                if !self.err_ctxt().consider_removing_semicolon(
1355                                    blk,
1356                                    expected_ty,
1357                                    err,
1358                                ) {
1359                                    self.err_ctxt().consider_returning_binding(
1360                                        blk,
1361                                        expected_ty,
1362                                        err,
1363                                    );
1364                                }
1365                                if expected_ty == self.tcx.types.bool {
1366                                    // If this is caused by a missing `let` in a `while let`,
1367                                    // silence this redundant error, as we already emit E0070.
1368
1369                                    // Our block must be a `assign desugar local; assignment`
1370                                    if let hir::Block {
1371                                        stmts:
1372                                            [
1373                                                hir::Stmt {
1374                                                    kind:
1375                                                        hir::StmtKind::Let(hir::LetStmt {
1376                                                            source: hir::LocalSource::AssignDesugar,
1377                                                            ..
1378                                                        }),
1379                                                    ..
1380                                                },
1381                                                hir::Stmt {
1382                                                    kind:
1383                                                        hir::StmtKind::Expr(hir::Expr {
1384                                                            kind: hir::ExprKind::Assign(lhs, ..),
1385                                                            ..
1386                                                        }),
1387                                                    ..
1388                                                },
1389                                            ],
1390                                        ..
1391                                    } = blk
1392                                    {
1393                                        self.comes_from_while_condition(blk.hir_id, |_| {
1394                                            // We cannot suppress the error if the LHS of assignment
1395                                            // is a syntactic place expression because E0070 would
1396                                            // not be emitted by `check_lhs_assignable`.
1397                                            let res = self.typeck_results.borrow().expr_ty_opt(lhs);
1398
1399                                            if !lhs.is_syntactic_place_expr()
1400                                                || res.references_error()
1401                                            {
1402                                                err.downgrade_to_delayed_bug();
1403                                            }
1404                                        })
1405                                    }
1406                                }
1407                            }
1408                            if let Some(fn_span) = fn_span {
1409                                err.span_label(
1410                                    fn_span,
1411                                    "implicitly returns `()` as its body has no tail or `return` \
1412                                     expression",
1413                                );
1414                            }
1415                        },
1416                        false,
1417                    );
1418                }
1419            }
1420        });
1421
1422        if ctxt.may_break {
1423            // If we can break from the block, then the block's exit is always reachable
1424            // (... as long as the entry is reachable) - regardless of the tail of the block.
1425            self.diverges.set(prev_diverges);
1426        }
1427
1428        let ty = ctxt.coerce.unwrap().complete(self);
1429
1430        self.write_ty(blk.hir_id, ty);
1431
1432        ty
1433    }
1434
1435    fn parent_item_span(&self, id: HirId) -> Option<Span> {
1436        let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
1437        match node {
1438            Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
1439            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1440                let body = self.tcx.hir_body(body_id);
1441                if let ExprKind::Block(block, _) = &body.value.kind {
1442                    return Some(block.span);
1443                }
1444            }
1445            _ => {}
1446        }
1447        None
1448    }
1449
1450    /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
1451    /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
1452    /// when given code like the following:
1453    /// ```text
1454    /// if false { return 0i32; } else { 1u32 }
1455    /// //                               ^^^^ point at this instead of the whole `if` expression
1456    /// ```
1457    fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1458        let check_in_progress = |elem: &hir::Expr<'_>| {
1459            self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
1460                |_| match elem.kind {
1461                    // Point at the tail expression when possible.
1462                    hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
1463                    _ => elem.span,
1464                },
1465            )
1466        };
1467
1468        if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
1469            && let Some(rslt) = check_in_progress(el)
1470        {
1471            return rslt;
1472        }
1473
1474        if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1475            let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1476            if let Some(span) = iter.next() {
1477                if iter.next().is_none() {
1478                    return span;
1479                }
1480            }
1481        }
1482
1483        expr.span
1484    }
1485
1486    fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
1487        if let Err(guar) = ty.error_reported() {
1488            struct OverwritePatternsWithError {
1489                pat_hir_ids: Vec<hir::HirId>,
1490            }
1491            impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
1492                fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
1493                    self.pat_hir_ids.push(p.hir_id);
1494                    hir::intravisit::walk_pat(self, p);
1495                }
1496            }
1497            // Override the types everywhere with `err()` to avoid knock on errors.
1498            let err = Ty::new_error(self.tcx, guar);
1499            self.write_ty(hir_id, err);
1500            self.write_ty(pat.hir_id, err);
1501            let mut visitor = OverwritePatternsWithError { pat_hir_ids: ::alloc::vec::Vec::new()vec![] };
1502            hir::intravisit::walk_pat(&mut visitor, pat);
1503            // Mark all the subpatterns as `{type error}` as well. This allows errors for specific
1504            // subpatterns to be silenced.
1505            for hir_id in visitor.pat_hir_ids {
1506                self.write_ty(hir_id, err);
1507            }
1508            self.locals.borrow_mut().insert(hir_id, err);
1509            self.locals.borrow_mut().insert(pat.hir_id, err);
1510        }
1511    }
1512
1513    // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
1514    // The newly resolved definition is written into `type_dependent_defs`.
1515    fn finish_resolving_struct_path(
1516        &self,
1517        qpath: &QPath<'tcx>,
1518        path_span: Span,
1519        hir_id: HirId,
1520    ) -> (Res, LoweredTy<'tcx>) {
1521        let ResolvedStructPath { res: result, ty } =
1522            self.lowerer().lower_path_for_struct_expr(*qpath, path_span, hir_id);
1523        match *qpath {
1524            QPath::Resolved(_, path) => (path.res, LoweredTy::from_raw(self, path_span, ty)),
1525            QPath::TypeRelative(_, _) => {
1526                let ty = LoweredTy::from_raw(self, path_span, ty);
1527                let resolution =
1528                    result.map(|res: Res| (self.tcx().def_kind(res.def_id()), res.def_id()));
1529
1530                // Write back the new resolution.
1531                self.write_resolution(hir_id, resolution);
1532
1533                (result.unwrap_or(Res::Err), ty)
1534            }
1535        }
1536    }
1537
1538    /// Given a vector of fulfillment errors, try to adjust the spans of the
1539    /// errors to more accurately point at the cause of the failure.
1540    ///
1541    /// This applies to calls, methods, and struct expressions. This will also
1542    /// try to deduplicate errors that are due to the same cause but might
1543    /// have been created with different [`ObligationCause`][traits::ObligationCause]s.
1544    pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
1545        &self,
1546        errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1547    ) {
1548        // Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
1549        // other errors that have the same span and predicate can also get fixed,
1550        // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
1551        // This is important since if we adjust one span but not the other, then
1552        // we will have "duplicated" the error on the UI side.
1553        let mut remap_cause = FxIndexSet::default();
1554        let mut not_adjusted = ::alloc::vec::Vec::new()vec![];
1555
1556        for error in errors {
1557            let before_span = error.obligation.cause.span;
1558            if self.adjust_fulfillment_error_for_expr_obligation(error)
1559                || before_span != error.obligation.cause.span
1560            {
1561                remap_cause.insert((
1562                    before_span,
1563                    error.obligation.predicate,
1564                    error.obligation.cause.clone(),
1565                ));
1566            } else {
1567                // If it failed to be adjusted once around, it may be adjusted
1568                // via the "remap cause" mapping the second time...
1569                not_adjusted.push(error);
1570            }
1571        }
1572
1573        // Adjust any other errors that come from other cause codes, when these
1574        // errors are of the same predicate as one we successfully adjusted, and
1575        // when their spans overlap (suggesting they're due to the same root cause).
1576        //
1577        // This is because due to normalization, we often register duplicate
1578        // obligations with misc obligations that are basically impossible to
1579        // line back up with a useful WhereClauseInExpr.
1580        for error in not_adjusted {
1581            for (span, predicate, cause) in &remap_cause {
1582                if *predicate == error.obligation.predicate
1583                    && span.contains(error.obligation.cause.span)
1584                {
1585                    error.obligation.cause = cause.clone();
1586                    continue;
1587                }
1588            }
1589        }
1590    }
1591
1592    fn label_fn_like(
1593        &self,
1594        err: &mut Diag<'_>,
1595        callable_def_id: Option<DefId>,
1596        callee_ty: Option<Ty<'tcx>>,
1597        call_expr: &'tcx hir::Expr<'tcx>,
1598        expected_ty: Option<Ty<'tcx>>,
1599        // A specific argument should be labeled, instead of all of them
1600        expected_idx: Option<usize>,
1601        matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1602        formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1603        is_method: bool,
1604        tuple_arguments: TupleArgumentsFlag,
1605    ) {
1606        let Some(mut def_id) = callable_def_id else {
1607            return;
1608        };
1609
1610        // If we're calling a method of a Fn/FnMut/FnOnce trait object implicitly
1611        // (eg invoking a closure) we want to point at the underlying callable,
1612        // not the method implicitly invoked (eg call_once).
1613        // TupleAllCallArgs is set only when this is an implicit call `my_closure(...)` rather
1614        // than explicit `my_closure.call(...)`.
1615        if tuple_arguments == TupleAllCallArgs
1616            && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1617            // Since this is an associated item, it might point at either an impl or a trait item.
1618            // We want it to always point to the trait item.
1619            // If we're pointing at an inherent function, we don't need to do anything,
1620            // so we fetch the parent and verify if it's a trait item.
1621            && let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
1622            && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1623            // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
1624            && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
1625            && let Some(callee_ty) = callee_ty
1626        {
1627            let callee_ty = callee_ty.peel_refs();
1628            match *callee_ty.kind() {
1629                ty::Param(param) => {
1630                    let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
1631                    if param.kind.is_synthetic() {
1632                        // if it's `impl Fn() -> ..` then just fall down to the def-id based logic
1633                        def_id = param.def_id;
1634                    } else {
1635                        // Otherwise, find the predicate that makes this generic callable,
1636                        // and point at that.
1637                        let instantiated = self
1638                            .tcx
1639                            .explicit_predicates_of(self.body_id)
1640                            .instantiate_identity(self.tcx);
1641                        // FIXME(compiler-errors): This could be problematic if something has two
1642                        // fn-like predicates with different args, but callable types really never
1643                        // do that, so it's OK.
1644                        for (predicate, span) in instantiated {
1645                            if let ty::ClauseKind::Trait(pred) =
1646                                predicate.skip_norm_wip().kind().skip_binder()
1647                                && pred.self_ty().peel_refs() == callee_ty
1648                                && self.tcx.is_fn_trait(pred.def_id())
1649                            {
1650                                err.span_note(span, "callable defined here");
1651                                return;
1652                            }
1653                        }
1654                    }
1655                }
1656                ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: new_def_id }, .. })
1657                | ty::Closure(new_def_id, _)
1658                | ty::FnDef(new_def_id, _) => {
1659                    def_id = new_def_id;
1660                }
1661                _ => {
1662                    // Look for a user-provided impl of a `Fn` trait, and point to it.
1663                    let new_def_id = self.probe(|_| {
1664                        let trait_ref = ty::TraitRef::new(
1665                            self.tcx,
1666                            self.tcx.fn_trait_kind_to_def_id(call_kind)?,
1667                            [callee_ty, self.next_ty_var(DUMMY_SP)],
1668                        );
1669                        let obligation = traits::Obligation::new(
1670                            self.tcx,
1671                            traits::ObligationCause::dummy(),
1672                            self.param_env,
1673                            trait_ref,
1674                        );
1675                        match SelectionContext::new(self).select(&obligation) {
1676                            Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1677                                Some(impl_source.impl_def_id)
1678                            }
1679                            _ => None,
1680                        }
1681                    });
1682                    let Some(new_def_id) = new_def_id else { return };
1683                    def_id = new_def_id;
1684                }
1685            }
1686        }
1687
1688        if let Some(def_span) = self.tcx.def_ident_span(def_id)
1689            && !def_span.is_dummy()
1690        {
1691            let mut spans: MultiSpan = def_span.into();
1692            if let Some((params_with_generics, hir_generics)) =
1693                self.get_hir_param_info(def_id, is_method)
1694            {
1695                struct MismatchedParam<'a> {
1696                    idx: ExpectedIdx,
1697                    generic: GenericIdx,
1698                    param: &'a FnParam<'a>,
1699                    deps: SmallVec<[ExpectedIdx; 4]>,
1700                }
1701
1702                // FIXME(splat): fix the generic mismatch earlier, so it doesn't reach here
1703                if !tuple_arguments.is_splatted() {
1704                    if true {
    {
        match (&params_with_generics.len(), &matched_inputs.len()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
1705                }
1706                // Gather all mismatched parameters with generics.
1707                let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
1708                let mut use_splat_fallback = false;
1709                if let Some(expected_idx) = expected_idx {
1710                    let expected_idx = ExpectedIdx::from_usize(expected_idx);
1711                    match params_with_generics.get(expected_idx) {
1712                        Some(&(Some(expected_generic), ref expected_param)) => mismatched_params
1713                            .push(MismatchedParam {
1714                                idx: expected_idx,
1715                                generic: expected_generic,
1716                                param: expected_param,
1717                                deps: SmallVec::new(),
1718                            }),
1719                        Some((None, expected_param)) => {
1720                            // Still mark the mismatched parameter
1721                            spans.push_span_label(expected_param.span(), "");
1722                        }
1723                        None => {
1724                            if tuple_arguments.is_splatted() {
1725                                // FIXME(splat): when the arg is splatted, adjust its index, to handle the type mismatch properly
1726                                use_splat_fallback = true;
1727                            } else {
1728                                ::rustc_middle::util::bug::span_bug_fmt(self.tcx.def_span(def_id),
    format_args!("arg index {0} out of bounds for method with {1} inputs",
        expected_idx.as_usize(), params_with_generics.len()));span_bug!(
1729                                    self.tcx.def_span(def_id),
1730                                    "arg index {} out of bounds for method with {} inputs",
1731                                    expected_idx.as_usize(),
1732                                    params_with_generics.len(),
1733                                );
1734                            }
1735                        }
1736                    };
1737                }
1738
1739                if expected_idx.is_none() || use_splat_fallback {
1740                    mismatched_params.extend(
1741                        params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
1742                            |((idx, &(generic, ref param)), matched_idx)| {
1743                                if matched_idx.is_some() {
1744                                    None
1745                                } else if let Some(generic) = generic {
1746                                    Some(MismatchedParam {
1747                                        idx,
1748                                        generic,
1749                                        param,
1750                                        deps: SmallVec::new(),
1751                                    })
1752                                } else {
1753                                    // Still mark mismatched parameters
1754                                    spans.push_span_label(param.span(), "");
1755                                    None
1756                                }
1757                            },
1758                        ),
1759                    );
1760                }
1761
1762                if !mismatched_params.is_empty() {
1763                    // For each mismatched parameter, create a two-way link to each matched parameter
1764                    // of the same type.
1765                    let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
1766                        |_| SmallVec::<[u32; 4]>::new(),
1767                        params_with_generics.len(),
1768                    );
1769                    let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
1770                        |_| SmallVec::<[ExpectedIdx; 4]>::new(),
1771                        hir_generics.params.len(),
1772                    );
1773                    for (idx, param) in mismatched_params.iter_mut().enumerate() {
1774                        for ((other_idx, &(other_generic, _)), &other_matched_idx) in
1775                            params_with_generics.iter_enumerated().zip(matched_inputs)
1776                        {
1777                            if other_generic == Some(param.generic) && other_matched_idx.is_some() {
1778                                generic_uses[param.generic].extend([param.idx, other_idx]);
1779                                dependants[other_idx].push(idx as u32);
1780                                param.deps.push(other_idx);
1781                            }
1782                        }
1783                    }
1784
1785                    // Highlight each mismatched type along with a note about which other parameters
1786                    // the type depends on (if any).
1787                    for param in &mismatched_params {
1788                        if let Some(deps_list) = listify(&param.deps, |&dep| {
1789                            params_with_generics[dep].1.display(dep.as_usize()).to_string()
1790                        }) {
1791                            spans.push_span_label(
1792                                param.param.span(),
1793                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this parameter needs to match the {0} type of {1}",
                self.resolve_vars_if_possible(formal_and_expected_inputs[param.deps[0]].1).sort_string(self.tcx),
                deps_list))
    })format!(
1794                                    "this parameter needs to match the {} type of {deps_list}",
1795                                    self.resolve_vars_if_possible(
1796                                        formal_and_expected_inputs[param.deps[0]].1
1797                                    )
1798                                    .sort_string(self.tcx),
1799                                ),
1800                            );
1801                        } else {
1802                            // Still mark mismatched parameters
1803                            spans.push_span_label(param.param.span(), "");
1804                        }
1805                    }
1806                    // Highlight each parameter being depended on for a generic type.
1807                    for ((&(_, param), deps), &(_, expected_ty)) in
1808                        params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
1809                    {
1810                        if let Some(deps_list) = listify(deps, |&dep| {
1811                            let param = &mismatched_params[dep as usize];
1812                            param.param.display(param.idx.as_usize()).to_string()
1813                        }) {
1814                            spans.push_span_label(
1815                                param.span(),
1816                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{2} need{0} to match the {1} type of this parameter",
                if (deps.len() != 1) as u32 == 1 { "" } else { "s" },
                self.resolve_vars_if_possible(expected_ty).sort_string(self.tcx),
                deps_list))
    })format!(
1817                                    "{deps_list} need{} to match the {} type of this parameter",
1818                                    pluralize!((deps.len() != 1) as u32),
1819                                    self.resolve_vars_if_possible(expected_ty)
1820                                        .sort_string(self.tcx),
1821                                ),
1822                            );
1823                        }
1824                    }
1825                    // Highlight each generic parameter in use.
1826                    for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
1827                        uses.sort();
1828                        uses.dedup();
1829                        if let Some(param_list) = listify(uses, |&idx| {
1830                            params_with_generics[idx].1.display(idx.as_usize()).to_string()
1831                        }) {
1832                            spans.push_span_label(
1833                                param.span,
1834                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{2} {0} reference this parameter `{1}`",
                if uses.len() == 2 { "both" } else { "all" },
                param.name.ident().name, param_list))
    })format!(
1835                                    "{param_list} {} reference this parameter `{}`",
1836                                    if uses.len() == 2 { "both" } else { "all" },
1837                                    param.name.ident().name,
1838                                ),
1839                            );
1840                        }
1841                    }
1842                }
1843            }
1844            err.span_note(spans, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} defined here",
                self.tcx.def_descr(def_id)))
    })format!("{} defined here", self.tcx.def_descr(def_id)));
1845            if let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(def_id)
1846                && let ty::Param(_) =
1847                    self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output().kind()
1848                && let parent = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id
1849                && let Some((output, body_id)) = match self.tcx.hir_node_by_def_id(parent) {
1850                    hir::Node::Item(hir::Item {
1851                        kind: hir::ItemKind::Fn { sig, body, .. },
1852                        ..
1853                    })
1854                    | hir::Node::TraitItem(hir::TraitItem {
1855                        kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)),
1856                        ..
1857                    })
1858                    | hir::Node::ImplItem(hir::ImplItem {
1859                        kind: hir::ImplItemKind::Fn(sig, body),
1860                        ..
1861                    }) => Some((sig.decl.output, body)),
1862                    _ => None,
1863                }
1864                && let expr = self.tcx.hir_body(*body_id).value
1865                && (expr.peel_blocks().span == call_expr.span
1866                    || #[allow(non_exhaustive_omitted_patterns)] match self.tcx.parent_hir_node(call_expr.hir_id)
    {
    hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. }) => true,
    _ => false,
}matches!(
1867                        self.tcx.parent_hir_node(call_expr.hir_id),
1868                        hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
1869                    ))
1870            {
1871                err.span_label(
1872                    output.span(),
1873                    match output {
1874                        FnRetTy::DefaultReturn(_) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this implicit `()` return type influences the call expression\'s return type"))
    })format!(
1875                            "this implicit `()` return type influences the call expression's return type"
1876                        ),
1877                        FnRetTy::Return(_) => {
1878                            "this return type influences the call expression's return type"
1879                                .to_string()
1880                        }
1881                    },
1882                );
1883            }
1884        } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
1885            && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
1886        {
1887            let param = expected_idx
1888                .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
1889            let (kind, span) = if let Some(param) = param {
1890                // Try to find earlier invocations of this closure to find if the type mismatch
1891                // is because of inference. If we find one, point at them.
1892                let mut call_finder = FindClosureArg { tcx: self.tcx, calls: ::alloc::vec::Vec::new()vec![] };
1893                let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
1894                match self.tcx.hir_node_by_def_id(parent_def_id) {
1895                    hir::Node::Item(item) => call_finder.visit_item(item),
1896                    hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
1897                    hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
1898                    _ => {}
1899                }
1900                let typeck = self.typeck_results.borrow();
1901                for (rcvr, args) in call_finder.calls {
1902                    if rcvr.hir_id.owner == typeck.hir_owner
1903                        && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
1904                        && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
1905                        && def_id == *call_def_id
1906                        && let Some(idx) = expected_idx
1907                        && let Some(arg) = args.get(idx)
1908                        && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
1909                        && let Some(expected_ty) = expected_ty
1910                        && self.can_eq(self.param_env, arg_ty, expected_ty)
1911                    {
1912                        let mut sp: MultiSpan = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [arg.span]))vec![arg.span].into();
1913                        sp.push_span_label(
1914                            arg.span,
1915                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected because this argument is of type `{0}`",
                arg_ty))
    })format!("expected because this argument is of type `{arg_ty}`"),
1916                        );
1917                        sp.push_span_label(rcvr.span, "in this closure call");
1918                        err.span_note(
1919                            sp,
1920                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected because the closure was earlier called with an argument of type `{0}`",
                arg_ty))
    })format!(
1921                                "expected because the closure was earlier called with an \
1922                                argument of type `{arg_ty}`",
1923                            ),
1924                        );
1925                        break;
1926                    }
1927                }
1928
1929                ("closure parameter", param.span)
1930            } else {
1931                ("closure", self.tcx.def_span(def_id))
1932            };
1933            err.span_note(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} defined here", kind))
    })format!("{kind} defined here"));
1934        } else {
1935            err.span_note(
1936                self.tcx.def_span(def_id),
1937                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} defined here",
                self.tcx.def_descr(def_id)))
    })format!("{} defined here", self.tcx.def_descr(def_id)),
1938            );
1939        }
1940    }
1941
1942    fn label_generic_mismatches(
1943        &self,
1944        err: &mut Diag<'_>,
1945        callable_def_id: Option<DefId>,
1946        matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1947        provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
1948        formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1949        is_method: bool,
1950        is_splat: bool,
1951    ) {
1952        let Some(def_id) = callable_def_id else {
1953            return;
1954        };
1955
1956        if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
1957            // FIXME(splat): fix the generic mismatch earlier, so it doesn't reach here
1958            if !is_splat {
1959                if true {
    {
        match (&params_with_generics.len(), &matched_inputs.len()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
1960            }
1961            for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
1962                if matched_inputs.get(idx).flatten_ref().is_none() {
1963                    continue;
1964                }
1965
1966                let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
1967                else {
1968                    continue;
1969                };
1970
1971                let Some(generic_param) = generic_param else {
1972                    continue;
1973                };
1974
1975                let idxs_matched = params_with_generics
1976                    .iter_enumerated()
1977                    .filter(|&(other_idx, (other_generic_param, _))| {
1978                        if other_idx == idx {
1979                            return false;
1980                        }
1981                        let Some(other_generic_param) = other_generic_param else {
1982                            return false;
1983                        };
1984                        if matched_inputs.get(other_idx).flatten_ref().is_some() {
1985                            return false;
1986                        }
1987                        other_generic_param == generic_param
1988                    })
1989                    .count();
1990
1991                if idxs_matched == 0 {
1992                    continue;
1993                }
1994
1995                let expected_display_type = self
1996                    .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
1997                    .sort_string(self.tcx);
1998                let label = if idxs_matched == params_with_generics.len() - 1 {
1999                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected all arguments to be this {0} type because they need to match the type of this parameter",
                expected_display_type))
    })format!(
2000                        "expected all arguments to be this {} type because they need to match the type of this parameter",
2001                        expected_display_type
2002                    )
2003                } else {
2004                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected some other arguments to be {0} {1} type to match the type of this parameter",
                a_or_an(&expected_display_type), expected_display_type))
    })format!(
2005                        "expected some other arguments to be {} {} type to match the type of this parameter",
2006                        a_or_an(&expected_display_type),
2007                        expected_display_type,
2008                    )
2009                };
2010
2011                err.span_label(*matched_arg_span, label);
2012            }
2013        }
2014    }
2015
2016    /// Returns the parameters of a function, with their generic parameters if those are the full
2017    /// type of that parameter.
2018    ///
2019    /// Returns `None` if the body is not a named function (e.g. a closure).
2020    fn get_hir_param_info(
2021        &self,
2022        def_id: DefId,
2023        is_method: bool,
2024    ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2025    {
2026        let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2027            hir::Node::TraitItem(&hir::TraitItem {
2028                generics,
2029                kind: hir::TraitItemKind::Fn(sig, trait_fn),
2030                ..
2031            }) => match trait_fn {
2032                hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2033                hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2034            },
2035            hir::Node::ImplItem(&hir::ImplItem {
2036                generics,
2037                kind: hir::ImplItemKind::Fn(sig, body),
2038                ..
2039            })
2040            | hir::Node::Item(&hir::Item {
2041                kind: hir::ItemKind::Fn { sig, generics, body, .. },
2042                ..
2043            }) => (sig, generics, Some(body), None),
2044            hir::Node::ForeignItem(&hir::ForeignItem {
2045                kind: hir::ForeignItemKind::Fn(sig, params, generics),
2046                ..
2047            }) => (sig, generics, None, Some(params)),
2048            _ => return None,
2049        };
2050
2051        // Make sure to remove both the receiver and variadic argument. Both are removed
2052        // when matching parameter types.
2053        let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2054            if let hir::TyKind::Path(QPath::Resolved(
2055                _,
2056                &hir::Path { res: Res::Def(_, res_def_id), .. },
2057            )) = param.kind
2058            {
2059                generics
2060                    .params
2061                    .iter()
2062                    .position(|param| param.def_id.to_def_id() == res_def_id)
2063                    .map(GenericIdx::from_usize)
2064            } else {
2065                None
2066            }
2067        });
2068        match (body_id, params) {
2069            (Some(_), Some(_)) | (None, None) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2070            (Some(body), None) => {
2071                let params = self.tcx.hir_body(body).params;
2072                let params = params
2073                    .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
2074                if true {
    {
        match (&params.len(), &fn_inputs.len()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(params.len(), fn_inputs.len());
2075                Some((fn_inputs.zip(params.iter().map(FnParam::Param)).collect(), generics))
2076            }
2077            (None, Some(params)) => {
2078                let params = params
2079                    .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
2080                if true {
    {
        match (&params.len(), &fn_inputs.len()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(params.len(), fn_inputs.len());
2081                Some((
2082                    fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2083                    generics,
2084                ))
2085            }
2086        }
2087    }
2088}
2089
2090struct FindClosureArg<'tcx> {
2091    tcx: TyCtxt<'tcx>,
2092    calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2093}
2094
2095impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2096    type NestedFilter = rustc_middle::hir::nested_filter::All;
2097
2098    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2099        self.tcx
2100    }
2101
2102    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2103        if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2104            self.calls.push((rcvr, args));
2105        }
2106        hir::intravisit::walk_expr(self, ex);
2107    }
2108}
2109
2110#[derive(#[automatically_derived]
impl<'hir> ::core::clone::Clone for FnParam<'hir> {
    #[inline]
    fn clone(&self) -> FnParam<'hir> {
        let _: ::core::clone::AssertParamIsClone<&'hir hir::Param<'hir>>;
        let _: ::core::clone::AssertParamIsClone<Option<Ident>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'hir> ::core::marker::Copy for FnParam<'hir> { }Copy)]
2111enum FnParam<'hir> {
2112    Param(&'hir hir::Param<'hir>),
2113    Ident(Option<Ident>),
2114}
2115
2116impl FnParam<'_> {
2117    fn span(&self) -> Span {
2118        match self {
2119            Self::Param(param) => param.span,
2120            Self::Ident(ident) => {
2121                if let Some(ident) = ident {
2122                    ident.span
2123                } else {
2124                    DUMMY_SP
2125                }
2126            }
2127        }
2128    }
2129
2130    fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2131        struct D<'a>(FnParam<'a>, usize);
2132        impl fmt::Display for D<'_> {
2133            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2134                // A "unique" param name is one that (a) exists, and (b) is guaranteed to be unique
2135                // among the parameters, i.e. `_` does not count.
2136                let unique_name = match self.0 {
2137                    FnParam::Param(param)
2138                        if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2139                    {
2140                        Some(ident.name)
2141                    }
2142                    FnParam::Ident(ident)
2143                        if let Some(ident) = ident
2144                            && ident.name != kw::Underscore =>
2145                    {
2146                        Some(ident.name)
2147                    }
2148                    _ => None,
2149                };
2150                if let Some(unique_name) = unique_name {
2151                    f.write_fmt(format_args!("`{0}`", unique_name))write!(f, "`{unique_name}`")
2152                } else {
2153                    f.write_fmt(format_args!("parameter #{0}", self.1 + 1))write!(f, "parameter #{}", self.1 + 1)
2154                }
2155            }
2156        }
2157        D(*self, idx)
2158    }
2159}
2160
2161struct FnCallDiagCtxt<'a, 'tcx> {
2162    arg_matching_ctxt: ArgMatchingCtxt<'a, 'tcx>,
2163    errors: Vec<Error<'tcx>>,
2164    matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2165}
2166
2167impl<'a, 'tcx> Deref for FnCallDiagCtxt<'a, 'tcx> {
2168    type Target = ArgMatchingCtxt<'a, 'tcx>;
2169
2170    fn deref(&self) -> &Self::Target {
2171        &self.arg_matching_ctxt
2172    }
2173}
2174
2175// Controls how the arguments should be listed in the suggestion.
2176enum ArgumentsFormatting {
2177    SingleLine,
2178    Multiline { fallback_indent: String, brace_indent: String },
2179}
2180
2181impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> {
2182    fn new(
2183        arg: &'a FnCtxt<'a, 'tcx>,
2184        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
2185        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2186        provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
2187        c_variadic: bool,
2188        err_code: ErrCode,
2189        fn_def_id: Option<DefId>,
2190        call_span: Span,
2191        call_expr: &'tcx Expr<'tcx>,
2192        tuple_arguments: TupleArgumentsFlag,
2193    ) -> Self {
2194        let arg_matching_ctxt = ArgMatchingCtxt::new(
2195            arg,
2196            compatibility_diagonal,
2197            formal_and_expected_inputs,
2198            provided_args,
2199            c_variadic,
2200            err_code,
2201            fn_def_id,
2202            call_span,
2203            call_expr,
2204            tuple_arguments,
2205        );
2206
2207        // The algorithm here is inspired by levenshtein distance and longest common subsequence.
2208        // We'll try to detect 4 different types of mistakes:
2209        // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
2210        // - An input is missing, which isn't satisfied by *any* of the other arguments
2211        // - Some number of arguments have been provided in the wrong order
2212        // - A type is straight up invalid
2213        let (errors, matched_inputs) = ArgMatrix::new(
2214            arg_matching_ctxt.provided_args.len(),
2215            arg_matching_ctxt.formal_and_expected_inputs.len(),
2216            |provided, expected| arg_matching_ctxt.check_compatible(provided, expected),
2217        )
2218        .find_errors();
2219
2220        FnCallDiagCtxt { arg_matching_ctxt, errors, matched_inputs }
2221    }
2222
2223    fn check_wrap_args_in_tuple(&self) -> Option<ErrorGuaranteed> {
2224        if let Some((mismatch_idx, terr)) = self.first_incompatible_error() {
2225            // Is the first bad expected argument a tuple?
2226            // Do we have as many extra provided arguments as the tuple's length?
2227            // If so, we might have just forgotten to wrap some args in a tuple.
2228            if let Some(ty::Tuple(tys)) =
2229               self.formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
2230                // If the tuple is unit, we're not actually wrapping any arguments.
2231                && !tys.is_empty()
2232                && self.provided_arg_tys.len() == self.formal_and_expected_inputs.len() - 1 + tys.len()
2233            {
2234                // Wrap up the N provided arguments starting at this position in a tuple.
2235                let provided_args_to_tuple = &self.provided_arg_tys[mismatch_idx..];
2236                let (provided_args_to_tuple, provided_args_after_tuple) =
2237                    provided_args_to_tuple.split_at(tys.len());
2238                let provided_as_tuple = Ty::new_tup_from_iter(
2239                    self.tcx,
2240                    provided_args_to_tuple.iter().map(|&(ty, _)| ty),
2241                );
2242
2243                let mut satisfied = true;
2244                // Check if the newly wrapped tuple + rest of the arguments are compatible.
2245                for ((_, expected_ty), provided_ty) in std::iter::zip(
2246                    self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
2247                    [provided_as_tuple]
2248                        .into_iter()
2249                        .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
2250                ) {
2251                    if !self.may_coerce(provided_ty, *expected_ty) {
2252                        satisfied = false;
2253                        break;
2254                    }
2255                }
2256
2257                // If they're compatible, suggest wrapping in an arg, and we're done!
2258                // Take some care with spans, so we don't suggest wrapping a macro's
2259                // innards in parenthesis, for example.
2260                if satisfied
2261                    && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
2262                {
2263                    let mut err;
2264                    if tys.len() == 1 {
2265                        // A tuple wrap suggestion actually occurs within,
2266                        // so don't do anything special here.
2267                        err = self.err_ctxt().report_and_explain_type_error(
2268                            self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2269                                lo,
2270                                self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
2271                                self.provided_arg_tys[mismatch_idx].0,
2272                            ),
2273                            self.param_env,
2274                            terr,
2275                        );
2276                        let call_name = self.call_metadata.call_name;
2277                        err.span_label(
2278                            self.call_metadata.full_call_span,
2279                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arguments to this {0} are incorrect",
                call_name))
    })format!("arguments to this {call_name} are incorrect"),
2280                        );
2281                    } else {
2282                        let call_name = self.call_metadata.call_name;
2283                        err = self.dcx().struct_span_err(
2284                            self.arg_matching_ctxt.args_ctxt.call_metadata.full_call_span,
2285                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{4} takes {0}{1} but {2} {3} supplied",
                if self.arg_matching_ctxt.args_ctxt.c_variadic {
                    "at least "
                } else { "" },
                potentially_plural_count(self.formal_and_expected_inputs.len(),
                    "argument"),
                potentially_plural_count(self.provided_args.len(),
                    "argument"),
                if self.provided_args.len() == 1 { "was" } else { "were" },
                call_name))
    })format!(
2286                                "{call_name} takes {}{} but {} {} supplied",
2287                                if self.arg_matching_ctxt.args_ctxt.c_variadic {
2288                                    "at least "
2289                                } else {
2290                                    ""
2291                                },
2292                                potentially_plural_count(
2293                                    self.formal_and_expected_inputs.len(),
2294                                    "argument"
2295                                ),
2296                                potentially_plural_count(self.provided_args.len(), "argument"),
2297                                pluralize!("was", self.provided_args.len())
2298                            ),
2299                        );
2300                        err.code(self.err_code.to_owned());
2301                        err.multipart_suggestion(
2302                            "wrap these arguments in parentheses to construct a tuple",
2303                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(lo.shrink_to_lo(), "(".to_string()),
                (hi.shrink_to_hi(), ")".to_string())]))vec![
2304                                (lo.shrink_to_lo(), "(".to_string()),
2305                                (hi.shrink_to_hi(), ")".to_string()),
2306                            ],
2307                            Applicability::MachineApplicable,
2308                        );
2309                    };
2310                    self.arg_matching_ctxt.args_ctxt.call_ctxt.fn_ctxt.label_fn_like(
2311                        &mut err,
2312                        self.fn_def_id,
2313                        self.callee_ty,
2314                        self.call_expr,
2315                        None,
2316                        Some(mismatch_idx.as_usize()),
2317                        &self.matched_inputs,
2318                        &self.formal_and_expected_inputs,
2319                        self.call_metadata.is_method,
2320                        self.tuple_arguments,
2321                    );
2322                    self.suggest_confusable(&mut err);
2323                    Some(err.emit())
2324                } else {
2325                    None
2326                }
2327            } else {
2328                None
2329            }
2330        } else {
2331            None
2332        }
2333    }
2334
2335    fn ensure_has_errors(&self) -> Option<ErrorGuaranteed> {
2336        if self.errors.is_empty() {
2337            if truecfg!(debug_assertions) {
2338                ::rustc_middle::util::bug::span_bug_fmt(self.call_metadata.error_span,
    format_args!("expected errors from argument matrix"));span_bug!(self.call_metadata.error_span, "expected errors from argument matrix");
2339            } else {
2340                let mut err = self.dcx().create_err(diagnostics::ArgMismatchIndeterminate {
2341                    span: self.call_metadata.error_span,
2342                });
2343                self.arg_matching_ctxt.suggest_confusable(&mut err);
2344                return Some(err.emit());
2345            }
2346        }
2347
2348        None
2349    }
2350
2351    fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) {
2352        if let ty::Adt(adt, _) = ty.kind()
2353            && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
2354            && is_range_literal(expr)
2355            && let hir::ExprKind::Struct(&path, [], _) = expr.kind
2356            && self.tcx().qpath_is_lang_item(path, hir::LangItem::RangeFull)
2357        {
2358            // We have `Foo(a, .., c)`, where the user might be trying to use the "rest" syntax
2359            // from default field values, which is not supported on tuples.
2360            let explanation = if self.tcx.features().default_field_values() {
2361                "this is only supported on non-tuple struct literals"
2362            } else if self.tcx.sess.is_nightly_build() {
2363                "this is only supported on non-tuple struct literals when \
2364                 `#![feature(default_field_values)]` is enabled"
2365            } else {
2366                "this is not supported"
2367            };
2368            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might have meant to use `..` to skip providing a value for expected fields, but {0}; it is instead interpreted as a `std::ops::RangeFull` literal",
                explanation))
    })format!(
2369                "you might have meant to use `..` to skip providing a value for \
2370                 expected fields, but {explanation}; it is instead interpreted as a \
2371                 `std::ops::RangeFull` literal",
2372            );
2373            err.span_help(expr.span, msg);
2374        }
2375    }
2376
2377    fn filter_out_invalid_arguments(&mut self) -> Option<ErrorGuaranteed> {
2378        let mut reported = None;
2379
2380        self.errors.retain(|error| {
2381            let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
2382                error
2383            else {
2384                return true;
2385            };
2386            let (provided_ty, provided_span) =
2387                self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2388            let trace = self.arg_matching_ctxt.mk_trace(
2389                provided_span,
2390                self.arg_matching_ctxt.formal_and_expected_inputs[*expected_idx],
2391                provided_ty,
2392            );
2393            if !#[allow(non_exhaustive_omitted_patterns)] match trace.cause.as_failure_code(*e)
    {
    FailureCode::Error0308 => true,
    _ => false,
}matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
2394                let mut err = self.arg_matching_ctxt.err_ctxt().report_and_explain_type_error(
2395                    trace,
2396                    self.arg_matching_ctxt.param_env,
2397                    *e,
2398                );
2399                self.arg_matching_ctxt.suggest_confusable(&mut err);
2400                reported = Some(err.emit());
2401                return false;
2402            }
2403            true
2404        });
2405
2406        reported
2407    }
2408
2409    fn check_single_incompatible(&self) -> Option<ErrorGuaranteed> {
2410        if let &[
2411            Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
2412        ] = &self.errors[..]
2413        {
2414            let (formal_ty, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2415            let (provided_ty, provided_arg_span) = self.provided_arg_tys[provided_idx];
2416            let trace = self.mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
2417            let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
2418            self.emit_coerce_suggestions(
2419                &mut err,
2420                self.provided_args[provided_idx],
2421                provided_ty,
2422                Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2423                    .only_has_type(self.fn_ctxt)
2424                    .unwrap_or(formal_ty),
2425                None,
2426                None,
2427            );
2428            let call_name = self.call_metadata.call_name;
2429            err.span_label(
2430                self.call_metadata.full_call_span,
2431                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("arguments to this {0} are incorrect",
                call_name))
    })format!("arguments to this {call_name} are incorrect"),
2432            );
2433
2434            self.label_generic_mismatches(&mut err);
2435
2436            if let hir::ExprKind::MethodCall(_, rcvr, _, _) =
2437                self.arg_matching_ctxt.args_ctxt.call_ctxt.call_expr.kind
2438                && provided_idx.as_usize() == expected_idx.as_usize()
2439            {
2440                self.note_source_of_type_mismatch_constraint(
2441                    &mut err,
2442                    rcvr,
2443                    crate::demand::TypeMismatchSource::Arg {
2444                        call_expr: self.call_expr,
2445                        incompatible_arg: provided_idx.as_usize(),
2446                    },
2447                );
2448            }
2449
2450            self.suggest_ptr_null_mut(
2451                expected_ty,
2452                provided_ty,
2453                self.provided_args[provided_idx],
2454                &mut err,
2455            );
2456
2457            self.suggest_deref_unwrap_or(
2458                &mut err,
2459                self.callee_ty,
2460                self.call_metadata.call_ident,
2461                expected_ty,
2462                provided_ty,
2463                self.provided_args[provided_idx],
2464                self.call_metadata.is_method,
2465            );
2466
2467            // Call out where the function is defined
2468            self.label_fn_like(
2469                &mut err,
2470                self.fn_def_id,
2471                self.callee_ty,
2472                self.call_expr,
2473                Some(expected_ty),
2474                Some(expected_idx.as_usize()),
2475                &self.matched_inputs,
2476                &self.formal_and_expected_inputs,
2477                self.call_metadata.is_method,
2478                self.tuple_arguments,
2479            );
2480            self.arg_matching_ctxt.suggest_confusable(&mut err);
2481            self.detect_dotdot(&mut err, provided_ty, self.provided_args[provided_idx]);
2482            return Some(err.emit());
2483        }
2484
2485        None
2486    }
2487
2488    fn maybe_optimize_extra_arg_suggestion(&mut self) {
2489        if let [Error::Extra(provided_idx)] = &self.errors[..] {
2490            if !self.remove_idx_is_perfect(provided_idx.as_usize()) {
2491                if let Some(i) = (0..self.args_ctxt.call_ctxt.provided_args.len())
2492                    .find(|&i| self.remove_idx_is_perfect(i))
2493                {
2494                    self.errors = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [Error::Extra(ProvidedIdx::from_usize(i))]))vec![Error::Extra(ProvidedIdx::from_usize(i))];
2495                }
2496            }
2497        }
2498    }
2499
2500    fn initial_final_diagnostic(&self) -> Diag<'_> {
2501        if self.formal_and_expected_inputs.len() == self.provided_args.len() {
2502            {
    self.dcx().struct_span_err(self.call_metadata.full_call_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("arguments to this {0} are incorrect",
                            self.call_metadata.call_name))
                })).with_code(E0308)
}struct_span_code_err!(
2503                self.dcx(),
2504                self.call_metadata.full_call_span,
2505                E0308,
2506                "arguments to this {} are incorrect",
2507                self.call_metadata.call_name,
2508            )
2509        } else {
2510            self.arg_matching_ctxt
2511                .dcx()
2512                .struct_span_err(
2513                    self.call_metadata.full_call_span,
2514                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this {0} takes {1}{2} but {3} {4} supplied",
                self.call_metadata.call_name,
                if self.arg_matching_ctxt.args_ctxt.c_variadic {
                    "at least "
                } else { "" },
                potentially_plural_count(self.formal_and_expected_inputs.len(),
                    "argument"),
                potentially_plural_count(self.provided_args.len(),
                    "argument"),
                if self.provided_args.len() == 1 { "was" } else { "were" }))
    })format!(
2515                        "this {} takes {}{} but {} {} supplied",
2516                        self.call_metadata.call_name,
2517                        if self.arg_matching_ctxt.args_ctxt.c_variadic { "at least " } else { "" },
2518                        potentially_plural_count(self.formal_and_expected_inputs.len(), "argument"),
2519                        potentially_plural_count(self.provided_args.len(), "argument"),
2520                        pluralize!("was", self.provided_args.len())
2521                    ),
2522                )
2523                .with_code(self.err_code.to_owned())
2524        }
2525    }
2526
2527    fn labels_and_suggestion_text(
2528        &self,
2529        err: &mut Diag<'_>,
2530    ) -> (Vec<(Span, String)>, Vec<(Span, String)>, SuggestionText) {
2531        // Don't print if it has error types or is just plain `_`
2532        fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
2533            tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
2534        }
2535
2536        let mut labels = Vec::new();
2537        let mut suggestion_text = SuggestionText::None;
2538
2539        let mut errors = self.errors.iter().peekable();
2540        let mut only_extras_so_far = errors
2541            .peek()
2542            .is_some_and(|first| #[allow(non_exhaustive_omitted_patterns)] match first {
    Error::Extra(arg_idx) if arg_idx.index() == 0 => true,
    _ => false,
}matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
2543        let mut prev_extra_idx = None;
2544        let mut suggestions = ::alloc::vec::Vec::new()vec![];
2545        while let Some(error) = errors.next() {
2546            only_extras_so_far &= #[allow(non_exhaustive_omitted_patterns)] match error {
    Error::Extra(_) => true,
    _ => false,
}matches!(error, Error::Extra(_));
2547
2548            match error {
2549                Error::Invalid(provided_idx, expected_idx, compatibility) => {
2550                    let (formal_ty, expected_ty) =
2551                        self.arg_matching_ctxt.args_ctxt.call_ctxt.formal_and_expected_inputs
2552                            [*expected_idx];
2553                    let (provided_ty, provided_span) =
2554                        self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2555                    if let Compatibility::Incompatible(error) = compatibility {
2556                        let trace = self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2557                            provided_span,
2558                            (formal_ty, expected_ty),
2559                            provided_ty,
2560                        );
2561                        if let Some(e) = error {
2562                            self.err_ctxt().note_type_err(
2563                                err,
2564                                &trace.cause,
2565                                None,
2566                                Some(self.param_env.and(trace.values)),
2567                                *e,
2568                                true,
2569                                None,
2570                            );
2571                        }
2572                    }
2573
2574                    self.emit_coerce_suggestions(
2575                        err,
2576                        self.provided_args[*provided_idx],
2577                        provided_ty,
2578                        Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2579                            .only_has_type(self.fn_ctxt)
2580                            .unwrap_or(formal_ty),
2581                        None,
2582                        None,
2583                    );
2584                    self.detect_dotdot(err, provided_ty, self.provided_args[*provided_idx]);
2585                }
2586                Error::Extra(arg_idx) => {
2587                    let (provided_ty, provided_span) = self.provided_arg_tys[*arg_idx];
2588                    let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2589                        // FIXME: not suggestable, use something else
2590                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" of type `{0}`", provided_ty))
    })format!(" of type `{provided_ty}`")
2591                    } else {
2592                        "".to_string()
2593                    };
2594                    let idx = if self.provided_arg_tys.len() == 1 {
2595                        "".to_string()
2596                    } else {
2597                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" #{0}", arg_idx.as_usize() + 1))
    })format!(" #{}", arg_idx.as_usize() + 1)
2598                    };
2599                    labels.push((
2600                        provided_span,
2601                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unexpected argument{0}{1}", idx,
                provided_ty_name))
    })format!("unexpected argument{idx}{provided_ty_name}"),
2602                    ));
2603                    if self.provided_arg_tys.len() == 1
2604                        && let Some(span) = self.maybe_suggest_expect_for_unwrap(provided_ty)
2605                    {
2606                        err.span_suggestion_verbose(
2607                            span,
2608                            "did you mean to use `expect`?",
2609                            "expect",
2610                            Applicability::MaybeIncorrect,
2611                        );
2612                        continue;
2613                    }
2614                    let mut span = provided_span;
2615                    if span.can_be_used_for_suggestions()
2616                        && self.call_metadata.error_span.can_be_used_for_suggestions()
2617                    {
2618                        if arg_idx.index() > 0
2619                            && let Some((_, prev)) = self
2620                                .provided_arg_tys
2621                                .get(ProvidedIdx::from_usize(arg_idx.index() - 1))
2622                        {
2623                            // Include previous comma
2624                            span = prev.shrink_to_hi().to(span);
2625                        }
2626
2627                        // Is last argument for deletion in a row starting from the 0-th argument?
2628                        // Then delete the next comma, so we are not left with `f(, ...)`
2629                        //
2630                        //     fn f() {}
2631                        //   - f(0, 1,)
2632                        //   + f()
2633                        let trim_next_comma = match errors.peek() {
2634                            Some(Error::Extra(provided_idx))
2635                                if only_extras_so_far
2636                                    && provided_idx.index() > arg_idx.index() + 1 =>
2637                            // If the next Error::Extra ("next") doesn't next to current ("current"),
2638                            // fn foo(_: (), _: u32) {}
2639                            // - foo("current", (), 1u32, "next")
2640                            // + foo((), 1u32)
2641                            // If the previous error is not a `Error::Extra`, then do not trim the next comma
2642                            // - foo((), "current", 42u32, "next")
2643                            // + foo((), 42u32)
2644                            {
2645                                prev_extra_idx.is_none_or(|prev_extra_idx| {
2646                                    prev_extra_idx + 1 == arg_idx.index()
2647                                })
2648                            }
2649                            // If no error left, we need to delete the next comma
2650                            None if only_extras_so_far => true,
2651                            // Not sure if other error type need to be handled as well
2652                            _ => false,
2653                        };
2654
2655                        if trim_next_comma {
2656                            let next = self
2657                                .provided_arg_tys
2658                                .get(*arg_idx + 1)
2659                                .map(|&(_, sp)| sp)
2660                                .unwrap_or_else(|| {
2661                                    // Try to move before `)`. Note that `)` here is not necessarily
2662                                    // the latin right paren, it could be a Unicode-confusable that
2663                                    // looks like a `)`, so we must not use `- BytePos(1)`
2664                                    // manipulations here.
2665                                    self.arg_matching_ctxt
2666                                        .tcx()
2667                                        .sess
2668                                        .source_map()
2669                                        .end_point(self.call_expr.span)
2670                                });
2671
2672                            // Include next comma
2673                            span = span.until(next);
2674                        }
2675
2676                        suggestions.push((span, String::new()));
2677
2678                        suggestion_text = match suggestion_text {
2679                            SuggestionText::None => SuggestionText::Remove(false),
2680                            SuggestionText::Remove(_) => SuggestionText::Remove(true),
2681                            _ => SuggestionText::DidYouMean,
2682                        };
2683                        prev_extra_idx = Some(arg_idx.index())
2684                    }
2685                    self.detect_dotdot(err, provided_ty, self.provided_args[*arg_idx]);
2686                }
2687                Error::Missing(expected_idx) => {
2688                    // If there are multiple missing arguments adjacent to each other,
2689                    // then we can provide a single error.
2690
2691                    let mut missing_idxs = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [*expected_idx]))vec![*expected_idx];
2692                    while let Some(e) = errors.next_if(|e| {
2693                        #[allow(non_exhaustive_omitted_patterns)] match e {
    Error::Missing(next_expected_idx) if
        *next_expected_idx == *missing_idxs.last().unwrap() + 1 => true,
    _ => false,
}matches!(e, Error::Missing(next_expected_idx)
2694                            if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
2695                    }) {
2696                        match e {
2697                            Error::Missing(expected_idx) => missing_idxs.push(*expected_idx),
2698                            _ => {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("control flow ensures that we should always get an `Error::Missing`")));
}unreachable!(
2699                                "control flow ensures that we should always get an `Error::Missing`"
2700                            ),
2701                        }
2702                    }
2703
2704                    // NOTE: Because we might be re-arranging arguments, might have extra
2705                    // arguments, etc. it's hard to *really* know where we should provide
2706                    // this error label, so as a heuristic, we point to the provided arg, or
2707                    // to the call if the missing inputs pass the provided args.
2708                    match &missing_idxs[..] {
2709                        &[expected_idx] => {
2710                            let (_, input_ty) = self.formal_and_expected_inputs[expected_idx];
2711                            let span = if let Some((_, arg_span)) =
2712                                self.provided_arg_tys.get(expected_idx.to_provided_idx())
2713                            {
2714                                *arg_span
2715                            } else {
2716                                self.args_span
2717                            };
2718                            let rendered = if !has_error_or_infer([input_ty]) {
2719                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" of type `{0}`", input_ty))
    })format!(" of type `{input_ty}`")
2720                            } else {
2721                                "".to_string()
2722                            };
2723                            labels.push((
2724                                span,
2725                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("argument #{0}{1} is missing",
                expected_idx.as_usize() + 1, rendered))
    })format!(
2726                                    "argument #{}{rendered} is missing",
2727                                    expected_idx.as_usize() + 1
2728                                ),
2729                            ));
2730
2731                            suggestion_text = match suggestion_text {
2732                                SuggestionText::None => SuggestionText::Provide(false),
2733                                SuggestionText::Provide(_) => SuggestionText::Provide(true),
2734                                _ => SuggestionText::DidYouMean,
2735                            };
2736                        }
2737                        &[first_idx, second_idx] => {
2738                            let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2739                            let (_, second_expected_ty) =
2740                                self.formal_and_expected_inputs[second_idx];
2741                            let span = if let (Some((_, first_span)), Some((_, second_span))) = (
2742                                self.provided_arg_tys.get(first_idx.to_provided_idx()),
2743                                self.provided_arg_tys.get(second_idx.to_provided_idx()),
2744                            ) {
2745                                first_span.to(*second_span)
2746                            } else {
2747                                self.args_span
2748                            };
2749                            let rendered =
2750                                if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
2751                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" of type `{0}` and `{1}`",
                first_expected_ty, second_expected_ty))
    })format!(
2752                                        " of type `{first_expected_ty}` and `{second_expected_ty}`"
2753                                    )
2754                                } else {
2755                                    "".to_string()
2756                                };
2757                            labels.push((span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("two arguments{0} are missing",
                rendered))
    })format!("two arguments{rendered} are missing")));
2758                            suggestion_text = match suggestion_text {
2759                                SuggestionText::None | SuggestionText::Provide(_) => {
2760                                    SuggestionText::Provide(true)
2761                                }
2762                                _ => SuggestionText::DidYouMean,
2763                            };
2764                        }
2765                        &[first_idx, second_idx, third_idx] => {
2766                            let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2767                            let (_, second_expected_ty) =
2768                                self.formal_and_expected_inputs[second_idx];
2769                            let (_, third_expected_ty) = self.formal_and_expected_inputs[third_idx];
2770                            let span = if let (Some((_, first_span)), Some((_, third_span))) = (
2771                                self.provided_arg_tys.get(first_idx.to_provided_idx()),
2772                                self.provided_arg_tys.get(third_idx.to_provided_idx()),
2773                            ) {
2774                                first_span.to(*third_span)
2775                            } else {
2776                                self.args_span
2777                            };
2778                            let rendered = if !has_error_or_infer([
2779                                first_expected_ty,
2780                                second_expected_ty,
2781                                third_expected_ty,
2782                            ]) {
2783                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" of type `{0}`, `{1}`, and `{2}`",
                first_expected_ty, second_expected_ty, third_expected_ty))
    })format!(
2784                                    " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
2785                                )
2786                            } else {
2787                                "".to_string()
2788                            };
2789                            labels.push((span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("three arguments{0} are missing",
                rendered))
    })format!("three arguments{rendered} are missing")));
2790                            suggestion_text = match suggestion_text {
2791                                SuggestionText::None | SuggestionText::Provide(_) => {
2792                                    SuggestionText::Provide(true)
2793                                }
2794                                _ => SuggestionText::DidYouMean,
2795                            };
2796                        }
2797                        missing_idxs => {
2798                            let first_idx = *missing_idxs.first().unwrap();
2799                            let last_idx = *missing_idxs.last().unwrap();
2800                            // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
2801                            // It's hard to *really* know where we should provide this error label, so this is a
2802                            // decent heuristic
2803                            let span = if let (Some((_, first_span)), Some((_, last_span))) = (
2804                                self.provided_arg_tys.get(first_idx.to_provided_idx()),
2805                                self.provided_arg_tys.get(last_idx.to_provided_idx()),
2806                            ) {
2807                                first_span.to(*last_span)
2808                            } else {
2809                                self.args_span
2810                            };
2811                            labels.push((span, "multiple arguments are missing".to_string()));
2812                            suggestion_text = match suggestion_text {
2813                                SuggestionText::None | SuggestionText::Provide(_) => {
2814                                    SuggestionText::Provide(true)
2815                                }
2816                                _ => SuggestionText::DidYouMean,
2817                            };
2818                        }
2819                    }
2820                }
2821                Error::Swap(
2822                    first_provided_idx,
2823                    second_provided_idx,
2824                    first_expected_idx,
2825                    second_expected_idx,
2826                ) => {
2827                    let (first_provided_ty, first_span) =
2828                        self.provided_arg_tys[*first_provided_idx];
2829                    let (_, first_expected_ty) =
2830                        self.formal_and_expected_inputs[*first_expected_idx];
2831                    let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
2832                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", found `{0}`", first_provided_ty))
    })format!(", found `{first_provided_ty}`")
2833                    } else {
2834                        String::new()
2835                    };
2836                    labels.push((
2837                        first_span,
2838                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected `{0}`{1}",
                first_expected_ty, first_provided_ty_name))
    })format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
2839                    ));
2840
2841                    let (second_provided_ty, second_span) =
2842                        self.provided_arg_tys[*second_provided_idx];
2843                    let (_, second_expected_ty) =
2844                        self.formal_and_expected_inputs[*second_expected_idx];
2845                    let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
2846                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", found `{0}`",
                second_provided_ty))
    })format!(", found `{second_provided_ty}`")
2847                    } else {
2848                        String::new()
2849                    };
2850                    labels.push((
2851                        second_span,
2852                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected `{0}`{1}",
                second_expected_ty, second_provided_ty_name))
    })format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
2853                    ));
2854
2855                    suggestion_text = match suggestion_text {
2856                        SuggestionText::None => SuggestionText::Swap,
2857                        _ => SuggestionText::DidYouMean,
2858                    };
2859                }
2860                Error::Permutation(args) => {
2861                    for (dst_arg, dest_input) in args {
2862                        let (_, expected_ty) = self.formal_and_expected_inputs[*dst_arg];
2863                        let (provided_ty, provided_span) = self.provided_arg_tys[*dest_input];
2864                        let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2865                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", found `{0}`", provided_ty))
    })format!(", found `{provided_ty}`")
2866                        } else {
2867                            String::new()
2868                        };
2869                        labels.push((
2870                            provided_span,
2871                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected `{0}`{1}", expected_ty,
                provided_ty_name))
    })format!("expected `{expected_ty}`{provided_ty_name}"),
2872                        ));
2873                    }
2874
2875                    suggestion_text = match suggestion_text {
2876                        SuggestionText::None => SuggestionText::Reorder,
2877                        _ => SuggestionText::DidYouMean,
2878                    };
2879                }
2880            }
2881        }
2882
2883        (suggestions, labels, suggestion_text)
2884    }
2885
2886    fn label_generic_mismatches(&self, err: &mut Diag<'a>) {
2887        self.fn_ctxt.label_generic_mismatches(
2888            err,
2889            self.fn_def_id,
2890            &self.matched_inputs,
2891            &self.provided_arg_tys,
2892            &self.formal_and_expected_inputs,
2893            self.call_metadata.is_method,
2894            self.arg_matching_ctxt.tuple_arguments.is_splatted(),
2895        );
2896    }
2897
2898    /// Incorporate the argument changes in the removal suggestion.
2899    ///
2900    /// When a type is *missing*, and the rest are additional, we want to suggest these with a
2901    /// multipart suggestion, but in order to do so we need to figure out *where* the arg that
2902    /// was provided but had the wrong type should go, because when looking at `expected_idx`
2903    /// that is the position in the argument list in the definition, while `provided_idx` will
2904    /// not be present. So we have to look at what the *last* provided position was, and point
2905    /// one after to suggest the replacement.
2906    fn append_arguments_changes(&self, suggestions: &mut Vec<(Span, String)>) {
2907        // FIXME(estebank): This is hacky, and there's
2908        // probably a better more involved change we can make to make this work.
2909        // For example, if we have
2910        // ```
2911        // fn foo(i32, &'static str) {}
2912        // foo((), (), ());
2913        // ```
2914        // what should be suggested is
2915        // ```
2916        // foo(/* i32 */, /* &str */);
2917        // ```
2918        // which includes the replacement of the first two `()` for the correct type, and the
2919        // removal of the last `()`.
2920
2921        let mut prev = -1;
2922        for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
2923            // We want to point not at the *current* argument expression index, but rather at the
2924            // index position where it *should have been*, which is *after* the previous one.
2925            if let Some(provided_idx) = provided_idx {
2926                prev = provided_idx.index() as i64;
2927                continue;
2928            }
2929            let idx = ProvidedIdx::from_usize((prev + 1) as usize);
2930            if let Some((_, arg_span)) = self.provided_arg_tys.get(idx) {
2931                prev += 1;
2932                // There is a type that was *not* found anywhere, so it isn't a move, but a
2933                // replacement and we look at what type it should have been. This will allow us
2934                // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
2935                // was `fn foo(())`.
2936                let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2937                // Check if the new suggestion would overlap with any existing suggestion.
2938                // This can happen when we have both removal suggestions (which may include
2939                // adjacent commas) and type replacement suggestions for the same span.
2940                let dominated = suggestions
2941                    .iter()
2942                    .any(|(span, _)| span.contains(*arg_span) || arg_span.overlaps(*span));
2943                if !dominated {
2944                    suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
2945                }
2946            }
2947        }
2948    }
2949
2950    fn format_suggestion_text(
2951        err: &mut Diag<'_>,
2952        suggestions: Vec<(Span, String)>,
2953        suggestion_text: SuggestionText,
2954    ) -> Option<String> {
2955        match suggestion_text {
2956            SuggestionText::None => None,
2957            SuggestionText::Provide(plural) => {
2958                Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("provide the argument{0}",
                if plural { "s" } else { "" }))
    })format!("provide the argument{}", if plural { "s" } else { "" }))
2959            }
2960            SuggestionText::Remove(plural) => {
2961                err.multipart_suggestion(
2962                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("remove the extra argument{0}",
                if plural { "s" } else { "" }))
    })format!("remove the extra argument{}", if plural { "s" } else { "" }),
2963                    suggestions,
2964                    Applicability::HasPlaceholders,
2965                );
2966                None
2967            }
2968            SuggestionText::Swap => Some("swap these arguments".to_string()),
2969            SuggestionText::Reorder => Some("reorder these arguments".to_string()),
2970            SuggestionText::DidYouMean => Some("did you mean".to_string()),
2971        }
2972    }
2973
2974    fn arguments_formatting(&self, suggestion_span: Span) -> ArgumentsFormatting {
2975        let source_map = self.sess().source_map();
2976        let mut provided_inputs = self.matched_inputs.iter().filter_map(|a| *a);
2977        if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
2978            && let Some(first_idx) = provided_inputs.by_ref().next()
2979            && let Some(last_idx) = provided_inputs.by_ref().next()
2980            && let (_, first_span) = self.provided_arg_tys[first_idx]
2981            && let (_, last_span) = self.provided_arg_tys[last_idx]
2982            && source_map.is_multiline(first_span.to(last_span))
2983            && let Some(fallback_indent) = source_map.indentation_before(first_span)
2984        {
2985            ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
2986        } else {
2987            ArgumentsFormatting::SingleLine
2988        }
2989    }
2990
2991    fn suggestion_code(&self) -> (Span, String) {
2992        let source_map = self.sess().source_map();
2993        let suggestion_span = if let Some(args_span) =
2994            self.call_metadata.error_span.trim_start(self.call_metadata.full_call_span)
2995        {
2996            // Span of the braces, e.g. `(a, b, c)`.
2997            args_span
2998        } else {
2999            // The arg span of a function call that wasn't even given braces
3000            // like what might happen with delegation reuse.
3001            // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
3002            self.call_metadata.full_call_span.shrink_to_hi()
3003        };
3004
3005        let arguments_formatting = self.arguments_formatting(suggestion_span);
3006
3007        let mut suggestion = "(".to_owned();
3008        let mut needs_comma = false;
3009        for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
3010            if needs_comma {
3011                suggestion += ",";
3012            }
3013            match &arguments_formatting {
3014                ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
3015                ArgumentsFormatting::SingleLine => {}
3016                ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
3017            }
3018            needs_comma = true;
3019            let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
3020                && let (_, provided_span) = self.provided_arg_tys[*provided_idx]
3021                && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
3022            {
3023                (Some(provided_span), arg_text)
3024            } else {
3025                // Propose a placeholder of the correct type
3026                let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
3027                (None, self.ty_to_snippet(expected_ty, expected_idx))
3028            };
3029            if let ArgumentsFormatting::Multiline { fallback_indent, .. } = &arguments_formatting {
3030                let indent = suggestion_span
3031                    .and_then(|span| source_map.indentation_before(span))
3032                    .unwrap_or_else(|| fallback_indent.clone());
3033                suggestion += &indent;
3034            }
3035            suggestion += &suggestion_text;
3036        }
3037        if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
3038            suggestion += ",\n";
3039            suggestion += &brace_indent;
3040        }
3041        suggestion += ")";
3042
3043        (suggestion_span, suggestion)
3044    }
3045
3046    fn maybe_suggest_expect_for_unwrap(&self, provided_ty: Ty<'tcx>) -> Option<Span> {
3047        let tcx = self.tcx();
3048        if let Some(call_ident) = self.call_metadata.call_ident
3049            && call_ident.name == sym::unwrap
3050            && let Some(callee_ty) = self.callee_ty
3051            && let ty::Adt(adt, _) = callee_ty.peel_refs().kind()
3052            && (tcx.is_diagnostic_item(sym::Option, adt.did())
3053                || tcx.is_diagnostic_item(sym::Result, adt.did()))
3054            && self.may_coerce(provided_ty, Ty::new_static_str(tcx))
3055        {
3056            Some(call_ident.span)
3057        } else {
3058            None
3059        }
3060    }
3061}
3062
3063struct ArgMatchingCtxt<'a, 'tcx> {
3064    args_ctxt: ArgsCtxt<'a, 'tcx>,
3065    provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
3066}
3067
3068impl<'a, 'tcx> Deref for ArgMatchingCtxt<'a, 'tcx> {
3069    type Target = ArgsCtxt<'a, 'tcx>;
3070
3071    fn deref(&self) -> &Self::Target {
3072        &self.args_ctxt
3073    }
3074}
3075
3076impl<'a, 'tcx> ArgMatchingCtxt<'a, 'tcx> {
3077    fn new(
3078        arg: &'a FnCtxt<'a, 'tcx>,
3079        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3080        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3081        provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
3082        c_variadic: bool,
3083        err_code: ErrCode,
3084        fn_def_id: Option<DefId>,
3085        call_span: Span,
3086        call_expr: &'tcx Expr<'tcx>,
3087        tuple_arguments: TupleArgumentsFlag,
3088    ) -> Self {
3089        let args_ctxt = ArgsCtxt::new(
3090            arg,
3091            compatibility_diagonal,
3092            formal_and_expected_inputs,
3093            provided_args,
3094            c_variadic,
3095            err_code,
3096            fn_def_id,
3097            call_span,
3098            call_expr,
3099            tuple_arguments,
3100        );
3101        let provided_arg_tys = args_ctxt.provided_arg_tys();
3102
3103        ArgMatchingCtxt { args_ctxt, provided_arg_tys }
3104    }
3105
3106    fn suggest_confusable(&self, err: &mut Diag<'_>) {
3107        let Some(call_name) = self.call_metadata.call_ident else {
3108            return;
3109        };
3110        let Some(callee_ty) = self.callee_ty else {
3111            return;
3112        };
3113        let input_types: Vec<Ty<'_>> = self.provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
3114
3115        // Check for other methods in the following order
3116        //  - methods marked as `rustc_confusables` with the provided arguments
3117        //  - methods with the same argument type/count and short levenshtein distance
3118        //  - methods marked as `rustc_confusables` (done)
3119        //  - methods with short levenshtein distance
3120
3121        // Look for commonly confusable method names considering arguments.
3122        if let Some(_name) = self.confusable_method_name(
3123            err,
3124            callee_ty.peel_refs(),
3125            call_name,
3126            Some(input_types.clone()),
3127        ) {
3128            return;
3129        }
3130        // Look for method names with short levenshtein distance, considering arguments.
3131        if let Some((assoc, fn_sig)) = self.similar_assoc(call_name)
3132            && fn_sig.inputs()[1..]
3133                .iter()
3134                .eq_by(input_types, |expected, found| self.may_coerce(*expected, found))
3135        {
3136            let assoc_name = assoc.name();
3137            err.span_suggestion_verbose(
3138                call_name.span,
3139                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might have meant to use `{0}`",
                assoc_name))
    })format!("you might have meant to use `{}`", assoc_name),
3140                assoc_name,
3141                Applicability::MaybeIncorrect,
3142            );
3143            return;
3144        }
3145    }
3146
3147    /// A "softer" version of the `demand_compatible`, which checks types without persisting them,
3148    /// and treats error types differently
3149    /// This will allow us to "probe" for other argument orders that would likely have been correct
3150    fn check_compatible(
3151        &self,
3152        provided_idx: ProvidedIdx,
3153        expected_idx: ExpectedIdx,
3154    ) -> Compatibility<'tcx> {
3155        if provided_idx.as_usize() == expected_idx.as_usize() {
3156            return self.compatibility_diagonal[provided_idx].clone();
3157        }
3158
3159        let (formal_input_ty, expected_input_ty) = self.formal_and_expected_inputs[expected_idx];
3160        // If either is an error type, we defy the usual convention and consider them to *not* be
3161        // coercible. This prevents our error message heuristic from trying to pass errors into
3162        // every argument.
3163        if (formal_input_ty, expected_input_ty).references_error() {
3164            return Compatibility::Incompatible(None);
3165        }
3166
3167        let (arg_ty, arg_span) = self.provided_arg_tys[provided_idx];
3168
3169        let expectation = Expectation::rvalue_hint(self.fn_ctxt, expected_input_ty);
3170        let coerced_ty = expectation.only_has_type(self.fn_ctxt).unwrap_or(formal_input_ty);
3171        let can_coerce = self.may_coerce(arg_ty, coerced_ty);
3172        if !can_coerce {
3173            return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
3174                ty::error::ExpectedFound::new(coerced_ty, arg_ty),
3175            )));
3176        }
3177
3178        // Using probe here, since we don't want this subtyping to affect inference.
3179        let subtyping_error = self.probe(|_| {
3180            self.at(&self.misc(arg_span), self.param_env)
3181                .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
3182                .err()
3183        });
3184
3185        // Same as above: if either the coerce type or the checked type is an error type,
3186        // consider them *not* compatible.
3187        let references_error = (coerced_ty, arg_ty).references_error();
3188        match (references_error, subtyping_error) {
3189            (false, None) => Compatibility::Compatible,
3190            (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
3191        }
3192    }
3193
3194    fn remove_idx_is_perfect(&self, idx: usize) -> bool {
3195        let removed_arg_tys = self
3196            .provided_arg_tys
3197            .iter()
3198            .enumerate()
3199            .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
3200            .collect::<IndexVec<ProvidedIdx, _>>();
3201        std::iter::zip(self.formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
3202            |((expected_ty, _), (provided_ty, _))| {
3203                !provided_ty.references_error() && self.may_coerce(*provided_ty, *expected_ty)
3204            },
3205        )
3206    }
3207}
3208
3209struct ArgsCtxt<'a, 'tcx> {
3210    call_ctxt: CallCtxt<'a, 'tcx>,
3211    call_metadata: CallMetadata,
3212    args_span: Span,
3213}
3214
3215impl<'a, 'tcx> Deref for ArgsCtxt<'a, 'tcx> {
3216    type Target = CallCtxt<'a, 'tcx>;
3217
3218    fn deref(&self) -> &Self::Target {
3219        &self.call_ctxt
3220    }
3221}
3222
3223impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> {
3224    fn new(
3225        arg: &'a FnCtxt<'a, 'tcx>,
3226        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3227        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3228        provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
3229        c_variadic: bool,
3230        err_code: ErrCode,
3231        fn_def_id: Option<DefId>,
3232        call_span: Span,
3233        call_expr: &'tcx Expr<'tcx>,
3234        tuple_arguments: TupleArgumentsFlag,
3235    ) -> Self {
3236        let call_ctxt: CallCtxt<'_, '_> = CallCtxt::new(
3237            arg,
3238            compatibility_diagonal,
3239            formal_and_expected_inputs,
3240            provided_args,
3241            c_variadic,
3242            err_code,
3243            fn_def_id,
3244            call_span,
3245            call_expr,
3246            tuple_arguments,
3247        );
3248
3249        let call_metadata = call_ctxt.call_metadata();
3250        let args_span = call_metadata
3251            .error_span
3252            .trim_start(call_metadata.full_call_span)
3253            .unwrap_or(call_metadata.error_span);
3254
3255        ArgsCtxt { args_span, call_metadata, call_ctxt }
3256    }
3257
3258    /// Get the argument span in the context of the call span so that
3259    /// suggestions and labels are (more) correct when an arg is a
3260    /// macro invocation.
3261    fn normalize_span(&self, span: Span) -> Span {
3262        let normalized_span =
3263            span.find_ancestor_inside_same_ctxt(self.call_metadata.error_span).unwrap_or(span);
3264        // Sometimes macros mess up the spans, so do not normalize the
3265        // arg span to equal the error span, because that's less useful
3266        // than pointing out the arg expr in the wrong context.
3267        if normalized_span.source_equal(self.call_metadata.error_span) {
3268            span
3269        } else {
3270            normalized_span
3271        }
3272    }
3273
3274    /// Computes the provided types and spans.
3275    fn provided_arg_tys(&self) -> IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> {
3276        self.call_ctxt
3277            .provided_args
3278            .iter()
3279            .map(|expr| {
3280                let ty = self
3281                    .call_ctxt
3282                    .fn_ctxt
3283                    .typeck_results
3284                    .borrow()
3285                    .expr_ty_adjusted_opt(expr)
3286                    .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx));
3287                (
3288                    self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty),
3289                    self.normalize_span(expr.span),
3290                )
3291            })
3292            .collect()
3293    }
3294
3295    // Obtain another method on `Self` that have similar name.
3296    fn similar_assoc(&self, call_name: Ident) -> Option<(ty::AssocItem, ty::FnSig<'tcx>)> {
3297        if let Some(callee_ty) = self.call_ctxt.callee_ty
3298            && let Ok(Some(assoc)) = self.call_ctxt.fn_ctxt.probe_op(
3299                call_name.span,
3300                MethodCall,
3301                Some(call_name),
3302                None,
3303                IsSuggestion(true),
3304                callee_ty.peel_refs(),
3305                self.call_ctxt.callee_expr.unwrap().hir_id,
3306                TraitsInScope,
3307                |mut ctxt| ctxt.probe_for_similar_candidate(),
3308            )
3309            && assoc.is_method()
3310        {
3311            let args =
3312                self.call_ctxt.fn_ctxt.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
3313            let fn_sig = self
3314                .call_ctxt
3315                .fn_ctxt
3316                .tcx
3317                .fn_sig(assoc.def_id)
3318                .instantiate(self.call_ctxt.fn_ctxt.tcx, args)
3319                .skip_norm_wip();
3320
3321            self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars(
3322                call_name.span,
3323                BoundRegionConversionTime::FnCall,
3324                fn_sig,
3325            );
3326        }
3327        None
3328    }
3329
3330    fn call_is_in_macro(&self) -> bool {
3331        self.call_metadata.full_call_span.in_external_macro(self.sess().source_map())
3332    }
3333}
3334
3335struct CallMetadata {
3336    error_span: Span,
3337    call_ident: Option<Ident>,
3338    full_call_span: Span,
3339    call_name: &'static str,
3340    is_method: bool,
3341}
3342
3343struct CallCtxt<'a, 'tcx> {
3344    fn_ctxt: &'a FnCtxt<'a, 'tcx>,
3345    compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3346    formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3347    provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3348    c_variadic: bool,
3349    err_code: ErrCode,
3350    fn_def_id: Option<DefId>,
3351    call_span: Span,
3352    call_expr: &'tcx hir::Expr<'tcx>,
3353    tuple_arguments: TupleArgumentsFlag,
3354    callee_expr: Option<&'tcx Expr<'tcx>>,
3355    callee_ty: Option<Ty<'tcx>>,
3356}
3357
3358impl<'a, 'tcx> Deref for CallCtxt<'a, 'tcx> {
3359    type Target = &'a FnCtxt<'a, 'tcx>;
3360
3361    fn deref(&self) -> &Self::Target {
3362        &self.fn_ctxt
3363    }
3364}
3365
3366impl<'a, 'tcx> CallCtxt<'a, 'tcx> {
3367    fn new(
3368        fn_ctxt: &'a FnCtxt<'a, 'tcx>,
3369        compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3370        formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3371        provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3372        c_variadic: bool,
3373        err_code: ErrCode,
3374        fn_def_id: Option<DefId>,
3375        call_span: Span,
3376        call_expr: &'tcx hir::Expr<'tcx>,
3377        tuple_arguments: TupleArgumentsFlag,
3378    ) -> CallCtxt<'a, 'tcx> {
3379        let callee_expr = match &call_expr.peel_blocks().kind {
3380            hir::ExprKind::Call(callee, _) => Some(*callee),
3381            hir::ExprKind::MethodCall(_, receiver, ..) => {
3382                if let Some((DefKind::AssocFn, def_id)) =
3383                    fn_ctxt.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
3384                    && let Some(assoc) = fn_ctxt.tcx.opt_associated_item(def_id)
3385                    && assoc.is_method()
3386                {
3387                    Some(*receiver)
3388                } else {
3389                    None
3390                }
3391            }
3392            _ => None,
3393        };
3394
3395        let callee_ty = callee_expr.and_then(|callee_expr| {
3396            fn_ctxt.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
3397        });
3398
3399        CallCtxt {
3400            fn_ctxt,
3401            compatibility_diagonal,
3402            formal_and_expected_inputs,
3403            provided_args,
3404            c_variadic,
3405            err_code,
3406            fn_def_id,
3407            call_span,
3408            call_expr,
3409            tuple_arguments,
3410            callee_expr,
3411            callee_ty,
3412        }
3413    }
3414
3415    fn call_metadata(&self) -> CallMetadata {
3416        match &self.call_expr.kind {
3417            hir::ExprKind::Call(
3418                hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
3419                _,
3420            ) => {
3421                if let Res::Def(DefKind::Ctor(of, _), _) =
3422                    self.typeck_results.borrow().qpath_res(qpath, *hir_id)
3423                {
3424                    let name = match of {
3425                        CtorOf::Struct => "struct",
3426                        CtorOf::Variant => "enum variant",
3427                    };
3428                    CallMetadata {
3429                        error_span: self.call_span,
3430                        call_ident: None,
3431                        full_call_span: *span,
3432                        call_name: name,
3433                        is_method: false,
3434                    }
3435                } else {
3436                    CallMetadata {
3437                        error_span: self.call_span,
3438                        call_ident: None,
3439                        full_call_span: *span,
3440                        call_name: "function",
3441                        is_method: false,
3442                    }
3443                }
3444            }
3445            hir::ExprKind::Call(hir::Expr { span, .. }, _) => CallMetadata {
3446                error_span: self.call_span,
3447                call_ident: None,
3448                full_call_span: *span,
3449                call_name: "function",
3450                is_method: false,
3451            },
3452            hir::ExprKind::MethodCall(path_segment, _, _, span) => {
3453                let ident_span = path_segment.ident.span;
3454                let ident_span = if let Some(args) = path_segment.args {
3455                    ident_span.with_hi(args.span_ext.hi())
3456                } else {
3457                    ident_span
3458                };
3459                CallMetadata {
3460                    error_span: *span,
3461                    call_ident: Some(path_segment.ident),
3462                    full_call_span: ident_span,
3463                    call_name: "method",
3464                    is_method: true,
3465                }
3466            }
3467            k => ::rustc_middle::util::bug::span_bug_fmt(self.call_span,
    format_args!("checking argument types on a non-call: `{0:?}`", k))span_bug!(self.call_span, "checking argument types on a non-call: `{:?}`", k),
3468        }
3469    }
3470
3471    fn mk_trace(
3472        &self,
3473        span: Span,
3474        (formal_ty, expected_ty): (Ty<'tcx>, Ty<'tcx>),
3475        provided_ty: Ty<'tcx>,
3476    ) -> TypeTrace<'tcx> {
3477        let mismatched_ty = if expected_ty == provided_ty {
3478            // If expected == provided, then we must have failed to sup
3479            // the formal type. Avoid printing out "expected Ty, found Ty"
3480            // in that case.
3481            formal_ty
3482        } else {
3483            expected_ty
3484        };
3485        TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
3486    }
3487
3488    fn ty_to_snippet(&self, ty: Ty<'tcx>, expected_idx: ExpectedIdx) -> String {
3489        if ty.is_unit() {
3490            "()".to_string()
3491        } else if ty.is_suggestable(self.tcx, false) {
3492            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("/* {0} */", ty))
    })format!("/* {ty} */")
3493        } else if let Some(fn_def_id) = self.fn_def_id
3494            && self.tcx.def_kind(fn_def_id).is_fn_like()
3495            && let self_implicit =
3496                #[allow(non_exhaustive_omitted_patterns)] match self.call_expr.kind {
    hir::ExprKind::MethodCall(..) => true,
    _ => false,
}matches!(self.call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
3497            && let Some(Some(arg)) =
3498                self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
3499            && arg.name != kw::SelfLower
3500        {
3501            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("/* {0} */", arg.name))
    })format!("/* {} */", arg.name)
3502        } else {
3503            "/* value */".to_string()
3504        }
3505    }
3506
3507    fn first_incompatible_error(&self) -> Option<(ProvidedIdx, TypeError<'tcx>)> {
3508        self.compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
3509            if let Compatibility::Incompatible(Some(terr)) = c { Some((i, *terr)) } else { None }
3510        })
3511    }
3512}
3513
3514enum SuggestionText {
3515    None,
3516    Provide(bool),
3517    Remove(bool),
3518    Swap,
3519    Reorder,
3520    DidYouMean,
3521}