Skip to main content

rustc_hir_typeck/fn_ctxt/
checks.rs

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