Skip to main content

rustc_hir_typeck/
demand.rs

1use rustc_attr_ir::find_attr;
2use rustc_errors::{Applicability, Diag, MultiSpan, listify, pluralize};
3use rustc_hir as hir;
4use rustc_hir::def::{DefKind, Res};
5use rustc_hir::intravisit::Visitor;
6use rustc_infer::infer::DefineOpaqueTypes;
7use rustc_middle::ty::adjustment::AllowTwoPhase;
8use rustc_middle::ty::error::{ExpectedFound, TypeError};
9use rustc_middle::ty::print::with_no_trimmed_paths;
10use rustc_middle::ty::{self, AssocItem, BottomUpFolder, Ty, TypeFoldable, TypeVisitableExt};
11use rustc_span::{DUMMY_SP, Ident, Span, bug, span_bug, sym};
12use rustc_trait_selection::infer::InferCtxtExt;
13use rustc_trait_selection::traits::ObligationCause;
14use tracing::instrument;
15
16use super::method::probe;
17use crate::FnCtxt;
18
19impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20    pub(crate) fn emit_type_mismatch_suggestions(
21        &self,
22        err: &mut Diag<'_>,
23        expr: &hir::Expr<'tcx>,
24        expr_ty: Ty<'tcx>,
25        expected: Ty<'tcx>,
26        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
27        error: Option<TypeError<'tcx>>,
28    ) {
29        if expr_ty == expected {
30            return;
31        }
32        self.annotate_alternative_method_deref_for_unop(err, expr, error);
33        self.explain_self_literal(err, expr, expected, expr_ty);
34
35        // Use `||` to give these suggestions a precedence
36        let suggested = self.suggest_missing_parentheses(err, expr)
37            || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
38            || self.suggest_remove_last_method_call(err, expr, expected)
39            || self.suggest_associated_const(err, expr, expected)
40            || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
41            || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
42            || self.suggest_option_to_bool(err, expr, expr_ty, expected)
43            || self.suggest_collect(err, expr, expected, expr_ty)
44            || self.suggest_compatible_variants(err, expr, expected, expr_ty)
45            || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
46            || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
47            || self.suggest_closure_to_fn_ptr_coercion(err, expr, expected, expr_ty)
48            || self.suggest_boxing_when_appropriate(
49                err,
50                expr.peel_blocks().span,
51                expr.hir_id,
52                expected,
53                expr_ty,
54            )
55            || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
56            || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected)
57            || self.suggest_clone_for_ref(err, expr, expr_ty, expected)
58            || self.suggest_into(err, expr, expr_ty, expected)
59            || self.suggest_floating_point_literal(err, expr, expected)
60            || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
61            || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
62            || self.suggest_returning_value_after_loop(err, expr, expected);
63
64        if !suggested {
65            self.note_source_of_type_mismatch_constraint(
66                err,
67                expr,
68                TypeMismatchSource::Ty(expected),
69            );
70        }
71    }
72
73    pub(crate) fn emit_coerce_suggestions(
74        &self,
75        err: &mut Diag<'_>,
76        expr: &hir::Expr<'tcx>,
77        expr_ty: Ty<'tcx>,
78        expected: Ty<'tcx>,
79        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
80        error: Option<TypeError<'tcx>>,
81    ) {
82        if expr_ty == expected {
83            return;
84        }
85
86        self.annotate_expected_due_to_let_ty(err, expr, error);
87        self.annotate_loop_expected_due_to_inference(err, expr, error);
88        if self.annotate_mut_binding_to_immutable_binding(err, expr, expr_ty, expected, error) {
89            return;
90        }
91
92        // FIXME(#73154): For now, we do leak check when coercing function
93        // pointers in typeck, instead of only during borrowck. This can lead
94        // to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
95        if #[allow(non_exhaustive_omitted_patterns)] match error {
    Some(TypeError::RegionsInsufficientlyPolymorphic(..)) => true,
    _ => false,
}matches!(error, Some(TypeError::RegionsInsufficientlyPolymorphic(..))) {
96            return;
97        }
98
99        if self.is_destruct_assignment_desugaring(expr) {
100            return;
101        }
102        self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
103        self.note_type_is_not_clone(err, expected, expr_ty, expr);
104        self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty);
105        self.suggest_method_call_on_range_literal(err, expr, expr_ty, expected);
106        self.suggest_return_binding_for_missing_tail_expr(err, expr, expr_ty, expected);
107        self.note_wrong_return_ty_due_to_generic_arg(err, expr, expr_ty);
108    }
109
110    /// Really hacky heuristic to remap an `assert_eq!` error to the user
111    /// expressions provided to the macro.
112    fn adjust_expr_for_assert_eq_macro(
113        &self,
114        found_expr: &mut &'tcx hir::Expr<'tcx>,
115        expected_expr: &mut Option<&'tcx hir::Expr<'tcx>>,
116    ) {
117        let Some(expected_expr) = expected_expr else {
118            return;
119        };
120
121        if !found_expr.span.eq_ctxt(expected_expr.span) {
122            return;
123        }
124
125        if !found_expr
126            .span
127            .ctxt()
128            .outer_expn_data()
129            .macro_def_id
130            .is_some_and(|def_id| self.tcx.is_diagnostic_item(sym::assert_eq_macro, def_id))
131        {
132            return;
133        }
134
135        let hir::ExprKind::Unary(
136            hir::UnOp::Deref,
137            hir::Expr { kind: hir::ExprKind::Path(found_path), .. },
138        ) = found_expr.kind
139        else {
140            return;
141        };
142        let hir::ExprKind::Unary(
143            hir::UnOp::Deref,
144            hir::Expr { kind: hir::ExprKind::Path(expected_path), .. },
145        ) = expected_expr.kind
146        else {
147            return;
148        };
149
150        for (path, name, idx, var) in [
151            (expected_path, "left_val", 0, expected_expr),
152            (found_path, "right_val", 1, found_expr),
153        ] {
154            if let hir::QPath::Resolved(_, path) = path
155                && let [segment] = path.segments
156                && segment.ident.name.as_str() == name
157                && let Res::Local(hir_id) = path.res
158                && let Some((_, hir::Node::Expr(match_expr))) =
159                    self.tcx.hir_parent_iter(hir_id).nth(2)
160                && let hir::ExprKind::Match(scrutinee, _, _) = match_expr.kind
161                && let hir::ExprKind::Tup(exprs) = scrutinee.kind
162                && let hir::ExprKind::AddrOf(_, _, macro_arg) = exprs[idx].kind
163            {
164                *var = macro_arg;
165            }
166        }
167    }
168
169    /// Requires that the two types unify, and prints an error message if
170    /// they don't.
171    pub(crate) fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
172        if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
173            e.emit();
174        }
175    }
176
177    pub(crate) fn demand_suptype_diag(
178        &'a self,
179        sp: Span,
180        expected: Ty<'tcx>,
181        actual: Ty<'tcx>,
182    ) -> Result<(), Diag<'a>> {
183        self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
184    }
185
186    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("demand_suptype_with_origin",
                                    "rustc_hir_typeck::demand", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/28221559263a3976766cf305940e80e30cf9ba8a/compiler/rustc_hir_typeck/src/demand.rs"),
                                    ::tracing_core::__macro_support::Option::Some(186u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::demand"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("cause")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("cause");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Result<(), Diag<'a>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            self.at(cause,
                            self.param_env).sup(DefineOpaqueTypes::Yes, expected,
                        actual).map(|infer_ok|
                        self.register_infer_ok_obligations(infer_ok)).map_err(|e|
                    {
                        self.err_ctxt().report_mismatched_types(cause,
                            self.param_env, expected, actual, e)
                    })
        }
    }
}#[instrument(skip(self), level = "debug")]
187    pub(crate) fn demand_suptype_with_origin(
188        &'a self,
189        cause: &ObligationCause<'tcx>,
190        expected: Ty<'tcx>,
191        actual: Ty<'tcx>,
192    ) -> Result<(), Diag<'a>> {
193        self.at(cause, self.param_env)
194            .sup(DefineOpaqueTypes::Yes, expected, actual)
195            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
196            .map_err(|e| {
197                self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e)
198            })
199    }
200
201    pub(crate) fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
202        if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
203            err.emit();
204        }
205    }
206
207    pub(crate) fn demand_eqtype_diag(
208        &'a self,
209        sp: Span,
210        expected: Ty<'tcx>,
211        actual: Ty<'tcx>,
212    ) -> Result<(), Diag<'a>> {
213        self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
214    }
215
216    pub(crate) fn demand_eqtype_with_origin(
217        &'a self,
218        cause: &ObligationCause<'tcx>,
219        expected: Ty<'tcx>,
220        actual: Ty<'tcx>,
221    ) -> Result<(), Diag<'a>> {
222        self.at(cause, self.param_env)
223            .eq(DefineOpaqueTypes::Yes, expected, actual)
224            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
225            .map_err(|e| {
226                self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e)
227            })
228    }
229
230    pub(crate) fn demand_coerce(
231        &self,
232        expr: &'tcx hir::Expr<'tcx>,
233        checked_ty: Ty<'tcx>,
234        expected: Ty<'tcx>,
235        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
236        allow_two_phase: AllowTwoPhase,
237    ) -> Ty<'tcx> {
238        match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
239        {
240            Ok(ty) => ty,
241            Err(err) => {
242                err.emit();
243                // Return the original type instead of an error type here, otherwise the type of `x` in
244                // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
245                // report errors, even though `x` is definitely `u32`.
246                expected
247            }
248        }
249    }
250
251    /// Checks that the type of `expr` can be coerced to `expected`.
252    ///
253    /// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!`
254    /// will be permitted if the diverges flag is currently "always".
255    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("demand_coerce_diag",
                                    "rustc_hir_typeck::demand", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/28221559263a3976766cf305940e80e30cf9ba8a/compiler/rustc_hir_typeck/src/demand.rs"),
                                    ::tracing_core::__macro_support::Option::Some(255u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::demand"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("checked_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("checked_ty");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&checked_ty)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Result<Ty<'tcx>, Diag<'a>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let expected =
                self.deeply_resolve_ignoring_regions_with_obligations(expected);
            let e =
                match self.coerce(expr, checked_ty, expected, allow_two_phase,
                        None) {
                    Ok(ty) => return Ok(ty),
                    Err(e) => e,
                };
            self.adjust_expr_for_assert_eq_macro(&mut expr,
                &mut expected_ty_expr);
            self.set_tainted_by_errors(self.dcx().span_delayed_bug(expr.span,
                    "`TypeError` when attempting coercion but no error emitted"));
            let expr = expr.peel_drop_temps();
            let cause = self.misc(expr.span);
            let expr_ty = self.deeply_resolve_ignoring_regions(checked_ty);
            let mut err =
                self.err_ctxt().report_mismatched_types(&cause,
                    self.param_env, expected, expr_ty, e);
            self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected,
                expected_ty_expr, Some(e));
            Err(err)
        }
    }
}#[instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
256    pub(crate) fn demand_coerce_diag(
257        &'a self,
258        mut expr: &'tcx hir::Expr<'tcx>,
259        checked_ty: Ty<'tcx>,
260        expected: Ty<'tcx>,
261        mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
262        allow_two_phase: AllowTwoPhase,
263    ) -> Result<Ty<'tcx>, Diag<'a>> {
264        let expected = self.deeply_resolve_ignoring_regions_with_obligations(expected);
265
266        let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
267            Ok(ty) => return Ok(ty),
268            Err(e) => e,
269        };
270
271        self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr);
272
273        self.set_tainted_by_errors(self.dcx().span_delayed_bug(
274            expr.span,
275            "`TypeError` when attempting coercion but no error emitted",
276        ));
277        let expr = expr.peel_drop_temps();
278        let cause = self.misc(expr.span);
279        let expr_ty = self.deeply_resolve_ignoring_regions(checked_ty);
280        let mut err =
281            self.err_ctxt().report_mismatched_types(&cause, self.param_env, expected, expr_ty, e);
282
283        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
284
285        Err(err)
286    }
287
288    /// Notes the point at which a variable is constrained to some type incompatible
289    /// with some expectation given by `source`.
290    pub(crate) fn note_source_of_type_mismatch_constraint(
291        &self,
292        err: &mut Diag<'_>,
293        expr: &hir::Expr<'_>,
294        source: TypeMismatchSource<'tcx>,
295    ) -> bool {
296        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else {
297            return false;
298        };
299        let [hir::PathSegment { ident, args: None, .. }] = p.segments else {
300            return false;
301        };
302        let hir::def::Res::Local(local_hir_id) = p.res else {
303            return false;
304        };
305        let hir::Node::Pat(pat) = self.tcx.hir_node(local_hir_id) else {
306            return false;
307        };
308        let (init_ty_hir_id, init) = match self.tcx.parent_hir_node(pat.hir_id) {
309            hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init, .. }) => (ty.hir_id, *init),
310            hir::Node::LetStmt(hir::LetStmt { init: Some(init), .. }) => (init.hir_id, Some(*init)),
311            _ => return false,
312        };
313        let Some(init_ty) = self.node_ty_opt(init_ty_hir_id) else {
314            return false;
315        };
316
317        // Locate all the usages of the relevant binding.
318        struct FindExprs<'tcx> {
319            hir_id: hir::HirId,
320            uses: Vec<&'tcx hir::Expr<'tcx>>,
321        }
322        impl<'tcx> Visitor<'tcx> for FindExprs<'tcx> {
323            fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
324                if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
325                    && let hir::def::Res::Local(hir_id) = path.res
326                    && hir_id == self.hir_id
327                {
328                    self.uses.push(ex);
329                }
330                hir::intravisit::walk_expr(self, ex);
331            }
332        }
333
334        let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() };
335        let body = self.tcx.hir_body_owned_by(self.body_def_id);
336        expr_finder.visit_expr(body.value);
337
338        // Replaces all of the variables in the given type with a fresh inference variable.
339        let mut fudger = BottomUpFolder {
340            tcx: self.tcx,
341            ty_op: |ty| {
342                if let ty::Infer(infer) = ty.kind() {
343                    match infer {
344                        ty::TyVar(_) => self.next_ty_var(DUMMY_SP),
345                        ty::IntVar(_) => self.next_int_var(),
346                        ty::FloatVar(_) => self.next_float_var(DUMMY_SP, None),
347                        ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
348                            ::rustc_span::macros::bug_impl(None,
    format_args!("unexpected fresh ty outside of the trait solver"),
    Location::caller())bug!("unexpected fresh ty outside of the trait solver")
349                        }
350                    }
351                } else {
352                    ty
353                }
354            },
355            lt_op: |_| self.tcx.lifetimes.re_erased,
356            ct_op: |ct| {
357                if let ty::ConstKind::Infer(_) = ct.kind() {
358                    self.next_const_var(DUMMY_SP)
359                } else {
360                    ct
361                }
362            },
363        };
364
365        let expected_ty = match source {
366            TypeMismatchSource::Ty(expected_ty) => expected_ty,
367            // Try to deduce what the possible value of `expr` would be if the
368            // incompatible arg were compatible. For example, given `Vec<i32>`
369            // and `vec.push(1u32)`, we ideally want to deduce that the type of
370            // `vec` *should* have been `Vec<u32>`. This will allow us to then
371            // run the subsequent code with this expectation, finding out exactly
372            // when this type diverged from our expectation.
373            TypeMismatchSource::Arg { call_expr, incompatible_arg: idx } => {
374                let hir::ExprKind::MethodCall(segment, _, args, _) = call_expr.kind else {
375                    return false;
376                };
377                let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
378                    return false;
379                };
380                let possible_rcvr_ty = expr_finder.uses.iter().rev().find_map(|binding| {
381                    let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?;
382                    if possible_rcvr_ty.is_ty_var() {
383                        return None;
384                    }
385                    // Fudge the receiver, so we can do new inference on it.
386                    let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
387                    let method = self
388                        .lookup_method_for_diagnostic(
389                            possible_rcvr_ty,
390                            segment,
391                            DUMMY_SP,
392                            call_expr,
393                            binding,
394                        )
395                        .ok()?;
396                    // Make sure we select the same method that we started with...
397                    if Some(method.def_id)
398                        != self.typeck_results.borrow().type_dependent_def_id(call_expr.hir_id)
399                    {
400                        return None;
401                    }
402                    // Unify the method signature with our incompatible arg, to
403                    // do inference in the *opposite* direction and to find out
404                    // what our ideal rcvr ty would look like.
405                    let Some(input_arg) = method.sig.inputs().get(idx + 1) else {
406                        if method.sig.splatted().is_some() {
407                            // FIXME(splat): when the arg is splatted, adjust its index, to handle the type mismatch properly
408                            return None;
409                        } else {
410                            ::rustc_span::macros::bug_impl(Some(self.tcx.def_span(method.def_id)),
    format_args!("arg index {0} out of bounds for method with {1} inputs",
        idx + 1, method.sig.inputs().len()), Location::caller());span_bug!(
411                                self.tcx.def_span(method.def_id),
412                                "arg index {} out of bounds for method with {} inputs",
413                                idx + 1,
414                                method.sig.inputs().len(),
415                            );
416                        }
417                    };
418                    let _ = self
419                        .at(&ObligationCause::dummy(), self.param_env)
420                        .eq(DefineOpaqueTypes::Yes, *input_arg, arg_ty)
421                        .ok()?;
422                    self.select_obligations_where_possible(|errs| {
423                        // Yeet the errors, we're already reporting errors.
424                        errs.clear();
425                    });
426                    Some(self.deeply_resolve_ignoring_regions(possible_rcvr_ty))
427                });
428                let Some(rcvr_ty) = possible_rcvr_ty else { return false };
429                rcvr_ty
430            }
431        };
432
433        // If our expected_ty does not equal init_ty, then it *began* as incompatible.
434        // No need to note in this case...
435        if !self.can_eq(self.param_env, expected_ty, init_ty.fold_with(&mut fudger)) {
436            return false;
437        }
438
439        for window in expr_finder.uses.windows(2) {
440            // Bindings always update their recorded type after the fact, so we
441            // need to look at the *following* usage's type to see when the
442            // binding became incompatible.
443            let [binding, next_usage] = *window else {
444                continue;
445            };
446
447            // Don't go past the binding (always gonna be a nonsense label if so)
448            if binding.hir_id == expr.hir_id {
449                break;
450            }
451
452            let Some(next_use_ty) = self.node_ty_opt(next_usage.hir_id) else {
453                continue;
454            };
455
456            // If the type is not constrained in a way making it not possible to
457            // equate with `expected_ty` by this point, skip.
458            if self.can_eq(self.param_env, expected_ty, next_use_ty.fold_with(&mut fudger)) {
459                continue;
460            }
461
462            if let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(binding.hir_id)
463                && let hir::ExprKind::MethodCall(segment, rcvr, args, _) = parent_expr.kind
464                && rcvr.hir_id == binding.hir_id
465            {
466                // If our binding became incompatible while it was a receiver
467                // to a method call, we may be able to make a better guess to
468                // the source of a type mismatch.
469                let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else {
470                    continue;
471                };
472                let rcvr_ty = rcvr_ty.fold_with(&mut fudger);
473                let Ok(method) = self.lookup_method_for_diagnostic(
474                    rcvr_ty,
475                    segment,
476                    DUMMY_SP,
477                    parent_expr,
478                    rcvr,
479                ) else {
480                    continue;
481                };
482                // Make sure we select the same method that we started with...
483                if Some(method.def_id)
484                    != self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
485                {
486                    continue;
487                }
488
489                let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
490                let ideal_method = self
491                    .lookup_method_for_diagnostic(
492                        ideal_rcvr_ty,
493                        segment,
494                        DUMMY_SP,
495                        parent_expr,
496                        rcvr,
497                    )
498                    .ok()
499                    .and_then(|method| {
500                        let _ = self
501                            .at(&ObligationCause::dummy(), self.param_env)
502                            .eq(DefineOpaqueTypes::Yes, ideal_rcvr_ty, expected_ty)
503                            .ok()?;
504                        Some(method)
505                    });
506
507                // Find what argument caused our rcvr to become incompatible
508                // with the expected ty.
509                for (idx, (expected_arg_ty, arg_expr)) in
510                    std::iter::zip(&method.sig.inputs()[1..], args).enumerate()
511                {
512                    let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else {
513                        continue;
514                    };
515                    let arg_ty = arg_ty.fold_with(&mut fudger);
516                    let _ =
517                        self.coerce(arg_expr, arg_ty, *expected_arg_ty, AllowTwoPhase::No, None);
518                    self.select_obligations_where_possible(|errs| {
519                        // Yeet the errors, we're already reporting errors.
520                        errs.clear();
521                    });
522                    // If our rcvr, after inference due to unifying the signature
523                    // with the expected argument type, is still compatible with
524                    // the rcvr, then it must've not been the source of blame.
525                    if self.can_eq(self.param_env, rcvr_ty, expected_ty) {
526                        continue;
527                    }
528                    err.span_label(arg_expr.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this argument has type `{0}`...",
                arg_ty))
    })format!("this argument has type `{arg_ty}`..."));
