Skip to main content

rustc_hir_typeck/fn_ctxt/
checks.rs

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