Skip to main content

rustc_hir_typeck/
demand.rs

1use rustc_errors::{Applicability, Diag, MultiSpan, listify};
2use rustc_hir::def::Res;
3use rustc_hir::intravisit::Visitor;
4use rustc_hir::{self as hir, find_attr};
5use rustc_infer::infer::DefineOpaqueTypes;
6use rustc_middle::ty::adjustment::AllowTwoPhase;
7use rustc_middle::ty::error::{ExpectedFound, TypeError};
8use rustc_middle::ty::print::with_no_trimmed_paths;
9use rustc_middle::ty::{self, AssocItem, BottomUpFolder, Ty, TypeFoldable, TypeVisitableExt};
10use rustc_span::{DUMMY_SP, Ident, Span, bug, span_bug, sym};
11use rustc_trait_selection::infer::InferCtxtExt;
12use rustc_trait_selection::traits::ObligationCause;
13use tracing::instrument;
14
15use super::method::probe;
16use crate::FnCtxt;
17
18impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19    pub(crate) fn emit_type_mismatch_suggestions(
20        &self,
21        err: &mut Diag<'_>,
22        expr: &hir::Expr<'tcx>,
23        expr_ty: Ty<'tcx>,
24        expected: Ty<'tcx>,
25        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
26        error: Option<TypeError<'tcx>>,
27    ) {
28        if expr_ty == expected {
29            return;
30        }
31        self.annotate_alternative_method_deref(err, expr, error);
32        self.explain_self_literal(err, expr, expected, expr_ty);
33
34        // Use `||` to give these suggestions a precedence
35        let suggested = self.suggest_missing_parentheses(err, expr)
36            || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
37            || self.suggest_remove_last_method_call(err, expr, expected)
38            || self.suggest_associated_const(err, expr, expected)
39            || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
40            || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
41            || self.suggest_option_to_bool(err, expr, expr_ty, expected)
42            || self.suggest_collect(err, expr, expected, expr_ty)
43            || self.suggest_compatible_variants(err, expr, expected, expr_ty)
44            || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
45            || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
46            || self.suggest_closure_to_fn_ptr_coercion(err, expr, expected, expr_ty)
47            || self.suggest_boxing_when_appropriate(
48                err,
49                expr.peel_blocks().span,
50                expr.hir_id,
51                expected,
52                expr_ty,
53            )
54            || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
55            || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected)
56            || self.suggest_clone_for_ref(err, expr, expr_ty, expected)
57            || self.suggest_into(err, expr, expr_ty, expected)
58            || self.suggest_floating_point_literal(err, expr, expected)
59            || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
60            || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
61            || self.suggest_returning_value_after_loop(err, expr, expected);
62
63        if !suggested {
64            self.note_source_of_type_mismatch_constraint(
65                err,
66                expr,
67                TypeMismatchSource::Ty(expected),
68            );
69        }
70    }
71
72    pub(crate) fn emit_coerce_suggestions(
73        &self,
74        err: &mut Diag<'_>,
75        expr: &hir::Expr<'tcx>,
76        expr_ty: Ty<'tcx>,
77        expected: Ty<'tcx>,
78        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
79        error: Option<TypeError<'tcx>>,
80    ) {
81        if expr_ty == expected {
82            return;
83        }
84
85        self.annotate_expected_due_to_let_ty(err, expr, error);
86        self.annotate_loop_expected_due_to_inference(err, expr, error);
87        if self.annotate_mut_binding_to_immutable_binding(err, expr, expr_ty, expected, error) {
88            return;
89        }
90
91        // FIXME(#73154): For now, we do leak check when coercing function
92        // pointers in typeck, instead of only during borrowck. This can lead
93        // to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
94        if #[allow(non_exhaustive_omitted_patterns)] match error {
    Some(TypeError::RegionsInsufficientlyPolymorphic(..)) => true,
    _ => false,
}matches!(error, Some(TypeError::RegionsInsufficientlyPolymorphic(..))) {
95            return;
96        }
97
98        if self.is_destruct_assignment_desugaring(expr) {
99            return;
100        }
101        self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
102        self.note_type_is_not_clone(err, expected, expr_ty, expr);
103        self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty);
104        self.suggest_method_call_on_range_literal(err, expr, expr_ty, expected);
105        self.suggest_return_binding_for_missing_tail_expr(err, expr, expr_ty, expected);
106        self.note_wrong_return_ty_due_to_generic_arg(err, expr, expr_ty);
107    }
108
109    /// Really hacky heuristic to remap an `assert_eq!` error to the user
110    /// expressions provided to the macro.
111    fn adjust_expr_for_assert_eq_macro(
112        &self,
113        found_expr: &mut &'tcx hir::Expr<'tcx>,
114        expected_expr: &mut Option<&'tcx hir::Expr<'tcx>>,
115    ) {
116        let Some(expected_expr) = expected_expr else {
117            return;
118        };
119
120        if !found_expr.span.eq_ctxt(expected_expr.span) {
121            return;
122        }
123
124        if !found_expr
125            .span
126            .ctxt()
127            .outer_expn_data()
128            .macro_def_id
129            .is_some_and(|def_id| self.tcx.is_diagnostic_item(sym::assert_eq_macro, def_id))
130        {
131            return;
132        }
133
134        let hir::ExprKind::Unary(
135            hir::UnOp::Deref,
136            hir::Expr { kind: hir::ExprKind::Path(found_path), .. },
137        ) = found_expr.kind
138        else {
139            return;
140        };
141        let hir::ExprKind::Unary(
142            hir::UnOp::Deref,
143            hir::Expr { kind: hir::ExprKind::Path(expected_path), .. },
144        ) = expected_expr.kind
145        else {
146            return;
147        };
148
149        for (path, name, idx, var) in [
150            (expected_path, "left_val", 0, expected_expr),
151            (found_path, "right_val", 1, found_expr),
152        ] {
153            if let hir::QPath::Resolved(_, path) = path
154                && let [segment] = path.segments
155                && segment.ident.name.as_str() == name
156                && let Res::Local(hir_id) = path.res
157                && let Some((_, hir::Node::Expr(match_expr))) =
158                    self.tcx.hir_parent_iter(hir_id).nth(2)
159                && let hir::ExprKind::Match(scrutinee, _, _) = match_expr.kind
160                && let hir::ExprKind::Tup(exprs) = scrutinee.kind
161                && let hir::ExprKind::AddrOf(_, _, macro_arg) = exprs[idx].kind
162            {
163                *var = macro_arg;
164            }
165        }
166    }
167
168    /// Requires that the two types unify, and prints an error message if
169    /// they don't.
170    pub(crate) fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
171        if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
172            e.emit();
173        }
174    }
175
176    pub(crate) fn demand_suptype_diag(
177        &'a self,
178        sp: Span,
179        expected: Ty<'tcx>,
180        actual: Ty<'tcx>,
181    ) -> Result<(), Diag<'a>> {
182        self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
183    }
184
185    {}
#[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/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_typeck/src/demand.rs"),
                                    ::tracing_core::__macro_support::Option::Some(185u32),
                                    ::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")]
