rustc_hir_typeck/fn_ctxt/
checks.rs

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