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