186    pub(crate) fn demand_suptype_with_origin(
187        &'a self,
188        cause: &ObligationCause<'tcx>,
189        expected: Ty<'tcx>,
190        actual: Ty<'tcx>,
191    ) -> Result<(), Diag<'a>> {
192        self.at(cause, self.param_env)
193            .sup(DefineOpaqueTypes::Yes, expected, actual)
194            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
195            .map_err(|e| {
196                self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e)
197            })
198    }
199
200    pub(crate) fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
201        if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
202            err.emit();
203        }
204    }
205
206    pub(crate) fn demand_eqtype_diag(
207        &'a self,
208        sp: Span,
209        expected: Ty<'tcx>,
210        actual: Ty<'tcx>,
211    ) -> Result<(), Diag<'a>> {
212        self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
213    }
214
215    pub(crate) fn demand_eqtype_with_origin(
216        &'a self,
217        cause: &ObligationCause<'tcx>,
218        expected: Ty<'tcx>,
219        actual: Ty<'tcx>,
220    ) -> Result<(), Diag<'a>> {
221        self.at(cause, self.param_env)
222            .eq(DefineOpaqueTypes::Yes, expected, actual)
223            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
224            .map_err(|e| {
225                self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e)
226            })
227    }
228
229    pub(crate) fn demand_coerce(
230        &self,
231        expr: &'tcx hir::Expr<'tcx>,
232        checked_ty: Ty<'tcx>,
233        expected: Ty<'tcx>,
234        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
235        allow_two_phase: AllowTwoPhase,
236    ) -> Ty<'tcx> {
237        match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
238        {
239            Ok(ty) => ty,
240            Err(err) => {
241                err.emit();
242                // Return the original type instead of an error type here, otherwise the type of `x` in
243                // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
244                // report errors, even though `x` is definitely `u32`.
245                expected
246            }
247        }
248    }
249
250    /// Checks that the type of `expr` can be coerced to `expected`.
251    ///
252    /// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!`
253    /// will be permitted if the diverges flag is currently "always".
254    {}
#[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/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_hir_typeck/src/demand.rs"),
                                    ::tracing_core::__macro_support::Option::Some(254u32),
                                    ::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))]
