Skip to main content

rustc_hir_typeck/fn_ctxt/
checks.rs

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