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