529                    err.span_label(
530                        binding.span,
531                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("... which causes `{0}` to have type `{1}`",
                ident, next_use_ty))
    })format!("... which causes `{ident}` to have type `{next_use_ty}`"),
532                    );
533                    // Using our "ideal" method signature, suggest a fix to this
534                    // blame arg, if possible. Don't do this if we're coming from
535                    // arg mismatch code, because we'll possibly suggest a mutually
536                    // incompatible fix at the original mismatch site.
537                    // HACK(compiler-errors): We don't actually consider the implications
538                    // of our inference guesses in `emit_type_mismatch_suggestions`, so
539                    // only suggest things when we know our type error is precisely due to
540                    // a type mismatch, and not via some projection or something. See #116155.
541                    if #[allow(non_exhaustive_omitted_patterns)] match source {
    TypeMismatchSource::Ty(_) => true,
    _ => false,
}matches!(source, TypeMismatchSource::Ty(_))
542                        && let Some(ideal_method) = ideal_method
543                        && Some(ideal_method.def_id)
544                            == self
545                                .typeck_results
546                                .borrow()
547                                .type_dependent_def_id(parent_expr.hir_id)
548                        && let ideal_arg_ty =
549                            self.deeply_resolve_ignoring_regions(ideal_method.sig.inputs()[idx + 1])
550                        && !ideal_arg_ty.has_non_region_infer()
551                    {
552                        self.emit_type_mismatch_suggestions(
553                            err,
554                            arg_expr,
555                            arg_ty,
556                            ideal_arg_ty,
557                            None,
558                            None,
559                        );
560                    }
561                    return true;
562                }
563            }
564            err.span_label(
565                binding.span,
566                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("here the type of `{0}` is inferred to be `{1}`",
                ident, next_use_ty))
    })format!("here the type of `{ident}` is inferred to be `{next_use_ty}`"),