255    pub(crate) fn demand_coerce_diag(
256        &'a self,
257        mut expr: &'tcx hir::Expr<'tcx>,
258        checked_ty: Ty<'tcx>,
259        expected: Ty<'tcx>,
260        mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
261        allow_two_phase: AllowTwoPhase,
262    ) -> Result<Ty<'tcx>, Diag<'a>> {
263        let expected = self.deeply_resolve_ignoring_regions_with_obligations(expected);
264
265        let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
266            Ok(ty) => return Ok(ty),
267            Err(e) => e,
268        };
269
270        self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr);
271
272        self.set_tainted_by_errors(self.dcx().span_delayed_bug(
273            expr.span,
274            "`TypeError` when attempting coercion but no error emitted",
275        ));
276        let expr = expr.peel_drop_temps();
277        let cause = self.misc(expr.span);
278        let expr_ty = self.deeply_resolve_ignoring_regions(checked_ty);
279        let mut err =
280            self.err_ctxt().report_mismatched_types(&cause, self.param_env, expected, expr_ty, e);
281
282        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
283
284        Err(err)
285    }
286
287    /// Notes the point at which a variable is constrained to some type incompatible
288    /// with some expectation given by `source`.
289    pub(crate) fn note_source_of_type_mismatch_constraint(
290        &self,
291        err: &mut Diag<'_>,
292        expr: &hir::Expr<'_>,
293        source: TypeMismatchSource<'tcx>,
294    ) -> bool {
295        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else {
296            return false;
297        };
298        let [hir::PathSegment { ident, args: None, .. }] = p.segments else {
299            return false;
300        };
301        let hir::def::Res::Local(local_hir_id) = p.res else {
302            return false;
303        };
304        let hir::Node::Pat(pat) = self.tcx.hir_node(local_hir_id) else {
305            return false;
306        };
307        let (init_ty_hir_id, init) = match self.tcx.parent_hir_node(pat.hir_id) {
308            hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init, .. }) => (ty.hir_id, *init),
309            hir::Node::LetStmt(hir::LetStmt { init: Some(init), .. }) => (init.hir_id, Some(*init)),
310            _ => return false,
311        };
312        let Some(init_ty) = self.node_ty_opt(init_ty_hir_id) else {
313            return false;
314        };
315
316        // Locate all the usages of the relevant binding.
317        struct FindExprs<'tcx> {
318            hir_id: hir::HirId,
319            uses: Vec<&'tcx hir::Expr<'tcx>>,
320        }
321        impl<'tcx> Visitor<'tcx> for FindExprs<'tcx> {
322            fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
323                if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
324                    && let hir::def::Res::Local(hir_id) = path.res
325                    && hir_id == self.hir_id
326                {
327                    self.uses.push(ex);
328                }
329                hir::intravisit::walk_expr(self, ex);
330            }
331        }
332
333        let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() };
334        let body = self.tcx.hir_body_owned_by(self.body_def_id);
335        expr_finder.visit_expr(body.value);
336
337        // Replaces all of the variables in the given type with a fresh inference variable.
338        let mut fudger = BottomUpFolder {
339            tcx: self.tcx,
340            ty_op: |ty| {
341                if let ty::Infer(infer) = ty.kind() {
342                    match infer {
343                        ty::TyVar(_) => self.next_ty_var(DUMMY_SP),
344                        ty::IntVar(_) => self.next_int_var(),
345                        ty::FloatVar(_) => self.next_float_var(DUMMY_SP, None),
346                        ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
347                            bug_impl(None,
    format_args!("unexpected fresh ty outside of the trait solver"),
    Location::caller())bug!("unexpected fresh ty outside of the trait solver")
348                        }
349                    }
350                } else {
351                    ty
352                }
353            },
354            lt_op: |_| self.tcx.lifetimes.re_erased,
355            ct_op: |ct| {
356                if let ty::ConstKind::Infer(_) = ct.kind() {
357                    self.next_const_var(DUMMY_SP)
358                } else {
359                    ct
360                }
361            },
362        };
363
364        let expected_ty = match source {
365            TypeMismatchSource::Ty(expected_ty) => expected_ty,
366            // Try to deduce what the possible value of `expr` would be if the
367            // incompatible arg were compatible. For example, given `Vec<i32>`
368            // and `vec.push(1u32)`, we ideally want to deduce that the type of
369            // `vec` *should* have been `Vec<u32>`. This will allow us to then
370            // run the subsequent code with this expectation, finding out exactly
371            // when this type diverged from our expectation.
372            TypeMismatchSource::Arg { call_expr, incompatible_arg: idx } => {
373                let hir::ExprKind::MethodCall(segment, _, args, _) = call_expr.kind else {
374                    return false;
375                };
376                let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
377                    return false;
378                };
379                let possible_rcvr_ty = expr_finder.uses.iter().rev().find_map(|binding| {
380                    let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?;
381                    if possible_rcvr_ty.is_ty_var() {
382                        return None;
383                    }
384                    // Fudge the receiver, so we can do new inference on it.
385                    let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
386                    let method = self
387                        .lookup_method_for_diagnostic(
388                            possible_rcvr_ty,
389                            segment,
390                            DUMMY_SP,
391                            call_expr,
392                            binding,
393                        )
394                        .ok()?;
395                    // Make sure we select the same method that we started with...
396                    if Some(method.def_id)
397                        != self.typeck_results.borrow().type_dependent_def_id(call_expr.hir_id)
398                    {
399                        return None;
400                    }
401                    // Unify the method signature with our incompatible arg, to
402                    // do inference in the *opposite* direction and to find out
403                    // what our ideal rcvr ty would look like.
404                    let Some(input_arg) = method.sig.inputs().get(idx + 1) else {
405                        if method.sig.splatted().is_some() {
406                            // FIXME(splat): when the arg is splatted, adjust its index, to handle the type mismatch properly
407                            return None;
408                        } else {
409                            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!(
410                                self.tcx.def_span(method.def_id),
411                                "arg index {} out of bounds for method with {} inputs",
412                                idx + 1,
413                                method.sig.inputs().len(),
414                            );
415                        }
416                    };
417                    let _ = self
418                        .at(&ObligationCause::dummy(), self.param_env)
419                        .eq(DefineOpaqueTypes::Yes, *input_arg, arg_ty)
420                        .ok()?;
421                    self.select_obligations_where_possible(|errs| {
422                        // Yeet the errors, we're already reporting errors.
423                        errs.clear();
424                    });
425                    Some(self.deeply_resolve_ignoring_regions(possible_rcvr_ty))
426                });
427                let Some(rcvr_ty) = possible_rcvr_ty else { return false };
428                rcvr_ty
429            }
430        };
431
432        // If our expected_ty does not equal init_ty, then it *began* as incompatible.
433        // No need to note in this case...
434        if !self.can_eq(self.param_env, expected_ty, init_ty.fold_with(&mut fudger)) {
435            return false;
436        }
437
438        for window in expr_finder.uses.windows(2) {
439            // Bindings always update their recorded type after the fact, so we
440            // need to look at the *following* usage's type to see when the
441            // binding became incompatible.
442            let [binding, next_usage] = *window else {
443                continue;
444            };
445
446            // Don't go past the binding (always gonna be a nonsense label if so)
447            if binding.hir_id == expr.hir_id {
448                break;
449            }
450
451            let Some(next_use_ty) = self.node_ty_opt(next_usage.hir_id) else {
452                continue;
453            };
454
455            // If the type is not constrained in a way making it not possible to
456            // equate with `expected_ty` by this point, skip.
457            if self.can_eq(self.param_env, expected_ty, next_use_ty.fold_with(&mut fudger)) {
458                continue;
459            }
460
461            if let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(binding.hir_id)
462                && let hir::ExprKind::MethodCall(segment, rcvr, args, _) = parent_expr.kind
463                && rcvr.hir_id == binding.hir_id
464            {
465                // If our binding became incompatible while it was a receiver
466                // to a method call, we may be able to make a better guess to
467                // the source of a type mismatch.
468                let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else {
469                    continue;
470                };
471                let rcvr_ty = rcvr_ty.fold_with(&mut fudger);
472                let Ok(method) = self.lookup_method_for_diagnostic(
473                    rcvr_ty,
474                    segment,
475                    DUMMY_SP,
476                    parent_expr,
477                    rcvr,
478                ) else {
479                    continue;
480                };
481                // Make sure we select the same method that we started with...
482                if Some(method.def_id)
483                    != self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
484                {
485                    continue;
486                }
487
488                let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
489                let ideal_method = self
490                    .lookup_method_for_diagnostic(
491                        ideal_rcvr_ty,
492                        segment,
493                        DUMMY_SP,
494                        parent_expr,
495                        rcvr,
496                    )
497                    .ok()
498                    .and_then(|method| {
499                        let _ = self
500                            .at(&ObligationCause::dummy(), self.param_env)
501                            .eq(DefineOpaqueTypes::Yes, ideal_rcvr_ty, expected_ty)
502                            .ok()?;
503                        Some(method)
504                    });
505
506                // Find what argument caused our rcvr to become incompatible
507                // with the expected ty.
508                for (idx, (expected_arg_ty, arg_expr)) in
509                    std::iter::zip(&method.sig.inputs()[1..], args).enumerate()
510                {
511                    let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else {
512                        continue;
513                    };
514                    let arg_ty = arg_ty.fold_with(&mut fudger);
515                    let _ =
516                        self.coerce(arg_expr, arg_ty, *expected_arg_ty, AllowTwoPhase::No, None);
517                    self.select_obligations_where_possible(|errs| {
518                        // Yeet the errors, we're already reporting errors.
519                        errs.clear();
520                    });
521                    // If our rcvr, after inference due to unifying the signature
522                    // with the expected argument type, is still compatible with
523                    // the rcvr, then it must've not been the source of blame.
524                    if self.can_eq(self.param_env, rcvr_ty, expected_ty) {
525                        continue;
526                    }
527                    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}`..."));
528                    err.span_label(
529                        binding.span,
530                        ::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}`"),
531                    );
532                    // Using our "ideal" method signature, suggest a fix to this
533                    // blame arg, if possible. Don't do this if we're coming from
534                    // arg mismatch code, because we'll possibly suggest a mutually
535                    // incompatible fix at the original mismatch site.
536                    // HACK(compiler-errors): We don't actually consider the implications
537                    // of our inference guesses in `emit_type_mismatch_suggestions`, so
538                    // only suggest things when we know our type error is precisely due to
539                    // a type mismatch, and not via some projection or something. See #116155.
540                    if #[allow(non_exhaustive_omitted_patterns)] match source {
    TypeMismatchSource::Ty(_) => true,
    _ => false,
}matches!(source, TypeMismatchSource::Ty(_))
541                        && let Some(ideal_method) = ideal_method
542                        && Some(ideal_method.def_id)
543                            == self
544                                .typeck_results
545                                .borrow()
546                                .type_dependent_def_id(parent_expr.hir_id)
547                        && let ideal_arg_ty =
548                            self.deeply_resolve_ignoring_regions(ideal_method.sig.inputs()[idx + 1])
549                        && !ideal_arg_ty.has_non_region_infer()
550                    {
551                        self.emit_type_mismatch_suggestions(
552                            err,
553                            arg_expr,
554                            arg_ty,
555                            ideal_arg_ty,
556                            None,
557                            None,
558                        );
559                    }
560                    return true;
561                }
562            }
563            err.span_label(
564                binding.span,
565                ::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}`"),
566            );
567            return true;
568        }
569
570        // We must've not found something that constrained the expr.
571        false
572    }
573
574    // When encountering a type error on the value of a `break`, try to point at the reason for the
575    // expected type.
576    pub(crate) fn annotate_loop_expected_due_to_inference(
577        &self,
578        err: &mut Diag<'_>,
579        expr: &hir::Expr<'_>,
580        error: Option<TypeError<'tcx>>,
581    ) {
582        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
583            return;
584        };
585        let mut parent_id = self.tcx.parent_hir_id(expr.hir_id);
586        let mut parent;
587        'outer: loop {
588            // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement.
589            let (hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(p), .. })
590            | hir::Node::Block(&hir::Block { expr: Some(p), .. })
591            | hir::Node::Expr(p)) = self.tcx.hir_node(parent_id)
592            else {
593                break;
594            };
595            parent = p;
596            parent_id = self.tcx.parent_hir_id(parent_id);
597            let hir::ExprKind::Break(destination, _) = parent.kind else {
598                continue;
599            };
600            let mut parent_id = parent_id;
601            let mut direct = false;
602            loop {
603                // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
604                let parent = match self.tcx.hir_node(parent_id) {
605                    hir::Node::Expr(parent) => {
606                        parent_id = self.tcx.parent_hir_id(parent.hir_id);
607                        parent
608                    }
609                    hir::Node::Stmt(hir::Stmt {
610                        hir_id,
611                        kind: hir::StmtKind::Semi(parent) | hir::StmtKind::Expr(parent),
612                        ..
613                    }) => {
614                        parent_id = self.tcx.parent_hir_id(*hir_id);
615                        parent
616                    }
617                    hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Let(_), .. }) => {
618                        parent_id = self.tcx.parent_hir_id(*hir_id);
619                        parent
620                    }
621                    hir::Node::LetStmt(hir::LetStmt { hir_id, .. }) => {
622                        parent_id = self.tcx.parent_hir_id(*hir_id);
623                        parent
624                    }
625                    hir::Node::Block(_) => {
626                        parent_id = self.tcx.parent_hir_id(parent_id);
627                        parent
628                    }
629                    _ => break,
630                };
631                if let hir::ExprKind::Loop(..) = parent.kind {
632                    // When you have `'a: loop { break; }`, the `break` corresponds to the labeled
633                    // loop, so we need to account for that.
634                    direct = !direct;
635                }
636                if let hir::ExprKind::Loop(block, label, _, span) = parent.kind
637                    && (destination.label == label || direct)
638                {
639                    if let Some((reason_span, message)) =
640                        self.maybe_get_coercion_reason(parent_id, parent.span)
641                    {
642                        err.span_label(reason_span, message);
643                        err.span_label(
644                            span,
645                            ::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}`"),
646                        );
647                        break 'outer;
648                    } else {
649                        // Locate all other `break` statements within the same `loop` that might
650                        // have affected inference.
651                        struct FindBreaks<'tcx> {
652                            label: Option<rustc_ast::Label>,
653                            uses: Vec<&'tcx hir::Expr<'tcx>>,
654                            nest_depth: usize,
655                        }
656                        impl<'tcx> Visitor<'tcx> for FindBreaks<'tcx> {
657                            fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
658                                let nest_depth = self.nest_depth;
659                                if let hir::ExprKind::Loop(_, label, _, _) = ex.kind {
660                                    if label == self.label {
661                                        // Account for `'a: loop { 'a: loop {...} }`.
662                                        return;
663                                    }
664                                    self.nest_depth += 1;
665                                }
666                                if let hir::ExprKind::Break(destination, _) = ex.kind
667                                    && (self.label == destination.label
668                                        // Account for `loop { 'a: loop { loop { break; } } }`.
669                                        || destination.label.is_none() && self.nest_depth == 0)
670                                {
671                                    self.uses.push(ex);
672                                }
673                                hir::intravisit::walk_expr(self, ex);
674                                self.nest_depth = nest_depth;
675                            }
676                        }
677                        let mut expr_finder = FindBreaks { label, uses: ::alloc::vec::Vec::new()vec![], nest_depth: 0 };
678                        expr_finder.visit_block(block);
679                        let mut exit = false;
680                        for ex in expr_finder.uses {
681                            let hir::ExprKind::Break(_, val) = ex.kind else {
682                                continue;
683                            };
684                            let ty = match val {
685                                Some(val) => {
686                                    match self.typeck_results.borrow().expr_ty_adjusted_opt(val) {
687                                        None => continue,
688                                        Some(ty) => ty,
689                                    }
690                                }
691                                None => self.tcx.types.unit,
692                            };
693                            if self.can_eq(self.param_env, ty, expected) {
694                                err.span_label(ex.span, "expected because of this `break`");
695                                exit = true;
696                            }
697                        }
698                        if exit {
699                            break 'outer;
700                        }
701                    }
702                }
703            }
704        }
705    }
706
707    fn annotate_expected_due_to_let_ty(
708        &self,
709        err: &mut Diag<'_>,
710        expr: &hir::Expr<'_>,
711        error: Option<TypeError<'tcx>>,
712    ) {
713        // Skip nested block to find the correct parent node to point at.
714        let mut current_hir_id = expr.hir_id;
715        let parent = self
716            .tcx
717            .hir_parent_iter(expr.hir_id)
718            .find_map(|(parent_hir_id, parent)| match parent {
719                hir::Node::Block(block)
720                    if block.expr.is_some_and(|expr| expr.hir_id == current_hir_id) =>
721                {
722                    current_hir_id = parent_hir_id;
723                    None
724                }
725                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. })
726                    if block.hir_id == current_hir_id =>
727                {
728                    current_hir_id = parent_hir_id;
729                    None
730                }
731                parent => Some(parent),
732            })
733            .expect("an expression must have a non-block ancestor");
734
735        match (parent, error) {
736            (hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init: Some(init), .. }), _)
737                if init.hir_id == current_hir_id && !ty.span.source_equal(init.span) =>
738            {
739                // Point at `let` assignment type.
740                err.span_label(ty.span, "expected due to this");
741            }
742            (
743                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }),
744                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
745            ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
746                // We ignore closures explicitly because we already point at them elsewhere.
747                // Point at the assigned-to binding.
748                let mut primary_span = lhs.span;
749                let mut secondary_span = lhs.span;
750                let mut post_message = "";
751                match lhs.kind {
752                    hir::ExprKind::Path(hir::QPath::Resolved(
753                        None,
754                        hir::Path {
755                            res:
756                                hir::def::Res::Def(
757                                    hir::def::DefKind::Static { .. } | hir::def::DefKind::Const,
758                                    def_id,
759                                ),
760                            ..
761                        },
762                    )) => {
763                        if let Some(hir::Node::Item(hir::Item {
764                            kind:
765                                hir::ItemKind::Static(_, ident, ty, _)
766                                | hir::ItemKind::Const(ident, _, ty, _),
767                            ..
768                        })) = self.tcx.hir_get_if_local(*def_id)
769                        {
770                            primary_span = ty.span;
771                            secondary_span = ident.span;
772                            post_message = " type";
773                        }
774                    }
775                    hir::ExprKind::Path(hir::QPath::Resolved(
776                        None,
777                        hir::Path { res: hir::def::Res::Local(hir_id), .. },
778                    )) => {
779                        if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) {
780                            primary_span = pat.span;
781                            secondary_span = pat.span;
782                            match self.tcx.parent_hir_node(pat.hir_id) {
783                                hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => {
784                                    primary_span = ty.span;
785                                    post_message = " type";
786                                }
787                                hir::Node::LetStmt(hir::LetStmt { init: Some(init), .. }) => {
788                                    primary_span = init.span;
789                                    post_message = " value";
790                                }
791                                hir::Node::Param(hir::Param { ty_span, .. }) => {
792                                    primary_span = *ty_span;
793                                    post_message = " parameter type";
794                                }
795                                _ => {}
796                            }
797                        }
798                    }
799                    _ => {}
800                }
801
802                if primary_span != secondary_span
803                    && self
804                        .tcx
805                        .sess
806                        .source_map()
807                        .is_multiline(secondary_span.shrink_to_hi().until(primary_span))
808                {
809                    // We are pointing at the binding's type or initializer value, but it's pattern
810                    // is in a different line, so we point at both.
811                    err.span_label(secondary_span, "expected due to the type of this binding");
812                    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}"));
813                } else if post_message.is_empty() {
814                    // We are pointing at either the assignment lhs or the binding def pattern.
815                    err.span_label(primary_span, "expected due to the type of this binding");
816                } else {
817                    // We are pointing at the binding's type or initializer value.
818                    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}"));
819                }
820
821                if !lhs.is_syntactic_place_expr() {
822                    // We already emitted E0070 "invalid left-hand side of assignment", so we
823                    // silence this.
824                    err.downgrade_to_delayed_bug();
825                }
826            }
827            (
828                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }),
829                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
830            ) if rhs.hir_id == expr.hir_id
831                && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected)
832                // let expressions being marked as `bool` is confusing (see issue #147665)
833                && !#[allow(non_exhaustive_omitted_patterns)] match lhs.kind {
    hir::ExprKind::Let(..) => true,
    _ => false,
}matches!(lhs.kind, hir::ExprKind::Let(..)) =>
834            {
835                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}`"));
836            }
837            _ => {}
838        }
839    }
840
841    /// Detect the following case
842    ///
843    /// ```text
844    /// fn change_object(mut b: &Ty) {
845    ///     let a = Ty::new();
846    ///     b = a;
847    /// }
848    /// ```
849    ///
850    /// where the user likely meant to modify the value behind there reference, use `b` as an out
851    /// parameter, instead of mutating the local binding. When encountering this we suggest:
852    ///
853    /// ```text
854    /// fn change_object(b: &'_ mut Ty) {
855    ///     let a = Ty::new();
856    ///     *b = a;
857    /// }
858    /// ```
859    fn annotate_mut_binding_to_immutable_binding(
860        &self,
861        err: &mut Diag<'_>,
862        expr: &hir::Expr<'_>,
863        expr_ty: Ty<'tcx>,
864        expected: Ty<'tcx>,
865        error: Option<TypeError<'tcx>>,
866    ) -> bool {
867        if let Some(TypeError::Sorts(ExpectedFound { .. })) = error
868            && let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()
869
870            // The difference between the expected and found values is one level of borrowing.
871            && self.can_eq(self.param_env, *inner, expr_ty)
872
873            // We have an `ident = expr;` assignment.
874            && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
875                self.tcx.parent_hir_node(expr.hir_id)
876            && rhs.hir_id == expr.hir_id
877
878            // We are assigning to some binding.
879            && let hir::ExprKind::Path(hir::QPath::Resolved(
880                None,
881                hir::Path { res: hir::def::Res::Local(hir_id), .. },
882            )) = lhs.kind
883            && let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id)
884
885            // The pattern we have is an fn argument.
886            && let hir::Node::Param(hir::Param { ty_span, .. }) =
887                self.tcx.parent_hir_node(pat.hir_id)
888            && let item = self.tcx.hir_get_parent_item(pat.hir_id)
889            && let item = self.tcx.hir_owner_node(item)
890            && let Some(fn_decl) = item.fn_decl()
891
892            // We have a mutable binding in the argument.
893            && let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
894
895            // Look for the type corresponding to the argument pattern we have in the argument list.
896            && let Some(ty_ref) = fn_decl
897                .inputs
898                .iter()
899                .filter_map(|ty| match ty.kind {
900                    hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)),
901                    _ => None,
902                })
903                .next()
904        {
905            let mut sugg = if ty_ref.1.mutbl.is_mut() {
906                // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
907                ::alloc::vec::Vec::new()vec![]
908            } else {
909                // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
910                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ty_ref.1.ty.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![(
911                    ty_ref.1.ty.span.shrink_to_lo(),
912                    format!("{}mut ", if ty_ref.0.ident.span.is_empty() { "" } else { " " },),
913                )]
914            };
915            sugg.extend([
916                (pat.span.until(ident.span), String::new()),
917                (lhs.span.shrink_to_lo(), "*".to_string()),
918            ]);
919            // We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
920            // assignment from `ident = val;` to `*ident = val;`.
921            err.multipart_suggestion(
922                "you might have meant to mutate the pointed at value being passed in, instead of \
923                changing the reference in the local binding",
924                sugg,
925                Applicability::MaybeIncorrect,
926            );
927            return true;
928        }
929        false
930    }
931
932    fn annotate_alternative_method_deref(
933        &self,
934        err: &mut Diag<'_>,
935        expr: &hir::Expr<'_>,
936        error: Option<TypeError<'tcx>>,
937    ) {
938        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
939            return;
940        };
941        let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
942            self.tcx.parent_hir_node(expr.hir_id)
943        else {
944            return;
945        };
946        if rhs.hir_id != expr.hir_id || expected.is_closure() {
947            return;
948        }
949        let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else {
950            return;
951        };
952        let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else {
953            return;
954        };
955        let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else {
956            return;
957        };
958
959        let Ok(pick) = self.lookup_probe_for_diagnostic(
960            path.ident,
961            self_ty,
962            deref,
963            probe::ProbeScope::TraitsInScope,
964            None,
965        ) else {
966            return;
967        };
968
969        let Ok(in_scope_methods) = self.probe_for_name_many(
970            probe::Mode::MethodCall,
971            path.ident,
972            Some(expected),
973            probe::IsSuggestion(true),
974            self_ty,
975            deref.hir_id,
976            probe::ProbeScope::TraitsInScope,
977        ) else {
978            return;
979        };
980
981        let other_methods_in_scope: Vec<_> =
982            in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
983
984        let Ok(all_methods) = self.probe_for_name_many(
985            probe::Mode::MethodCall,
986            path.ident,
987            Some(expected),
988            probe::IsSuggestion(true),
989            self_ty,
990            deref.hir_id,
991            probe::ProbeScope::AllTraits,
992        ) else {
993            return;
994        };
995
996        let suggestions: Vec<_> = all_methods
997            .into_iter()
998            .filter(|c| c.item.def_id != pick.item.def_id)
999            .map(|c| {
1000                let m = c.item;
1001                let generic_args = ty::GenericArgs::for_item(self.tcx, m.def_id, |param, _| {
1002                    self.var_for_def(deref.span, param)
1003                });
1004                let mutability =
1005                    match self.tcx.fn_sig(m.def_id).skip_binder().input(0).skip_binder().kind() {
1006                        ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
1007                        ty::Ref(_, _, _) => "&",
1008                        _ => "",
1009                    };
1010                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(deref.span.until(base.span),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}({1}",
                                    {
                                        let _guard = NoTrimmedGuard::new();
                                        self.tcx.def_path_str_with_args(m.def_id, generic_args)
                                    }, mutability))
                        })),
                match &args {
                    [] =>
                        (base.span.shrink_to_hi().with_hi(deref.span.hi()),
                            ")".to_string()),
                    [first, ..] =>
                        (base.span.between(first.span), ", ".to_string()),
                }]))vec![
1011                    (
1012                        deref.span.until(base.span),
1013                        format!(
1014                            "{}({}",
1015                            with_no_trimmed_paths!(
1016                                self.tcx.def_path_str_with_args(m.def_id, generic_args,)
1017                            ),
1018                            mutability,
1019                        ),
1020                    ),
1021                    match &args {
1022                        [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
1023                        [first, ..] => (base.span.between(first.span), ", ".to_string()),
1024                    },
1025                ]
1026            })
1027            .collect();
1028        if suggestions.is_empty() {
1029            return;
1030        }
1031        let mut path_span: MultiSpan = path.ident.span.into();
1032        path_span.push_span_label(
1033            path.ident.span,
1034            {
    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)))
        })
}with_no_trimmed_paths!(format!(
1035                "refers to `{}`",
1036                self.tcx.def_path_str(pick.item.def_id),
1037            )),
1038        );
1039        let container_id = pick.item.container_id(self.tcx);
1040        let container = { let _guard = NoTrimmedGuard::new(); self.tcx.def_path_str(container_id) }with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
1041        for &def_id in pick.import_ids {
1042            let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
1043            path_span
1044                .push_span_label(self.tcx.hir_span(hir_id), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` imported here", container))
    })format!("`{container}` imported here"));
1045        }
1046        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()))
                }),
    }
}with_no_trimmed_paths!(match &other_methods_in_scope[..] {
1047            [] => return,
1048            [candidate] => format!(
1049                "the method of the same name on {} `{}`",
1050                match candidate.kind {
1051                    probe::CandidateKind::InherentImplCandidate { .. } => "the inherent impl for",
1052                    _ => "trait",
1053                },
1054                self.tcx.def_path_str(candidate.item.container_id(self.tcx))
1055            ),
1056            _ if other_methods_in_scope.len() < 5 => {
1057                format!(
1058                    "the methods of the same name on {}",
1059                    listify(
1060                        &other_methods_in_scope[..other_methods_in_scope.len() - 1],
1061                        |c| format!("`{}`", self.tcx.def_path_str(c.item.container_id(self.tcx)))
1062                    )
1063                    .unwrap_or_default(),
1064                )
1065            }
1066            _ => format!(
1067                "the methods of the same name on {} other traits",
1068                other_methods_in_scope.len()
1069            ),
1070        });
1071        err.span_note(
1072            path_span,
1073            ::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))
    })format!(
1074                "the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
1075                path.ident,
1076            ),
1077        );
1078        if suggestions.len() > other_methods_in_scope.len() {
1079            err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("additionally, there are {0} other available methods that aren\'t in scope",
                suggestions.len() - other_methods_in_scope.len()))
    })format!(
1080                "additionally, there are {} other available methods that aren't in scope",
1081                suggestions.len() - other_methods_in_scope.len()
1082            ));
1083        }
1084        err.multipart_suggestions(
1085            ::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" }))
    })format!(
1086                "you might have meant to call {}; you can use the fully-qualified path to call {} \
1087                 explicitly",
1088                if suggestions.len() == 1 {
1089                    "the other method"
1090                } else {
1091                    "one of the other methods"
1092                },
1093                if suggestions.len() == 1 { "it" } else { "one of them" },
1094            ),
1095            suggestions,
1096            Applicability::MaybeIncorrect,
1097        );
1098    }
1099
1100    pub(crate) fn get_conversion_methods_for_diagnostic(
1101        &self,
1102        span: Span,
1103        expected: Ty<'tcx>,
1104        checked_ty: Ty<'tcx>,
1105        hir_id: hir::HirId,
1106    ) -> Vec<AssocItem> {
1107        let methods = self.probe_for_return_type_for_diagnostic(
1108            span,
1109            probe::Mode::MethodCall,
1110            expected,
1111            checked_ty,
1112            hir_id,
1113            |m| {
1114                self.has_only_self_parameter(m)
1115                // This special internal attribute is used to permit
1116                // "identity-like" conversion methods to be suggested here.
1117                //
1118                // FIXME (#46459 and #46460): ideally
1119                // `std::convert::Into::into` and `std::borrow:ToOwned` would
1120                // also be `#[rustc_conversion_suggestion]`, if not for
1121                // method-probing false-positives and -negatives (respectively).
1122                //
1123                // FIXME? Other potential candidate methods: `as_ref` and
1124                // `as_mut`?
1125                && {
        {
            '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)
1126            },
1127        );
1128
1129        methods
1130    }
1131
1132    /// This function checks whether the method is not static and does not accept other parameters than `self`.
1133    fn has_only_self_parameter(&self, method: &AssocItem) -> bool {
1134        method.is_method()
1135            && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() == 1
1136    }
1137
1138    /// If the given `HirId` corresponds to a block with a trailing expression, return that expression
1139    pub(crate) fn maybe_get_block_expr(
1140        &self,
1141        expr: &hir::Expr<'tcx>,
1142    ) -> Option<&'tcx hir::Expr<'tcx>> {
1143        match expr {
1144            hir::Expr { kind: hir::ExprKind::Block(block, ..), .. } => block.expr,
1145            _ => None,
1146        }
1147    }
1148
1149    /// Returns whether the given expression is a destruct assignment desugaring.
1150    /// For example, `(a, b) = (1, &2);`
1151    /// Here we try to find the pattern binding of the expression,
1152    /// `default_binding_modes` is false only for destruct assignment desugaring.
1153    pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool {
1154        if let hir::ExprKind::Path(hir::QPath::Resolved(
1155            _,
1156            hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
1157        )) = expr.kind
1158            && let bind = self.tcx.hir_node(*bind_hir_id)
1159            && let parent = self.tcx.parent_hir_node(*bind_hir_id)
1160            && let hir::Node::Pat(hir::Pat {
1161                kind: hir::PatKind::Binding(_, _hir_id, _, _), ..
1162            }) = bind
1163            && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent
1164        {
1165            true
1166        } else {
1167            false
1168        }
1169    }
1170
1171    fn explain_self_literal(
1172        &self,
1173        err: &mut Diag<'_>,
1174        expr: &hir::Expr<'tcx>,
1175        expected: Ty<'tcx>,
1176        found: Ty<'tcx>,
1177    ) {
1178        match expr.peel_drop_temps().kind {
1179            hir::ExprKind::Struct(
1180                hir::QPath::Resolved(
1181                    None,
1182                    hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. },
1183                ),
1184                ..,
1185            )
1186            | hir::ExprKind::Call(
1187                hir::Expr {
1188                    kind:
1189                        hir::ExprKind::Path(hir::QPath::Resolved(
1190                            None,
1191                            hir::Path {
1192                                res: hir::def::Res::SelfTyAlias { alias_to, .. },
1193                                span,
1194                                ..
1195                            },
1196                        )),
1197                    ..
1198                },
1199                ..,
1200            ) => {
1201                if let Some(hir::Node::Item(hir::Item {
1202                    kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
1203                    ..
1204                })) = self.tcx.hir_get_if_local(*alias_to)
1205                {
1206                    err.span_label(self_ty.span, "this is the type of the `Self` literal");
1207                }
1208                if let ty::Adt(e_def, e_args) = expected.kind()
1209                    && let ty::Adt(f_def, _f_args) = found.kind()
1210                    && e_def == f_def
1211                {
1212                    err.span_suggestion_verbose(
1213                        *span,
1214                        "use the type name directly",
1215                        self.tcx.value_path_str_with_args(e_def.did(), e_args),
1216                        Applicability::MaybeIncorrect,
1217                    );
1218                }
1219            }
1220            _ => {}
1221        }
1222    }
1223
1224    fn note_wrong_return_ty_due_to_generic_arg(
1225        &self,
1226        err: &mut Diag<'_>,
1227        expr: &hir::Expr<'_>,
1228        checked_ty: Ty<'tcx>,
1229    ) {
1230        let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr.hir_id) else {
1231            return;
1232        };
1233        if parent_expr.span.desugaring_kind().is_some() {
1234            return;
1235        }
1236        enum CallableKind {
1237            Function,
1238            Method,
1239            Constructor,
1240        }
1241        let mut maybe_emit_help = |def_id: hir::def_id::DefId,
1242                                   callable: Ident,
1243                                   args: &[hir::Expr<'_>],
1244                                   kind: CallableKind| {
1245            let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
1246            let fn_ty = self.tcx.type_of(def_id).skip_binder();
1247            if !fn_ty.is_fn() {
1248                return;
1249            }
1250            let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
1251            let Some(&arg) = fn_sig
1252                .inputs()
1253                .get(arg_idx + if #[allow(non_exhaustive_omitted_patterns)] match kind {
    CallableKind::Method => true,
    _ => false,
}matches!(kind, CallableKind::Method) { 1 } else { 0 })
1254            else {
1255                return;
1256            };
1257            if #[allow(non_exhaustive_omitted_patterns)] match arg.kind() {
    ty::Param(_) => true,
    _ => false,
}matches!(arg.kind(), ty::Param(_))
1258                && fn_sig.output().contains(arg)
1259                && self.node_ty(args[arg_idx].hir_id) == checked_ty
1260            {
1261                let mut multi_span: MultiSpan = parent_expr.span.into();
1262                multi_span.push_span_label(
1263                    args[arg_idx].span,
1264                    ::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!(
1265                        "this argument influences the {} of `{}`",
1266                        if matches!(kind, CallableKind::Constructor) {
1267                            "type"
1268                        } else {
1269                            "return type"
1270                        },
1271                        callable
1272                    ),
1273                );
1274                err.span_help(
1275                    multi_span,
1276                    ::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!(
1277                        "the {} `{}` due to the type of the argument passed",
1278                        match kind {
1279                            CallableKind::Function => "return type of this call is",
1280                            CallableKind::Method => "return type of this call is",
1281                            CallableKind::Constructor => "type constructed contains",
1282                        },
1283                        checked_ty
1284                    ),
1285                );
1286            }
1287        };
1288        match parent_expr.kind {
1289            hir::ExprKind::Call(fun, args) => {
1290                let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else {
1291                    return;
1292                };
1293                let hir::def::Res::Def(kind, def_id) = path.res else {
1294                    return;
1295                };
1296                let callable_kind = if #[allow(non_exhaustive_omitted_patterns)] match kind {
    hir::def::DefKind::Ctor(_, _) => true,
    _ => false,
}matches!(kind, hir::def::DefKind::Ctor(_, _)) {
1297                    CallableKind::Constructor
1298                } else {
1299                    CallableKind::Function
1300                };
1301                maybe_emit_help(def_id, path.segments.last().unwrap().ident, args, callable_kind);
1302            }
1303            hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
1304                let Some(def_id) =
1305                    self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
1306                else {
1307                    return;
1308                };
1309                maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
1310            }
1311            _ => return,
1312        }
1313    }
1314}
1315
1316pub(crate) enum TypeMismatchSource<'tcx> {
1317    /// Expected the binding to have the given type, but it was found to have
1318    /// a different type. Find out when that type first became incompatible.
1319    Ty(Ty<'tcx>),
1320    /// When we fail during method argument checking, try to find out if a previous
1321    /// expression has constrained the method's receiver in a way that makes the
1322    /// argument's type incompatible.
1323    Arg { call_expr: &'tcx hir::Expr<'tcx>, incompatible_arg: usize },
1324}