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