567            );
568            return true;
569        }
570
571        // We must've not found something that constrained the expr.
572        false
573    }
574
575    // When encountering a type error on the value of a `break`, try to point at the reason for the
576    // expected type.
577    pub(crate) fn annotate_loop_expected_due_to_inference(
578        &self,
579        err: &mut Diag<'_>,
580        expr: &hir::Expr<'_>,
581        error: Option<TypeError<'tcx>>,
582    ) {
583        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
584            return;
585        };
586        let mut parent_id = self.tcx.parent_hir_id(expr.hir_id);
587        let mut parent;
588        'outer: loop {
589            // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement.
590            let (hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(p), .. })
591            | hir::Node::Block(&hir::Block { expr: Some(p), .. })
592            | hir::Node::Expr(p)) = self.tcx.hir_node(parent_id)
593            else {
594                break;
595            };
596            parent = p;
597            parent_id = self.tcx.parent_hir_id(parent_id);
598            let hir::ExprKind::Break(destination, _) = parent.kind else {
599                continue;
600            };
601            let mut parent_id = parent_id;
602            let mut direct = false;
603            loop {
604                // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
605                let parent = match self.tcx.hir_node(parent_id) {
606                    hir::Node::Expr(parent) => {
607                        parent_id = self.tcx.parent_hir_id(parent.hir_id);
608                        parent
609                    }
610                    hir::Node::Stmt(hir::Stmt {
611                        hir_id,
612                        kind: hir::StmtKind::Semi(parent) | hir::StmtKind::Expr(parent),
613                        ..
614                    }) => {
615                        parent_id = self.tcx.parent_hir_id(*hir_id);
616                        parent
617                    }
618                    hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Let(_), .. }) => {
619                        parent_id = self.tcx.parent_hir_id(*hir_id);
620                        parent
621                    }
622                    hir::Node::LetStmt(hir::LetStmt { hir_id, .. }) => {
623                        parent_id = self.tcx.parent_hir_id(*hir_id);
624                        parent
625                    }
626                    hir::Node::Block(_) => {
627                        parent_id = self.tcx.parent_hir_id(parent_id);
628                        parent
629                    }
630                    _ => break,
631                };
632                if let hir::ExprKind::Loop(..) = parent.kind {
633                    // When you have `'a: loop { break; }`, the `break` corresponds to the labeled
634                    // loop, so we need to account for that.
635                    direct = !direct;
636                }
637                if let hir::ExprKind::Loop(block, label, _, span) = parent.kind
638                    && (destination.label == label || direct)
639                {
640                    if let Some((reason_span, message)) =
641                        self.maybe_get_coercion_reason(parent_id, parent.span)
642                    {
643                        err.span_label(reason_span, message);
644                        err.span_label(
645                            span,
646                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this loop is expected to be of type `{0}`",
                expected))
    })format!("this loop is expected to be of type `{expected}`"),
