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