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