1use rustc_errors::{Applicability, Diag, MultiSpan, listify};
2use rustc_hir::attrs::AttributeKind;
3use rustc_hir::def::Res;
4use rustc_hir::intravisit::Visitor;
5use rustc_hir::{self as hir, find_attr};
6use rustc_infer::infer::DefineOpaqueTypes;
7use rustc_middle::bug;
8use rustc_middle::ty::adjustment::AllowTwoPhase;
9use rustc_middle::ty::error::{ExpectedFound, TypeError};
10use rustc_middle::ty::print::with_no_trimmed_paths;
11use rustc_middle::ty::{self, AssocItem, BottomUpFolder, Ty, TypeFoldable, TypeVisitableExt};
12use rustc_span::{DUMMY_SP, Ident, Span, sym};
13use rustc_trait_selection::infer::InferCtxtExt;
14use rustc_trait_selection::traits::ObligationCause;
15use tracing::instrument;
16
17use super::method::probe;
18use crate::FnCtxt;
19
20impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21 pub(crate) fn emit_type_mismatch_suggestions(
22 &self,
23 err: &mut Diag<'_>,
24 expr: &hir::Expr<'tcx>,
25 expr_ty: Ty<'tcx>,
26 expected: Ty<'tcx>,
27 expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
28 error: Option<TypeError<'tcx>>,
29 ) {
30 if expr_ty == expected {
31 return;
32 }
33 self.annotate_alternative_method_deref(err, expr, error);
34 self.explain_self_literal(err, expr, expected, expr_ty);
35
36 let suggested = self.suggest_missing_parentheses(err, expr)
38 || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
39 || self.suggest_remove_last_method_call(err, expr, expected)
40 || self.suggest_associated_const(err, expr, expected)
41 || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
42 || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
43 || self.suggest_option_to_bool(err, expr, expr_ty, expected)
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_no_capture_closure(err, 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 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 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 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("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(&["cause", "expected",
"actual"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual)
as &dyn 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 expected
247 }
248 }
249 }
250
251 #[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("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(&["checked_ty",
"expected"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&checked_ty)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected)
as &dyn 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 =
if self.next_trait_solver() {
expected
} else { self.resolve_vars_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.resolve_vars_if_possible(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 = if self.next_trait_solver() {
265 expected
266 } else {
267 self.resolve_vars_with_obligations(expected)
268 };
269
270 let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
271 Ok(ty) => return Ok(ty),
272 Err(e) => e,
273 };
274
275 self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr);
276
277 self.set_tainted_by_errors(self.dcx().span_delayed_bug(
278 expr.span,
279 "`TypeError` when attempting coercion but no error emitted",
280 ));
281 let expr = expr.peel_drop_temps();
282 let cause = self.misc(expr.span);
283 let expr_ty = self.resolve_vars_if_possible(checked_ty);
284 let mut err =
285 self.err_ctxt().report_mismatched_types(&cause, self.param_env, expected, expr_ty, e);
286
287 self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
288
289 Err(err)
290 }
291
292 pub(crate) fn note_source_of_type_mismatch_constraint(
295 &self,
296 err: &mut Diag<'_>,
297 expr: &hir::Expr<'_>,
298 source: TypeMismatchSource<'tcx>,
299 ) -> bool {
300 let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else {
301 return false;
302 };
303 let [hir::PathSegment { ident, args: None, .. }] = p.segments else {
304 return false;
305 };
306 let hir::def::Res::Local(local_hir_id) = p.res else {
307 return false;
308 };
309 let hir::Node::Pat(pat) = self.tcx.hir_node(local_hir_id) else {
310 return false;
311 };
312 let (init_ty_hir_id, init) = match self.tcx.parent_hir_node(pat.hir_id) {
313 hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init, .. }) => (ty.hir_id, *init),
314 hir::Node::LetStmt(hir::LetStmt { init: Some(init), .. }) => (init.hir_id, Some(*init)),
315 _ => return false,
316 };
317 let Some(init_ty) = self.node_ty_opt(init_ty_hir_id) else {
318 return false;
319 };
320
321 struct FindExprs<'tcx> {
323 hir_id: hir::HirId,
324 uses: Vec<&'tcx hir::Expr<'tcx>>,
325 }
326 impl<'tcx> Visitor<'tcx> for FindExprs<'tcx> {
327 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
328 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
329 && let hir::def::Res::Local(hir_id) = path.res
330 && hir_id == self.hir_id
331 {
332 self.uses.push(ex);
333 }
334 hir::intravisit::walk_expr(self, ex);
335 }
336 }
337
338 let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() };
339 let body = self.tcx.hir_body_owned_by(self.body_id);
340 expr_finder.visit_expr(body.value);
341
342 let mut fudger = BottomUpFolder {
344 tcx: self.tcx,
345 ty_op: |ty| {
346 if let ty::Infer(infer) = ty.kind() {
347 match infer {
348 ty::TyVar(_) => self.next_ty_var(DUMMY_SP),
349 ty::IntVar(_) => self.next_int_var(),
350 ty::FloatVar(_) => self.next_float_var(),
351 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
352 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected fresh ty outside of the trait solver"))bug!("unexpected fresh ty outside of the trait solver")
353 }
354 }
355 } else {
356 ty
357 }
358 },
359 lt_op: |_| self.tcx.lifetimes.re_erased,
360 ct_op: |ct| {
361 if let ty::ConstKind::Infer(_) = ct.kind() {
362 self.next_const_var(DUMMY_SP)
363 } else {
364 ct
365 }
366 },
367 };
368
369 let expected_ty = match source {
370 TypeMismatchSource::Ty(expected_ty) => expected_ty,
371 TypeMismatchSource::Arg { call_expr, incompatible_arg: idx } => {
378 let hir::ExprKind::MethodCall(segment, _, args, _) = call_expr.kind else {
379 return false;
380 };
381 let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
382 return false;
383 };
384 let possible_rcvr_ty = expr_finder.uses.iter().rev().find_map(|binding| {
385 let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?;
386 if possible_rcvr_ty.is_ty_var() {
387 return None;
388 }
389 let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
391 let method = self
392 .lookup_method_for_diagnostic(
393 possible_rcvr_ty,
394 segment,
395 DUMMY_SP,
396 call_expr,
397 binding,
398 )
399 .ok()?;
400 if Some(method.def_id)
402 != self.typeck_results.borrow().type_dependent_def_id(call_expr.hir_id)
403 {
404 return None;
405 }
406 let _ = self
410 .at(&ObligationCause::dummy(), self.param_env)
411 .eq(DefineOpaqueTypes::Yes, method.sig.inputs()[idx + 1], arg_ty)
412 .ok()?;
413 self.select_obligations_where_possible(|errs| {
414 errs.clear();
416 });
417 Some(self.resolve_vars_if_possible(possible_rcvr_ty))
418 });
419 let Some(rcvr_ty) = possible_rcvr_ty else { return false };
420 rcvr_ty
421 }
422 };
423
424 if !self.can_eq(self.param_env, expected_ty, init_ty.fold_with(&mut fudger)) {
427 return false;
428 }
429
430 for window in expr_finder.uses.windows(2) {
431 let [binding, next_usage] = *window else {
435 continue;
436 };
437
438 if binding.hir_id == expr.hir_id {
440 break;
441 }
442
443 let Some(next_use_ty) = self.node_ty_opt(next_usage.hir_id) else {
444 continue;
445 };
446
447 if self.can_eq(self.param_env, expected_ty, next_use_ty.fold_with(&mut fudger)) {
450 continue;
451 }
452
453 if let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(binding.hir_id)
454 && let hir::ExprKind::MethodCall(segment, rcvr, args, _) = parent_expr.kind
455 && rcvr.hir_id == binding.hir_id
456 {
457 let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else {
461 continue;
462 };
463 let rcvr_ty = rcvr_ty.fold_with(&mut fudger);
464 let Ok(method) = self.lookup_method_for_diagnostic(
465 rcvr_ty,
466 segment,
467 DUMMY_SP,
468 parent_expr,
469 rcvr,
470 ) else {
471 continue;
472 };
473 if Some(method.def_id)
475 != self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
476 {
477 continue;
478 }
479
480 let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
481 let ideal_method = self
482 .lookup_method_for_diagnostic(
483 ideal_rcvr_ty,
484 segment,
485 DUMMY_SP,
486 parent_expr,
487 rcvr,
488 )
489 .ok()
490 .and_then(|method| {
491 let _ = self
492 .at(&ObligationCause::dummy(), self.param_env)
493 .eq(DefineOpaqueTypes::Yes, ideal_rcvr_ty, expected_ty)
494 .ok()?;
495 Some(method)
496 });
497
498 for (idx, (expected_arg_ty, arg_expr)) in
501 std::iter::zip(&method.sig.inputs()[1..], args).enumerate()
502 {
503 let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else {
504 continue;
505 };
506 let arg_ty = arg_ty.fold_with(&mut fudger);
507 let _ =
508 self.coerce(arg_expr, arg_ty, *expected_arg_ty, AllowTwoPhase::No, None);
509 self.select_obligations_where_possible(|errs| {
510 errs.clear();
512 });
513 if self.can_eq(self.param_env, rcvr_ty, expected_ty) {
517 continue;
518 }
519 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}`..."));
520 err.span_label(
521 binding.span,
522 ::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}`"),
523 );
524 if #[allow(non_exhaustive_omitted_patterns)] match source {
TypeMismatchSource::Ty(_) => true,
_ => false,
}matches!(source, TypeMismatchSource::Ty(_))
533 && let Some(ideal_method) = ideal_method
534 && Some(ideal_method.def_id)
535 == self
536 .typeck_results
537 .borrow()
538 .type_dependent_def_id(parent_expr.hir_id)
539 && let ideal_arg_ty =
540 self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1])
541 && !ideal_arg_ty.has_non_region_infer()
542 {
543 self.emit_type_mismatch_suggestions(
544 err,
545 arg_expr,
546 arg_ty,
547 ideal_arg_ty,
548 None,
549 None,
550 );
551 }
552 return true;
553 }
554 }
555 err.span_label(
556 binding.span,
557 ::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}`"),
558 );
559 return true;
560 }
561
562 false
564 }
565
566 pub(crate) fn annotate_loop_expected_due_to_inference(
569 &self,
570 err: &mut Diag<'_>,
571 expr: &hir::Expr<'_>,
572 error: Option<TypeError<'tcx>>,
573 ) {
574 let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
575 return;
576 };
577 let mut parent_id = self.tcx.parent_hir_id(expr.hir_id);
578 let mut parent;
579 'outer: loop {
580 let (hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(p), .. })
582 | hir::Node::Block(&hir::Block { expr: Some(p), .. })
583 | hir::Node::Expr(p)) = self.tcx.hir_node(parent_id)
584 else {
585 break;
586 };
587 parent = p;
588 parent_id = self.tcx.parent_hir_id(parent_id);
589 let hir::ExprKind::Break(destination, _) = parent.kind else {
590 continue;
591 };
592 let mut parent_id = parent_id;
593 let mut direct = false;
594 loop {
595 let parent = match self.tcx.hir_node(parent_id) {
597 hir::Node::Expr(parent) => {
598 parent_id = self.tcx.parent_hir_id(parent.hir_id);
599 parent
600 }
601 hir::Node::Stmt(hir::Stmt {
602 hir_id,
603 kind: hir::StmtKind::Semi(parent) | hir::StmtKind::Expr(parent),
604 ..
605 }) => {
606 parent_id = self.tcx.parent_hir_id(*hir_id);
607 parent
608 }
609 hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Let(_), .. }) => {
610 parent_id = self.tcx.parent_hir_id(*hir_id);
611 parent
612 }
613 hir::Node::LetStmt(hir::LetStmt { hir_id, .. }) => {
614 parent_id = self.tcx.parent_hir_id(*hir_id);
615 parent
616 }
617 hir::Node::Block(_) => {
618 parent_id = self.tcx.parent_hir_id(parent_id);
619 parent
620 }
621 _ => break,
622 };
623 if let hir::ExprKind::Loop(..) = parent.kind {
624 direct = !direct;
627 }
628 if let hir::ExprKind::Loop(block, label, _, span) = parent.kind
629 && (destination.label == label || direct)
630 {
631 if let Some((reason_span, message)) =
632 self.maybe_get_coercion_reason(parent_id, parent.span)
633 {
634 err.span_label(reason_span, message);
635 err.span_label(
636 span,
637 ::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}`"),
638 );
639 break 'outer;
640 } else {
641 struct FindBreaks<'tcx> {
644 label: Option<rustc_ast::Label>,
645 uses: Vec<&'tcx hir::Expr<'tcx>>,
646 nest_depth: usize,
647 }
648 impl<'tcx> Visitor<'tcx> for FindBreaks<'tcx> {
649 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
650 let nest_depth = self.nest_depth;
651 if let hir::ExprKind::Loop(_, label, _, _) = ex.kind {
652 if label == self.label {
653 return;
655 }
656 self.nest_depth += 1;
657 }
658 if let hir::ExprKind::Break(destination, _) = ex.kind
659 && (self.label == destination.label
660 || destination.label.is_none() && self.nest_depth == 0)
662 {
663 self.uses.push(ex);
664 }
665 hir::intravisit::walk_expr(self, ex);
666 self.nest_depth = nest_depth;
667 }
668 }
669 let mut expr_finder = FindBreaks { label, uses: ::alloc::vec::Vec::new()vec![], nest_depth: 0 };
670 expr_finder.visit_block(block);
671 let mut exit = false;
672 for ex in expr_finder.uses {
673 let hir::ExprKind::Break(_, val) = ex.kind else {
674 continue;
675 };
676 let ty = match val {
677 Some(val) => {
678 match self.typeck_results.borrow().expr_ty_adjusted_opt(val) {
679 None => continue,
680 Some(ty) => ty,
681 }
682 }
683 None => self.tcx.types.unit,
684 };
685 if self.can_eq(self.param_env, ty, expected) {
686 err.span_label(ex.span, "expected because of this `break`");
687 exit = true;
688 }
689 }
690 if exit {
691 break 'outer;
692 }
693 }
694 }
695 }
696 }
697 }
698
699 fn annotate_expected_due_to_let_ty(
700 &self,
701 err: &mut Diag<'_>,
702 expr: &hir::Expr<'_>,
703 error: Option<TypeError<'tcx>>,
704 ) {
705 match (self.tcx.parent_hir_node(expr.hir_id), error) {
706 (hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init: Some(init), .. }), _)
707 if init.hir_id == expr.hir_id && !ty.span.source_equal(init.span) =>
708 {
709 err.span_label(ty.span, "expected due to this");
711 }
712 (
713 hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }),
714 Some(TypeError::Sorts(ExpectedFound { expected, .. })),
715 ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
716 let mut primary_span = lhs.span;
719 let mut secondary_span = lhs.span;
720 let mut post_message = "";
721 match lhs.kind {
722 hir::ExprKind::Path(hir::QPath::Resolved(
723 None,
724 hir::Path {
725 res:
726 hir::def::Res::Def(
727 hir::def::DefKind::Static { .. } | hir::def::DefKind::Const,
728 def_id,
729 ),
730 ..
731 },
732 )) => {
733 if let Some(hir::Node::Item(hir::Item {
734 kind:
735 hir::ItemKind::Static(_, ident, ty, _)
736 | hir::ItemKind::Const(ident, _, ty, _),
737 ..
738 })) = self.tcx.hir_get_if_local(*def_id)
739 {
740 primary_span = ty.span;
741 secondary_span = ident.span;
742 post_message = " type";
743 }
744 }
745 hir::ExprKind::Path(hir::QPath::Resolved(
746 None,
747 hir::Path { res: hir::def::Res::Local(hir_id), .. },
748 )) => {
749 if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) {
750 primary_span = pat.span;
751 secondary_span = pat.span;
752 match self.tcx.parent_hir_node(pat.hir_id) {
753 hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => {
754 primary_span = ty.span;
755 post_message = " type";
756 }
757 hir::Node::LetStmt(hir::LetStmt { init: Some(init), .. }) => {
758 primary_span = init.span;
759 post_message = " value";
760 }
761 hir::Node::Param(hir::Param { ty_span, .. }) => {
762 primary_span = *ty_span;
763 post_message = " parameter type";
764 }
765 _ => {}
766 }
767 }
768 }
769 _ => {}
770 }
771
772 if primary_span != secondary_span
773 && self
774 .tcx
775 .sess
776 .source_map()
777 .is_multiline(secondary_span.shrink_to_hi().until(primary_span))
778 {
779 err.span_label(secondary_span, "expected due to the type of this binding");
782 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}"));
783 } else if post_message.is_empty() {
784 err.span_label(primary_span, "expected due to the type of this binding");
786 } else {
787 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}"));
789 }
790
791 if !lhs.is_syntactic_place_expr() {
792 err.downgrade_to_delayed_bug();
795 }
796 }
797 (
798 hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }),
799 Some(TypeError::Sorts(ExpectedFound { expected, .. })),
800 ) if rhs.hir_id == expr.hir_id
801 && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected)
802 && !#[allow(non_exhaustive_omitted_patterns)] match lhs.kind {
hir::ExprKind::Let(..) => true,
_ => false,
}matches!(lhs.kind, hir::ExprKind::Let(..)) =>
804 {
805 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}`"));
806 }
807 _ => {}
808 }
809 }
810
811 fn annotate_mut_binding_to_immutable_binding(
830 &self,
831 err: &mut Diag<'_>,
832 expr: &hir::Expr<'_>,
833 expr_ty: Ty<'tcx>,
834 expected: Ty<'tcx>,
835 error: Option<TypeError<'tcx>>,
836 ) -> bool {
837 if let Some(TypeError::Sorts(ExpectedFound { .. })) = error
838 && let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()
839
840 && self.can_eq(self.param_env, *inner, expr_ty)
842
843 && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
845 self.tcx.parent_hir_node(expr.hir_id)
846 && rhs.hir_id == expr.hir_id
847
848 && let hir::ExprKind::Path(hir::QPath::Resolved(
850 None,
851 hir::Path { res: hir::def::Res::Local(hir_id), .. },
852 )) = lhs.kind
853 && let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id)
854
855 && let hir::Node::Param(hir::Param { ty_span, .. }) =
857 self.tcx.parent_hir_node(pat.hir_id)
858 && let item = self.tcx.hir_get_parent_item(pat.hir_id)
859 && let item = self.tcx.hir_owner_node(item)
860 && let Some(fn_decl) = item.fn_decl()
861
862 && let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
864
865 && let Some(ty_ref) = fn_decl
867 .inputs
868 .iter()
869 .filter_map(|ty| match ty.kind {
870 hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)),
871 _ => None,
872 })
873 .next()
874 {
875 let mut sugg = if ty_ref.1.mutbl.is_mut() {
876 ::alloc::vec::Vec::new()vec![]
878 } else {
879 ::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![(
881 ty_ref.1.ty.span.shrink_to_lo(),
882 format!("{}mut ", if ty_ref.0.ident.span.is_empty() { "" } else { " " },),
883 )]
884 };
885 sugg.extend([
886 (pat.span.until(ident.span), String::new()),
887 (lhs.span.shrink_to_lo(), "*".to_string()),
888 ]);
889 err.multipart_suggestion_verbose(
892 "you might have meant to mutate the pointed at value being passed in, instead of \
893 changing the reference in the local binding",
894 sugg,
895 Applicability::MaybeIncorrect,
896 );
897 return true;
898 }
899 false
900 }
901
902 fn annotate_alternative_method_deref(
903 &self,
904 err: &mut Diag<'_>,
905 expr: &hir::Expr<'_>,
906 error: Option<TypeError<'tcx>>,
907 ) {
908 let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {
909 return;
910 };
911 let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
912 self.tcx.parent_hir_node(expr.hir_id)
913 else {
914 return;
915 };
916 if rhs.hir_id != expr.hir_id || expected.is_closure() {
917 return;
918 }
919 let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else {
920 return;
921 };
922 let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else {
923 return;
924 };
925 let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else {
926 return;
927 };
928
929 let Ok(pick) = self.lookup_probe_for_diagnostic(
930 path.ident,
931 self_ty,
932 deref,
933 probe::ProbeScope::TraitsInScope,
934 None,
935 ) else {
936 return;
937 };
938
939 let Ok(in_scope_methods) = self.probe_for_name_many(
940 probe::Mode::MethodCall,
941 path.ident,
942 Some(expected),
943 probe::IsSuggestion(true),
944 self_ty,
945 deref.hir_id,
946 probe::ProbeScope::TraitsInScope,
947 ) else {
948 return;
949 };
950
951 let other_methods_in_scope: Vec<_> =
952 in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
953
954 let Ok(all_methods) = self.probe_for_name_many(
955 probe::Mode::MethodCall,
956 path.ident,
957 Some(expected),
958 probe::IsSuggestion(true),
959 self_ty,
960 deref.hir_id,
961 probe::ProbeScope::AllTraits,
962 ) else {
963 return;
964 };
965
966 let suggestions: Vec<_> = all_methods
967 .into_iter()
968 .filter(|c| c.item.def_id != pick.item.def_id)
969 .map(|c| {
970 let m = c.item;
971 let generic_args = ty::GenericArgs::for_item(self.tcx, m.def_id, |param, _| {
972 self.var_for_def(deref.span, param)
973 });
974 let mutability =
975 match self.tcx.fn_sig(m.def_id).skip_binder().input(0).skip_binder().kind() {
976 ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
977 ty::Ref(_, _, _) => "&",
978 _ => "",
979 };
980 ::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![
981 (
982 deref.span.until(base.span),
983 format!(
984 "{}({}",
985 with_no_trimmed_paths!(
986 self.tcx.def_path_str_with_args(m.def_id, generic_args,)
987 ),
988 mutability,
989 ),
990 ),
991 match &args {
992 [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
993 [first, ..] => (base.span.between(first.span), ", ".to_string()),
994 },
995 ]
996 })
997 .collect();
998 if suggestions.is_empty() {
999 return;
1000 }
1001 let mut path_span: MultiSpan = path.ident.span.into();
1002 path_span.push_span_label(
1003 path.ident.span,
1004 {
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!(
1005 "refers to `{}`",
1006 self.tcx.def_path_str(pick.item.def_id),
1007 )),
1008 );
1009 let container_id = pick.item.container_id(self.tcx);
1010 let container = { let _guard = NoTrimmedGuard::new(); self.tcx.def_path_str(container_id) }with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
1011 for def_id in pick.import_ids {
1012 let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
1013 path_span
1014 .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"));
1015 }
1016 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[..] {
1017 [] => return,
1018 [candidate] => format!(
1019 "the method of the same name on {} `{}`",
1020 match candidate.kind {
1021 probe::CandidateKind::InherentImplCandidate { .. } => "the inherent impl for",
1022 _ => "trait",
1023 },
1024 self.tcx.def_path_str(candidate.item.container_id(self.tcx))
1025 ),
1026 _ if other_methods_in_scope.len() < 5 => {
1027 format!(
1028 "the methods of the same name on {}",
1029 listify(
1030 &other_methods_in_scope[..other_methods_in_scope.len() - 1],
1031 |c| format!("`{}`", self.tcx.def_path_str(c.item.container_id(self.tcx)))
1032 )
1033 .unwrap_or_default(),
1034 )
1035 }
1036 _ => format!(
1037 "the methods of the same name on {} other traits",
1038 other_methods_in_scope.len()
1039 ),
1040 });
1041 err.span_note(
1042 path_span,
1043 ::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!(
1044 "the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
1045 path.ident,
1046 ),
1047 );
1048 if suggestions.len() > other_methods_in_scope.len() {
1049 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!(
1050 "additionally, there are {} other available methods that aren't in scope",
1051 suggestions.len() - other_methods_in_scope.len()
1052 ));
1053 }
1054 err.multipart_suggestions(
1055 ::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!(
1056 "you might have meant to call {}; you can use the fully-qualified path to call {} \
1057 explicitly",
1058 if suggestions.len() == 1 {
1059 "the other method"
1060 } else {
1061 "one of the other methods"
1062 },
1063 if suggestions.len() == 1 { "it" } else { "one of them" },
1064 ),
1065 suggestions,
1066 Applicability::MaybeIncorrect,
1067 );
1068 }
1069
1070 pub(crate) fn get_conversion_methods_for_diagnostic(
1071 &self,
1072 span: Span,
1073 expected: Ty<'tcx>,
1074 checked_ty: Ty<'tcx>,
1075 hir_id: hir::HirId,
1076 ) -> Vec<AssocItem> {
1077 let methods = self.probe_for_return_type_for_diagnostic(
1078 span,
1079 probe::Mode::MethodCall,
1080 expected,
1081 checked_ty,
1082 hir_id,
1083 |m| {
1084 self.has_only_self_parameter(m)
1085 && {
{
'done:
{
for i in self.tcx.get_all_attrs(m.def_id) {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::RustcConversionSuggestion)
=> {
break 'done Some(());
}
_ => {}
}
}
None
}
}.is_some()
}find_attr!(self.tcx.get_all_attrs(m.def_id), AttributeKind::RustcConversionSuggestion)
1096 },
1097 );
1098
1099 methods
1100 }
1101
1102 fn has_only_self_parameter(&self, method: &AssocItem) -> bool {
1104 method.is_method()
1105 && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() == 1
1106 }
1107
1108 pub(crate) fn maybe_get_block_expr(
1110 &self,
1111 expr: &hir::Expr<'tcx>,
1112 ) -> Option<&'tcx hir::Expr<'tcx>> {
1113 match expr {
1114 hir::Expr { kind: hir::ExprKind::Block(block, ..), .. } => block.expr,
1115 _ => None,
1116 }
1117 }
1118
1119 pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool {
1124 if let hir::ExprKind::Path(hir::QPath::Resolved(
1125 _,
1126 hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
1127 )) = expr.kind
1128 && let bind = self.tcx.hir_node(*bind_hir_id)
1129 && let parent = self.tcx.parent_hir_node(*bind_hir_id)
1130 && let hir::Node::Pat(hir::Pat {
1131 kind: hir::PatKind::Binding(_, _hir_id, _, _), ..
1132 }) = bind
1133 && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent
1134 {
1135 true
1136 } else {
1137 false
1138 }
1139 }
1140
1141 fn explain_self_literal(
1142 &self,
1143 err: &mut Diag<'_>,
1144 expr: &hir::Expr<'tcx>,
1145 expected: Ty<'tcx>,
1146 found: Ty<'tcx>,
1147 ) {
1148 match expr.peel_drop_temps().kind {
1149 hir::ExprKind::Struct(
1150 hir::QPath::Resolved(
1151 None,
1152 hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. },
1153 ),
1154 ..,
1155 )
1156 | hir::ExprKind::Call(
1157 hir::Expr {
1158 kind:
1159 hir::ExprKind::Path(hir::QPath::Resolved(
1160 None,
1161 hir::Path {
1162 res: hir::def::Res::SelfTyAlias { alias_to, .. },
1163 span,
1164 ..
1165 },
1166 )),
1167 ..
1168 },
1169 ..,
1170 ) => {
1171 if let Some(hir::Node::Item(hir::Item {
1172 kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
1173 ..
1174 })) = self.tcx.hir_get_if_local(*alias_to)
1175 {
1176 err.span_label(self_ty.span, "this is the type of the `Self` literal");
1177 }
1178 if let ty::Adt(e_def, e_args) = expected.kind()
1179 && let ty::Adt(f_def, _f_args) = found.kind()
1180 && e_def == f_def
1181 {
1182 err.span_suggestion_verbose(
1183 *span,
1184 "use the type name directly",
1185 self.tcx.value_path_str_with_args(e_def.did(), e_args),
1186 Applicability::MaybeIncorrect,
1187 );
1188 }
1189 }
1190 _ => {}
1191 }
1192 }
1193
1194 fn note_wrong_return_ty_due_to_generic_arg(
1195 &self,
1196 err: &mut Diag<'_>,
1197 expr: &hir::Expr<'_>,
1198 checked_ty: Ty<'tcx>,
1199 ) {
1200 let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr.hir_id) else {
1201 return;
1202 };
1203 if parent_expr.span.desugaring_kind().is_some() {
1204 return;
1205 }
1206 enum CallableKind {
1207 Function,
1208 Method,
1209 Constructor,
1210 }
1211 let mut maybe_emit_help = |def_id: hir::def_id::DefId,
1212 callable: Ident,
1213 args: &[hir::Expr<'_>],
1214 kind: CallableKind| {
1215 let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
1216 let fn_ty = self.tcx.type_of(def_id).skip_binder();
1217 if !fn_ty.is_fn() {
1218 return;
1219 }
1220 let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
1221 let Some(&arg) = fn_sig
1222 .inputs()
1223 .get(arg_idx + if #[allow(non_exhaustive_omitted_patterns)] match kind {
CallableKind::Method => true,
_ => false,
}matches!(kind, CallableKind::Method) { 1 } else { 0 })
1224 else {
1225 return;
1226 };
1227 if #[allow(non_exhaustive_omitted_patterns)] match arg.kind() {
ty::Param(_) => true,
_ => false,
}matches!(arg.kind(), ty::Param(_))
1228 && fn_sig.output().contains(arg)
1229 && self.node_ty(args[arg_idx].hir_id) == checked_ty
1230 {
1231 let mut multi_span: MultiSpan = parent_expr.span.into();
1232 multi_span.push_span_label(
1233 args[arg_idx].span,
1234 ::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!(
1235 "this argument influences the {} of `{}`",
1236 if matches!(kind, CallableKind::Constructor) {
1237 "type"
1238 } else {
1239 "return type"
1240 },
1241 callable
1242 ),
1243 );
1244 err.span_help(
1245 multi_span,
1246 ::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!(
1247 "the {} `{}` due to the type of the argument passed",
1248 match kind {
1249 CallableKind::Function => "return type of this call is",
1250 CallableKind::Method => "return type of this call is",
1251 CallableKind::Constructor => "type constructed contains",
1252 },
1253 checked_ty
1254 ),
1255 );
1256 }
1257 };
1258 match parent_expr.kind {
1259 hir::ExprKind::Call(fun, args) => {
1260 let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else {
1261 return;
1262 };
1263 let hir::def::Res::Def(kind, def_id) = path.res else {
1264 return;
1265 };
1266 let callable_kind = if #[allow(non_exhaustive_omitted_patterns)] match kind {
hir::def::DefKind::Ctor(_, _) => true,
_ => false,
}matches!(kind, hir::def::DefKind::Ctor(_, _)) {
1267 CallableKind::Constructor
1268 } else {
1269 CallableKind::Function
1270 };
1271 maybe_emit_help(def_id, path.segments.last().unwrap().ident, args, callable_kind);
1272 }
1273 hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
1274 let Some(def_id) =
1275 self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
1276 else {
1277 return;
1278 };
1279 maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
1280 }
1281 _ => return,
1282 }
1283 }
1284}
1285
1286pub(crate) enum TypeMismatchSource<'tcx> {
1287 Ty(Ty<'tcx>),
1290 Arg { call_expr: &'tcx hir::Expr<'tcx>, incompatible_arg: usize },
1294}