rustc_hir_typeck/fn_ctxt/
checks.rs

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