647                        );
648                        break 'outer;
649                    } else {
650                        // Locate all other `break` statements within the same `loop` that might
651                        // have affected inference.
652                        struct FindBreaks<'tcx> {
653                            label: Option<rustc_ast::Label>,
654                            uses: Vec<&'tcx hir::Expr<'tcx>>,
655                            nest_depth: usize,
656                        }
657                        impl<'tcx> Visitor<'tcx> for FindBreaks<'tcx> {
658                            fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
659                                let nest_depth = self.nest_depth;
660                                if let hir::ExprKind::Loop(_, label, _, _) = ex.kind {
661                                    if label == self.label {
662                                        // Account for `'a: loop { 'a: loop {...} }`.
663                                        return;
664                                    }
665                                    self.nest_depth += 1;
666                                }
667                                if let hir::ExprKind::Break(destination, _) = ex.kind
668                                    && (self.label == destination.label
669                                        // Account for `loop { 'a: loop { loop { break; } } }`.
670                                        || destination.label.is_none() && self.nest_depth == 0)
671                                {
672                                    self.uses.push(ex);
673                                }
674                                hir::intravisit::walk_expr(self, ex);
675                                self.nest_depth = nest_depth;
676                            }
677                        }
678                        let mut expr_finder = FindBreaks { label, uses: ::alloc::vec::Vec::new()vec![], nest_depth: 0 };
679                        expr_finder.visit_block(block);
680                        let mut exit = false;
681                        for ex in expr_finder.uses {
682                            let hir::ExprKind::Break(_, val) = ex.kind else {
683                                continue;
684                            };
685                            let ty = match val {
686                                Some(val) => {
687                                    match self.typeck_results.borrow().expr_ty_adjusted_opt(val) {
688                                        None => continue,
689                                        Some(ty) => ty,
690                                    }
691                                }
692                                None => self.tcx.types.unit,
693                            };
694                            if self.can_eq(self.param_env, ty, expected) {
695                                err.span_label(ex.span, "expected because of this `break`");
696                                exit = true;
697                            }
698                        }
699                        if exit {
700                            break 'outer;
701                        }
702                    }
703                }
704            }
705        }
706    }
707
708    fn annotate_expected_due_to_let_ty(
709        &self,
710        err: &mut Diag<'_>,
711        expr: &hir::Expr<'_>,
712        error: Option<TypeError<'tcx>>,
713    ) {
714        // Skip nested block to find the correct parent node to point at.
715        let mut current_hir_id = expr.hir_id;
716        let parent = self
717            .tcx
718            .hir_parent_iter(expr.hir_id)
719            .find_map(|(parent_hir_id, parent)| match parent {
720                hir::Node::Block(block)
721                    if block.expr.is_some_and(|expr| expr.hir_id == current_hir_id) =>
722                {
723                    current_hir_id = parent_hir_id;
724                    None
725                }
726                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. })
727                    if block.hir_id == current_hir_id =>
728                {
729                    current_hir_id = parent_hir_id;
730                    None
731                }
732                parent => Some(parent),
733            })
734            .expect("an expression must have a non-block ancestor");
735
736        match (parent, error) {
737            (hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init: Some(init), .. }), _)
738                if init.hir_id == current_hir_id && ty.span.lo_hi() != init.span.lo_hi() =>
739            {
740                // Point at `let` assignment type.
741                err.span_label(ty.span, "expected due to this");
742            }
743            (
744                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }),
745                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
746            ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
747                // We ignore closures explicitly because we already point at them elsewhere.
748                // Point at the assigned-to binding.
749                let mut primary_span = lhs.span;
750                let mut secondary_span = lhs.span;
751                let mut post_message = "";
752                match lhs.kind {
753                    hir::ExprKind::Path(hir::QPath::Resolved(
754                        None,
755                        hir::Path {
756                            res: hir::def::Res::Def(DefKind::Static { .. } | DefKind::Const, def_id),
757                            ..
758                        },
759                    )) => {
760                        if let Some(hir::Node::Item(hir::Item {
761                            kind:
762                                hir::ItemKind::Static(_, ident, ty, _)
763                                | hir::ItemKind::Const(ident, _, ty, _),
764                            ..
765                        })) = self.tcx.hir_get_if_local(*def_id)
766                        {
767                            primary_span = ty.span;
768                            secondary_span = ident.span;
769                            post_message = " type";
770                        }
771                    }
772                    hir::ExprKind::Path(hir::QPath::Resolved(
773                        None,
774                        hir::Path { res: hir::def::Res::Local(hir_id), .. },
775                    )) => {
776                        if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) {
777                            primary_span = pat.span;
778                            secondary_span = pat.span;
779                            match self.tcx.parent_hir_node(pat.hir_id) {
780                                hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => {
781                                    primary_span = ty.span;
782                                    post_message = " type";
783                                }
784                                hir::Node::LetStmt(hir::LetStmt { init: Some(init), .. }) => {
785                                    primary_span = init.span;
786                                    post_message = " value";
787                                }
788                                hir::Node::Param(hir::Param { ty_span, .. }) => {
789                                    primary_span = *ty_span;
790                                    post_message = " parameter type";
791                                }
792                                _ => {}
793                            }
794                        }
795                    }
796                    _ => {}
797                }
798
799                if primary_span != secondary_span
800                    && self
801                        .tcx
802                        .sess
803                        .source_map()
804                        .is_multiline(secondary_span.shrink_to_hi().until(primary_span))
805                {
806                    // We are pointing at the binding's type or initializer value, but it's pattern
807                    // is in a different line, so we point at both.
808                    err.span_label(secondary_span, "expected due to the type of this binding");
809                    err.span_label(primary_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected due to this{0}",
                post_message))
    })format!("expected due to this{post_message}"));
810                } else if post_message.is_empty() {
811                    // We are pointing at either the assignment lhs or the binding def pattern.
812                    err.span_label(primary_span, "expected due to the type of this binding");
813                } else {
814                    // We are pointing at the binding's type or initializer value.
815                    err.span_label(primary_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected due to this{0}",
                post_message))
    })format!("expected due to this{post_message}"));
816                }
817
818                if !lhs.is_syntactic_place_expr() {
819                    // We already emitted E0070 "invalid left-hand side of assignment", so we
820                    // silence this.
821                    err.downgrade_to_delayed_bug();
822                }
823            }
824            (
825                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }),
826                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
827            ) if rhs.hir_id == expr.hir_id
828                && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected)
829                // let expressions being marked as `bool` is confusing (see issue #147665)
830                && !#[allow(non_exhaustive_omitted_patterns)] match lhs.kind {
    hir::ExprKind::Let(..) => true,
    _ => false,
}matches!(lhs.kind, hir::ExprKind::Let(..)) =>
831            {
832                err.span_label(lhs.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected because this is `{0}`",
                expected))
    })format!("expected because this is `{expected}`"));
833            }
834            _ => {}
835        }
836    }
837
838    /// Detect the following case
839    ///
840    /// ```text
841    /// fn change_object(mut b: &Ty) {
842    ///     let a = Ty::new();
843    ///     b = a;
844    /// }
845    /// ```
846    ///
847    /// where the user likely meant to modify the value behind there reference, use `b` as an out
848    /// parameter, instead of mutating the local binding. When encountering this we suggest:
849    ///
850    /// ```text
851    /// fn change_object(b: &'_ mut Ty) {
852    ///     let a = Ty::new();
853    ///     *b = a;
854    /// }
855    /// ```
856    fn annotate_mut_binding_to_immutable_binding(
857        &self,
858        err: &mut Diag<'_>,
859        expr: &hir::Expr<'_>,
860        expr_ty: Ty<'tcx>,
861        expected: Ty<'tcx>,
862        error: Option<TypeError<'tcx>>,
863    ) -> bool {
864        if let Some(TypeError::Sorts(ExpectedFound { .. })) = error
865            && let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()
866
867            // The difference between the expected and found values is one level of borrowing.
868            && self.can_eq(self.param_env, *inner, expr_ty)
869
870            // We have an `ident = expr;` assignment.
871            && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
872                self.tcx.parent_hir_node(expr.hir_id)
873            && rhs.hir_id == expr.hir_id
874
875            // We are assigning to some binding.
876            && let hir::ExprKind::Path(hir::QPath::Resolved(
877                None,
878                hir::Path { res: hir::def::Res::Local(hir_id), .. },
879            )) = lhs.kind
880            && let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id)
881
882            // The pattern we have is an fn argument.
883            && let hir::Node::Param(hir::Param { ty_span, .. }) =
884                self.tcx.parent_hir_node(pat.hir_id)
885            && let item = self.tcx.hir_get_parent_item(pat.hir_id)
886            && let item = self.tcx.hir_owner_node(item)
887            && let Some(fn_decl) = item.fn_decl()
888
889            // We have a mutable binding in the argument.
890            && let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
891
892            // Look for the type corresponding to the argument pattern we have in the argument list.
893            && let Some(ty_ref) = fn_decl
894                .inputs
895                .iter()
896                .filter_map(|ty| match ty.kind {
897                    hir::TyKind::Ref(lt, inner_ty, mutbl) if ty.span == *ty_span => Some((lt, inner_ty, mutbl)),
898                    _ => None,
899                })
900                .next()
901        {
902            let mut sugg = if ty_ref.2.is_mut() {
903                // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
904                ::alloc::vec::Vec::new()vec![]
905            } else {
906                // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
907                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ty_ref.1.span.shrink_to_lo(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}mut ",
                                    if ty_ref.0.ident.span.is_empty() { "" } else { " " }))
                        }))]))vec![(
908                    ty_ref.1.span.shrink_to_lo(),
909                    format!("{}mut ", if ty_ref.0.ident.span.is_empty() { "" } else { " " },),
910                )]
911            };
912            sugg.extend([
913                (pat.span.until(ident.span), String::new()),
914                (lhs.span.shrink_to_lo(), "*".to_string()),
915            ]);
916            // We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
917            // assignment from `ident = val;` to `*ident = val;`.
918            err.multipart_suggestion(
919                "you might have meant to mutate the pointed at value being passed in, instead of \
920                changing the reference in the local binding",
921                sugg,
922                Applicability::MaybeIncorrect,
923            );
924            return true;
925        }
926        false
927    }
928
929    fn annotate_alternative_method_deref_for_unop(
930        &self,
931        err: &mut Diag<'_>,
932        expr: &hir::Expr<'_>,
933        error: Option<TypeError<'tcx>>,
934    ) {
935        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
936            return;
937        };
938        let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
939            self.tcx.parent_hir_node(expr.hir_id)
940        else {
941            return;
942        };
943        if rhs.hir_id != expr.hir_id || expected.is_closure() {
944            return;
945        }
946        let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else {
947            return;
948        };
949        self.annotate_alternative_method_deref(err, deref, Some(expected))
950    }
951
952    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("annotate_alternative_method_deref",
                                    "rustc_hir_typeck::demand", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/28221559263a3976766cf305940e80e30cf9ba8a/compiler/rustc_hir_typeck/src/demand.rs"),
                                    ::tracing_core::__macro_support::Option::Some(952u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::demand"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expr")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expr");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let hir::ExprKind::MethodCall(path, base, args, _) =
                expr.kind else { return; };
            let Some(self_ty) =
                self.typeck_results.borrow().expr_ty_adjusted_opt(base) else {
                    return;
                };
            let Ok(pick) =
                self.lookup_probe_for_diagnostic(path.ident, self_ty, expr,
                    probe::ProbeScope::TraitsInScope, None) else { return; };
            let Ok(in_scope_methods) =
                self.probe_for_name_many(probe::Mode::MethodCall, path.ident,
                    expected, probe::IsSuggestion(true), self_ty, expr.hir_id,
                    probe::ProbeScope::TraitsInScope) else { return; };
            let other_methods_in_scope: Vec<_> =
                in_scope_methods.iter().filter(|c|
                            c.item.def_id != pick.item.def_id).collect();
            let Ok(all_methods) =
                self.probe_for_name_many(probe::Mode::MethodCall, path.ident,
                    expected, probe::IsSuggestion(true), self_ty, expr.hir_id,
                    probe::ProbeScope::AllTraits) else { return; };
            let suggestions: Vec<_> =
                all_methods.into_iter().filter_map(|c|
                            {
                                if c.item.def_id == pick.item.def_id { return None; }
                                let m = c.item;
                                let generic_args =
                                    ty::GenericArgs::for_item(self.tcx, m.def_id,
                                        |param, _| { self.var_for_def(expr.span, param) });
                                let fn_sig = self.tcx.fn_sig(m.def_id);
                                if fn_sig.skip_binder().inputs().skip_binder().len() !=
                                        args.len() + 1 {
                                    return None;
                                }
                                let rcvr_ty = fn_sig.skip_binder().input(0).skip_binder();
                                let (mutability, ty) =
                                    match rcvr_ty.kind() {
                                        ty::Ref(_, ty, hir::Mutability::Mut) => ("&mut ", ty),
                                        ty::Ref(_, ty, _) => ("&", ty),
                                        _ => ("", &rcvr_ty),
                                    };
                                let path =
                                    match self.tcx.assoc_parent(m.def_id) {
                                        Some((_, DefKind::Impl { of_trait: true })) => {
                                            self.tcx.def_path_str_with_args(m.def_id,
                                                    generic_args).to_string()
                                        }
                                        Some((_, DefKind::Impl { of_trait: false })) => {
                                            if let ty::Adt(def, _) = ty.kind() {
                                                ::alloc::__export::must_use({
                                                        ::alloc::fmt::format(format_args!("{0}::{1}",
                                                                self.tcx.def_path_str(def.did()), path.ident))
                                                    })
                                            } else {
                                                ::alloc::__export::must_use({
                                                        ::alloc::fmt::format(format_args!("{1}::{0}", path.ident,
                                                                ty))
                                                    })
                                            }
                                        }
                                        _ =>
                                            {
                                                    let _guard = NoTrimmedGuard::new();
                                                    self.tcx.def_path_str_with_args(m.def_id, generic_args)
                                                }.to_string(),
                                    };
                                Some(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                            [(expr.span.until(base.span),
                                                        ::alloc::__export::must_use({
                                                                ::alloc::fmt::format(format_args!("{1}({0}", mutability,
                                                                        path))
                                                            })),
                                                    match &args {
                                                        [] =>
                                                            (base.span.shrink_to_hi().with_hi(expr.span.hi()),
                                                                ")".to_string()),
                                                        [first, ..] =>
                                                            (base.span.between(first.span), ", ".to_string()),
                                                    }])))
                            }).collect();
            if suggestions.is_empty() { return; }
            let mut path_span: MultiSpan = path.ident.span.into();
            path_span.push_span_label(path.ident.span,
                {
                    let _guard = NoTrimmedGuard::new();
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("refers to `{0}`",
                                    self.tcx.def_path_str(pick.item.def_id)))
                        })
                });
            let container_id = pick.item.container_id(self.tcx);
            let container =
                {
                    let _guard = NoTrimmedGuard::new();
                    self.tcx.def_path_str(container_id)
                };
            for &def_id in pick.import_ids {
                let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
                path_span.push_span_label(self.tcx.hir_span(hir_id),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("`{0}` imported here",
                                    container))
                        }));
            }
            let tail =
                {
                    let _guard = NoTrimmedGuard::new();
                    match &other_methods_in_scope[..] {
                        [] => return,
                        [candidate] =>
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("the method of the same name on {0} `{1}`",
                                            match candidate.kind {
                                                probe::CandidateKind::InherentImplCandidate { .. } =>
                                                    "the inherent impl for",
                                                _ => "trait",
                                            },
                                            self.tcx.def_path_str(candidate.item.container_id(self.tcx))))
                                }),
                        _ if other_methods_in_scope.len() < 5 => {
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("the methods of the same name on {0}",
                                            listify(&other_methods_in_scope[..other_methods_in_scope.len()
                                                                    - 1],
                                                    |c|
                                                        ::alloc::__export::must_use({
                                                                ::alloc::fmt::format(format_args!("`{0}`",
                                                                        self.tcx.def_path_str(c.item.container_id(self.tcx))))
                                                            })).unwrap_or_default()))
                                })
                        }
                        _ =>
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("the methods of the same name on {0} other traits",
                                            other_methods_in_scope.len()))
                                }),
                    }
                };
            err.span_note(path_span,
                ::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("the `{0}` call is resolved to the method in `{1}`, shadowing {2}",
                                path.ident, container, tail))
                    }));
            if suggestions.len() > other_methods_in_scope.len() {
                let n = suggestions.len() - other_methods_in_scope.len();
                err.note(::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("additionally, there {0} {2} other available method{1} that {0}n\'t in scope",
                                    if n == 1 { "is" } else { "are" },
                                    if n == 1 { "" } else { "s" }, n))
                        }));
            }
            err.multipart_suggestions(::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("you might have meant to call {0}; you can use the fully-qualified path to call {1} explicitly",
                                if suggestions.len() == 1 {
                                    "the other method"
                                } else { "one of the other methods" },
                                if suggestions.len() == 1 { "it" } else { "one of them" }))
                    }), suggestions, Applicability::MaybeIncorrect);
        }
    }
}#[tracing::instrument(skip(self, err), level = "debug")]
953    pub(crate) fn annotate_alternative_method_deref(
954        &self,
955        err: &mut Diag<'_>,
956        expr: &hir::Expr<'_>,
957        expected: Option<Ty<'tcx>>,
958    ) {
959        let hir::ExprKind::MethodCall(path, base, args, _) = expr.kind else {
960            return;
961        };
962        let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else {
963            return;
964        };
965
966        let Ok(pick) = self.lookup_probe_for_diagnostic(
967            path.ident,
968            self_ty,
969            expr,
970            probe::ProbeScope::TraitsInScope,
971            None,
972        ) else {
973            return;
974        };
975
976        let Ok(in_scope_methods) = self.probe_for_name_many(
977            probe::Mode::MethodCall,
978            path.ident,
979            expected,
980            probe::IsSuggestion(true),
981            self_ty,
982            expr.hir_id,
983            probe::ProbeScope::TraitsInScope,
984        ) else {
985            return;
986        };
987
988        let other_methods_in_scope: Vec<_> =
989            in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
990
991        let Ok(all_methods) = self.probe_for_name_many(
992            probe::Mode::MethodCall,
993            path.ident,
994            expected,
995            probe::IsSuggestion(true),
996            self_ty,
997            expr.hir_id,
998            probe::ProbeScope::AllTraits,
999        ) else {
1000            return;
1001        };
1002
1003        let suggestions: Vec<_> = all_methods
1004            .into_iter()
1005            .filter_map(|c| {
1006                if c.item.def_id == pick.item.def_id {
1007                    return None;
1008                }
1009                let m = c.item;
1010                let generic_args = ty::GenericArgs::for_item(self.tcx, m.def_id, |param, _| {
1011                    self.var_for_def(expr.span, param)
1012                });
1013                let fn_sig = self.tcx.fn_sig(m.def_id);
1014                if fn_sig.skip_binder().inputs().skip_binder().len() != args.len() + 1 {
1015                    return None;
1016                }
1017                let rcvr_ty = fn_sig.skip_binder().input(0).skip_binder();
1018                let (mutability, ty) = match rcvr_ty.kind() {
1019                    ty::Ref(_, ty, hir::Mutability::Mut) => ("&mut ", ty),
1020                    ty::Ref(_, ty, _) => ("&", ty),
1021                    _ => ("", &rcvr_ty),
1022                };
1023                let path = match self.tcx.assoc_parent(m.def_id) {
1024                    Some((_, DefKind::Impl { of_trait: true })) => {
1025                        // We have `impl Trait for T {}`, suggest `<T as Trait>::method`.
1026                        self.tcx.def_path_str_with_args(m.def_id, generic_args).to_string()
1027                    }
1028                    Some((_, DefKind::Impl { of_trait: false })) => {
1029                        if let ty::Adt(def, _) = ty.kind() {
1030                            // We have `impl T {}`, suggest `T::method`.
1031                            format!("{}::{}", self.tcx.def_path_str(def.did()), path.ident)
1032                        } else {
1033                            // This should be unreachable, as `impl &'a T {}` is invalid.
1034                            format!("{ty}::{}", path.ident)
1035                        }
1036                    }
1037                    // Fallback for arbitrary self types.
1038                    _ => with_no_trimmed_paths!(
1039                        self.tcx.def_path_str_with_args(m.def_id, generic_args)
1040                    )
1041                    .to_string(),
1042                };
1043                Some(vec![
1044                    (expr.span.until(base.span), format!("{path}({}", mutability)),
1045                    match &args {
1046                        [] => (base.span.shrink_to_hi().with_hi(expr.span.hi()), ")".to_string()),
1047                        [first, ..] => (base.span.between(first.span), ", ".to_string()),
1048                    },
1049                ])
1050            })
1051            .collect();
1052        if suggestions.is_empty() {
1053            return;
1054        }
1055        let mut path_span: MultiSpan = path.ident.span.into();
1056        path_span.push_span_label(
1057            path.ident.span,
1058            with_no_trimmed_paths!(format!(
1059                "refers to `{}`",
1060                self.tcx.def_path_str(pick.item.def_id),
1061            )),
1062        );
1063        let container_id = pick.item.container_id(self.tcx);
1064        let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
1065        for &def_id in pick.import_ids {
1066            let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
1067            path_span
1068                .push_span_label(self.tcx.hir_span(hir_id), format!("`{container}` imported here"));
1069        }
1070        let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
1071            [] => return,
1072            [candidate] => format!(
1073                "the method of the same name on {} `{}`",
1074                match candidate.kind {
1075                    probe::CandidateKind::InherentImplCandidate { .. } => "the inherent impl for",
1076                    _ => "trait",
1077                },
1078                self.tcx.def_path_str(candidate.item.container_id(self.tcx))
1079            ),
1080            _ if other_methods_in_scope.len() < 5 => {
1081                format!(
1082                    "the methods of the same name on {}",
1083                    listify(
1084                        &other_methods_in_scope[..other_methods_in_scope.len() - 1],
1085                        |c| format!("`{}`", self.tcx.def_path_str(c.item.container_id(self.tcx)))
1086                    )
1087                    .unwrap_or_default(),
1088                )
1089            }
1090            _ => format!(
1091                "the methods of the same name on {} other traits",
1092                other_methods_in_scope.len()
1093            ),
1094        });
1095        err.span_note(
1096            path_span,
1097            format!(
1098                "the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
1099                path.ident,
1100            ),
1101        );
1102        if suggestions.len() > other_methods_in_scope.len() {
1103            let n = suggestions.len() - other_methods_in_scope.len();
1104            err.note(format!(
1105                "additionally, there {are} {n} other available method{s} that {are}n't in scope",
1106                are = pluralize!("is", n),
1107                s = pluralize!(n),
1108            ));
1109        }
1110        err.multipart_suggestions(
1111            format!(
1112                "you might have meant to call {}; you can use the fully-qualified path to call {} \
1113                 explicitly",
1114                if suggestions.len() == 1 {
1115                    "the other method"
1116                } else {
1117                    "one of the other methods"
1118                },
1119                if suggestions.len() == 1 { "it" } else { "one of them" },
1120            ),
1121            suggestions,
1122            Applicability::MaybeIncorrect,
1123        );
1124    }
1125
1126    pub(crate) fn get_conversion_methods_for_diagnostic(
1127        &self,
1128        span: Span,
1129        expected: Ty<'tcx>,
1130        checked_ty: Ty<'tcx>,
1131        hir_id: hir::HirId,
1132    ) -> Vec<AssocItem> {
1133        let methods = self.probe_for_return_type_for_diagnostic(
1134            span,
1135            probe::Mode::MethodCall,
1136            expected,
1137            checked_ty,
1138            hir_id,
1139            |m| {
1140                self.has_only_self_parameter(m)
1141                // This special internal attribute is used to permit
1142                // "identity-like" conversion methods to be suggested here.
1143                //
1144                // FIXME (#46459 and #46460): ideally
1145                // `std::convert::Into::into` and `std::borrow:ToOwned` would
1146                // also be `#[rustc_conversion_suggestion]`, if not for
1147                // method-probing false-positives and -negatives (respectively).
1148                //
1149                // FIXME? Other potential candidate methods: `as_ref` and
1150                // `as_mut`?
1151                && {
        {
            'done:
                {
                for i in
                    ::rustc_attr_ir::HasAttrs::get_attrs(m.def_id, &self.tcx) {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcConversionSuggestion)
                            => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(self.tcx, m.def_id, RustcConversionSuggestion)
1152            },
1153        );
1154
1155        methods
1156    }
1157
1158    /// This function checks whether the method is not static and does not accept other parameters than `self`.
1159    fn has_only_self_parameter(&self, method: &AssocItem) -> bool {
1160        method.is_method()
1161            && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() == 1
1162    }
1163
1164    /// If the given `HirId` corresponds to a block with a trailing expression, return that expression
1165    pub(crate) fn maybe_get_block_expr(
1166        &self,
1167        expr: &hir::Expr<'tcx>,
1168    ) -> Option<&'tcx hir::Expr<'tcx>> {
1169        match expr {
1170            hir::Expr { kind: hir::ExprKind::Block(block, ..), .. } => block.expr,
1171            _ => None,
1172        }
1173    }
1174
1175    /// Returns whether the given expression is a destruct assignment desugaring.
1176    /// For example, `(a, b) = (1, &2);`
1177    /// Here we try to find the pattern binding of the expression,
1178    /// `default_binding_modes` is false only for destruct assignment desugaring.
1179    pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool {
1180        if let hir::ExprKind::Path(hir::QPath::Resolved(
1181            _,
1182            hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
1183        )) = expr.kind
1184            && let bind = self.tcx.hir_node(*bind_hir_id)
1185            && let parent = self.tcx.parent_hir_node(*bind_hir_id)
1186            && let hir::Node::Pat(hir::Pat {
1187                kind: hir::PatKind::Binding(_, _hir_id, _, _), ..
1188            }) = bind
1189            && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent
1190        {
1191            true
1192        } else {
1193            false
1194        }
1195    }
1196
1197    fn explain_self_literal(
1198        &self,
1199        err: &mut Diag<'_>,
1200        expr: &hir::Expr<'tcx>,
1201        expected: Ty<'tcx>,
1202        found: Ty<'tcx>,
1203    ) {
1204        match expr.peel_drop_temps().kind {
1205            hir::ExprKind::Struct(
1206                hir::QPath::Resolved(
1207                    None,
1208                    hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. },
1209                ),
1210                ..,
1211            )
1212            | hir::ExprKind::Call(
1213                hir::Expr {
1214                    kind:
1215                        hir::ExprKind::Path(hir::QPath::Resolved(
1216                            None,
1217                            hir::Path {
1218                                res: hir::def::Res::SelfTyAlias { alias_to, .. },
1219                                span,
1220                                ..
1221                            },
1222                        )),
1223                    ..
1224                },
1225                ..,
1226            ) => {
1227                if let Some(hir::Node::Item(hir::Item {
1228                    kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
1229                    ..
1230                })) = self.tcx.hir_get_if_local(*alias_to)
1231                {
1232                    err.span_label(self_ty.span, "this is the type of the `Self` literal");
1233                }
1234                if let ty::Adt(e_def, e_args) = expected.kind()
1235                    && let ty::Adt(f_def, _f_args) = found.kind()
1236                    && e_def == f_def
1237                {
1238                    err.span_suggestion_verbose(
1239                        *span,
1240                        "use the type name directly",
1241                        self.tcx.value_path_str_with_args(e_def.did(), e_args),
1242                        Applicability::MaybeIncorrect,
1243                    );
1244                }
1245            }
1246            _ => {}
1247        }
1248    }
1249
1250    fn note_wrong_return_ty_due_to_generic_arg(
1251        &self,
1252        err: &mut Diag<'_>,
1253        expr: &hir::Expr<'_>,
1254        checked_ty: Ty<'tcx>,
1255    ) {
1256        let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr.hir_id) else {
1257            return;
1258        };
1259        if parent_expr.span.desugaring_kind().is_some() {
1260            return;
1261        }
1262        enum CallableKind {
1263            Function,
1264            Method,
1265            Constructor,
1266        }
1267        let mut maybe_emit_help = |def_id: hir::def_id::DefId,
1268                                   callable: Ident,
1269                                   args: &[hir::Expr<'_>],
1270                                   kind: CallableKind| {
1271            let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
1272            let fn_ty = self.tcx.type_of(def_id).skip_binder();
1273            if !fn_ty.is_fn() {
1274                return;
1275            }
1276            let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
1277            let Some(&arg) = fn_sig
1278                .inputs()
1279                .get(arg_idx + if #[allow(non_exhaustive_omitted_patterns)] match kind {
    CallableKind::Method => true,
    _ => false,
}matches!(kind, CallableKind::Method) { 1 } else { 0 })
1280            else {
1281                return;
1282            };
1283            if #[allow(non_exhaustive_omitted_patterns)] match arg.kind() {
    ty::Param(_) => true,
    _ => false,
}matches!(arg.kind(), ty::Param(_))
1284                && fn_sig.output().contains(arg)
1285                && self.node_ty(args[arg_idx].hir_id) == checked_ty
1286            {
1287                let mut multi_span: MultiSpan = parent_expr.span.into();
1288                multi_span.push_span_label(
1289                    args[arg_idx].span,
1290                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this argument influences the {0} of `{1}`",
                if #[allow(non_exhaustive_omitted_patterns)] match kind {
                        CallableKind::Constructor => true,
                        _ => false,
                    } {
                    "type"
                } else { "return type" }, callable))
    })format!(
1291                        "this argument influences the {} of `{}`",
1292                        if matches!(kind, CallableKind::Constructor) {
1293                            "type"
1294                        } else {
1295                            "return type"
1296                        },
1297                        callable
1298                    ),
1299                );
1300                err.span_help(
1301                    multi_span,
1302                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the {0} `{1}` due to the type of the argument passed",
                match kind {
                    CallableKind::Function => "return type of this call is",
                    CallableKind::Method => "return type of this call is",
                    CallableKind::Constructor => "type constructed contains",
                }, checked_ty))
    })format!(
1303                        "the {} `{}` due to the type of the argument passed",
1304                        match kind {
1305                            CallableKind::Function => "return type of this call is",
1306                            CallableKind::Method => "return type of this call is",
1307                            CallableKind::Constructor => "type constructed contains",
1308                        },
1309                        checked_ty
1310                    ),
1311                );
1312            }
1313        };
1314        match parent_expr.kind {
1315            hir::ExprKind::Call(fun, args) => {
1316                let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else {
1317                    return;
1318                };
1319                let hir::def::Res::Def(kind, def_id) = path.res else {
1320                    return;
1321                };
1322                let callable_kind = if #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Ctor(_, _) => true,
    _ => false,
}matches!(kind, DefKind::Ctor(_, _)) {
1323                    CallableKind::Constructor
1324                } else {
1325                    CallableKind::Function
1326                };
1327                maybe_emit_help(def_id, path.segments.last().unwrap().ident, args, callable_kind);
1328            }
1329            hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
1330                let Some(def_id) =
1331                    self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
1332                else {
1333                    return;
1334                };
1335                maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
1336            }
1337            _ => return,
1338        }
1339    }
1340}
1341
1342pub(crate) enum TypeMismatchSource<'tcx> {
1343    /// Expected the binding to have the given type, but it was found to have
1344    /// a different type. Find out when that type first became incompatible.
1345    Ty(Ty<'tcx>),
1346    /// When we fail during method argument checking, try to find out if a previous
1347    /// expression has constrained the method's receiver in a way that makes the
1348    /// argument's type incompatible.
1349    Arg { call_expr: &'tcx hir::Expr<'tcx>, incompatible_arg: usize },
1350}