1use std::{fmt, iter, mem};
2
3use itertools::Itertools;
4use rustc_data_structures::fx::FxIndexSet;
5use rustc_errors::codes::*;
6use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
7use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
8use rustc_hir::def_id::DefId;
9use rustc_hir::intravisit::Visitor;
10use rustc_hir::{ExprKind, HirId, LangItem, Node, QPath};
11use rustc_hir_analysis::check::potentially_plural_count;
12use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
13use rustc_index::IndexVec;
14use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
15use rustc_middle::ty::adjustment::AllowTwoPhase;
16use rustc_middle::ty::error::TypeError;
17use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
18use rustc_middle::{bug, span_bug};
19use rustc_session::Session;
20use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
21use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
22use rustc_trait_selection::infer::InferCtxtExt;
23use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
24use smallvec::SmallVec;
25use tracing::debug;
26use {rustc_ast as ast, rustc_hir as hir};
27
28use crate::Expectation::*;
29use crate::TupleArgumentsFlag::*;
30use crate::coercion::CoerceMany;
31use crate::errors::SuggestPtrNullMut;
32use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
33use crate::fn_ctxt::infer::FnCall;
34use crate::gather_locals::Declaration;
35use crate::inline_asm::InlineAsmCtxt;
36use crate::method::probe::IsSuggestion;
37use crate::method::probe::Mode::MethodCall;
38use crate::method::probe::ProbeScope::TraitsInScope;
39use crate::{
40 BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
41 TupleArgumentsFlag, errors, struct_span_code_err,
42};
43
44rustc_index::newtype_index! {
45 #[orderable]
46 #[debug_format = "GenericIdx({})"]
47 pub(crate) struct GenericIdx {}
48}
49
50#[derive(Clone, Copy, Default)]
51pub(crate) enum DivergingBlockBehavior {
52 #[default]
60 Never,
61
62 Unit,
71}
72
73impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
74 pub(in super::super) fn check_casts(&mut self) {
75 let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
78
79 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
80 for cast in deferred_cast_checks.drain(..) {
81 cast.check(self);
82 }
83
84 *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
85 }
86
87 pub(in super::super) fn check_transmutes(&self) {
88 let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
89 debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
90 for (from, to, hir_id) in deferred_transmute_checks.drain(..) {
91 self.check_transmute(from, to, hir_id);
92 }
93 }
94
95 pub(in super::super) fn check_asms(&self) {
96 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
97 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
98 for (asm, hir_id) in deferred_asm_checks.drain(..) {
99 let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
100 InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
101 }
102 }
103
104 pub(in super::super) fn check_repeat_exprs(&self) {
105 let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
106 debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
107
108 let deferred_repeat_expr_checks = deferred_repeat_expr_checks
109 .drain(..)
110 .flat_map(|(element, element_ty, count)| {
111 match &element.kind {
115 hir::ExprKind::ConstBlock(..) => return None,
116 hir::ExprKind::Path(qpath) => {
117 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
118 if let Res::Def(DefKind::Const | DefKind::AssocConst, _) = res {
119 return None;
120 }
121 }
122 _ => {}
123 }
124
125 let count = self
130 .structurally_resolve_const(element.span, self.normalize(element.span, count));
131
132 if count.references_error() {
136 return None;
137 }
138
139 Some((element, element_ty, count))
140 })
141 .collect::<Vec<_>>();
147
148 let enforce_copy_bound = |element: &hir::Expr<'_>, element_ty| {
149 let is_constable = match element.kind {
153 hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
154 ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
155 traits::IsConstable::Fn
156 }
157 _ => traits::IsConstable::No,
158 },
159 hir::ExprKind::Path(qpath) => {
160 match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
161 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
162 _ => traits::IsConstable::No,
163 }
164 }
165 _ => traits::IsConstable::No,
166 };
167
168 let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
169 let code = traits::ObligationCauseCode::RepeatElementCopy {
170 is_constable,
171 elt_span: element.span,
172 };
173 self.require_type_meets(element_ty, element.span, code, lang_item);
174 };
175
176 for (element, element_ty, count) in deferred_repeat_expr_checks {
177 match count.kind() {
178 ty::ConstKind::Value(val) => {
179 if val.try_to_target_usize(self.tcx).is_none_or(|count| count > 1) {
180 enforce_copy_bound(element, element_ty)
181 } else {
182 }
185 }
186
187 ty::ConstKind::Param(_)
190 | ty::ConstKind::Expr(_)
191 | ty::ConstKind::Placeholder(_)
192 | ty::ConstKind::Unevaluated(_) => enforce_copy_bound(element, element_ty),
193
194 ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => {
195 unreachable!()
196 }
197 }
198 }
199 }
200
201 pub(in super::super) fn check_argument_types(
204 &self,
205 call_span: Span,
207 call_expr: &'tcx hir::Expr<'tcx>,
209 formal_input_tys: &[Ty<'tcx>],
211 formal_output: Ty<'tcx>,
212 expectation: Expectation<'tcx>,
214 provided_args: &'tcx [hir::Expr<'tcx>],
216 c_variadic: bool,
218 tuple_arguments: TupleArgumentsFlag,
220 fn_def_id: Option<DefId>,
222 ) {
223 let tcx = self.tcx;
224
225 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
240 self.register_wf_obligation(
241 fn_input_ty.into(),
242 arg_expr.span,
243 ObligationCauseCode::WellFormed(None),
244 );
245 }
246
247 let formal_output = self.resolve_vars_with_obligations(formal_output);
252 let expected_input_tys: Option<Vec<_>> = expectation
253 .only_has_type(self)
254 .and_then(|expected_output| {
255 self.fudge_inference_if_ok(|| {
256 let ocx = ObligationCtxt::new(self);
257
258 let origin = self.misc(call_span);
263 ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
264 if !ocx.select_where_possible().is_empty() {
265 return Err(TypeError::Mismatch);
266 }
267
268 Ok(Some(
271 formal_input_tys
272 .iter()
273 .map(|&ty| self.resolve_vars_if_possible(ty))
274 .collect(),
275 ))
276 })
277 .ok()
278 })
279 .unwrap_or_default();
280
281 let mut err_code = E0061;
282
283 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
285 let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]);
286 match tuple_type.kind() {
287 ty::Tuple(arg_types) => {
289 if arg_types.len() != provided_args.len() {
291 err_code = E0057;
292 }
293 let expected_input_tys = match expected_input_tys {
294 Some(expected_input_tys) => match expected_input_tys.get(0) {
295 Some(ty) => match ty.kind() {
296 ty::Tuple(tys) => Some(tys.iter().collect()),
297 _ => None,
298 },
299 None => None,
300 },
301 None => None,
302 };
303 (arg_types.iter().collect(), expected_input_tys)
304 }
305 _ => {
306 let guar = struct_span_code_err!(
309 self.dcx(),
310 call_span,
311 E0059,
312 "cannot use call notation; the first type parameter \
313 for the function trait is neither a tuple nor unit"
314 )
315 .emit();
316 (self.err_args(provided_args.len(), guar), None)
317 }
318 }
319 } else {
320 (formal_input_tys.to_vec(), expected_input_tys)
321 };
322
323 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
325 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
326 expected_input_tys
327 } else {
328 formal_input_tys.clone()
329 };
330
331 let minimum_input_count = expected_input_tys.len();
332 let provided_arg_count = provided_args.len();
333
334 let demand_compatible = |idx| {
338 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
339 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
340 let provided_arg = &provided_args[idx];
341
342 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
343
344 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
348
349 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
350
351 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
355
356 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
360
361 let coerce_error =
362 self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
363 if coerce_error.is_some() {
364 return Compatibility::Incompatible(coerce_error);
365 }
366
367 let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
370 DefineOpaqueTypes::Yes,
371 formal_input_ty,
372 coerced_ty,
373 );
374
375 match formal_ty_error {
377 Ok(InferOk { obligations, value: () }) => {
378 self.register_predicates(obligations);
379 Compatibility::Compatible
380 }
381 Err(err) => Compatibility::Incompatible(Some(err)),
382 }
383 };
384
385 let mut compatibility_diagonal =
388 vec![Compatibility::Incompatible(None); provided_args.len()];
389
390 let mut call_appears_satisfied = if c_variadic {
395 provided_arg_count >= minimum_input_count
396 } else {
397 provided_arg_count == minimum_input_count
398 };
399
400 for check_closures in [false, true] {
406 if check_closures {
410 self.select_obligations_where_possible(|_| {})
411 }
412
413 for (idx, arg) in provided_args.iter().enumerate() {
416 if !check_closures {
420 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
421 }
422
423 if idx >= minimum_input_count {
429 continue;
430 }
431
432 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
438 !tcx.coroutine_is_async(closure.def_id.to_def_id())
439 } else {
440 false
441 };
442 if is_closure != check_closures {
443 continue;
444 }
445
446 let compatible = demand_compatible(idx);
447 let is_compatible = matches!(compatible, Compatibility::Compatible);
448 compatibility_diagonal[idx] = compatible;
449
450 if !is_compatible {
451 call_appears_satisfied = false;
452 }
453 }
454 }
455
456 if c_variadic && provided_arg_count < minimum_input_count {
457 err_code = E0060;
458 }
459
460 for arg in provided_args.iter().skip(minimum_input_count) {
461 let arg_ty = self.check_expr(arg);
463
464 if c_variadic {
469 fn variadic_error<'tcx>(
470 sess: &'tcx Session,
471 span: Span,
472 ty: Ty<'tcx>,
473 cast_ty: &str,
474 ) {
475 sess.dcx().emit_err(errors::PassToVariadicFunction {
476 span,
477 ty,
478 cast_ty,
479 sugg_span: span.shrink_to_hi(),
480 teach: sess.teach(E0617),
481 });
482 }
483
484 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
487 match arg_ty.kind() {
488 ty::Float(ty::FloatTy::F32) => {
489 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
490 }
491 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
492 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
493 }
494 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
495 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
496 }
497 ty::FnDef(..) => {
498 let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
499 let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
500
501 let fn_item_spa = arg.span;
502 tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
503 span: fn_item_spa,
504 sugg_span: fn_item_spa.shrink_to_hi(),
505 replace: fn_ptr,
506 });
507 }
508 _ => {}
509 }
510 }
511 }
512
513 if !call_appears_satisfied {
514 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
515 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
516 minimum_input_count
517 } else {
518 provided_arg_count
519 }));
520 debug_assert_eq!(
521 formal_input_tys.len(),
522 expected_input_tys.len(),
523 "expected formal_input_tys to be the same size as expected_input_tys"
524 );
525 let formal_and_expected_inputs = IndexVec::from_iter(
526 formal_input_tys
527 .iter()
528 .copied()
529 .zip_eq(expected_input_tys.iter().copied())
530 .map(|vars| self.resolve_vars_if_possible(vars)),
531 );
532
533 self.report_arg_errors(
534 compatibility_diagonal,
535 formal_and_expected_inputs,
536 provided_args,
537 c_variadic,
538 err_code,
539 fn_def_id,
540 call_span,
541 call_expr,
542 tuple_arguments,
543 );
544 }
545 }
546
547 fn report_arg_errors(
548 &self,
549 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
550 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
551 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
552 c_variadic: bool,
553 err_code: ErrCode,
554 fn_def_id: Option<DefId>,
555 call_span: Span,
556 call_expr: &'tcx hir::Expr<'tcx>,
557 tuple_arguments: TupleArgumentsFlag,
558 ) -> ErrorGuaranteed {
559 let (error_span, call_ident, full_call_span, call_name, is_method) = match &call_expr.kind {
561 hir::ExprKind::Call(
562 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
563 _,
564 ) => {
565 if let Res::Def(DefKind::Ctor(of, _), _) =
566 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
567 {
568 let name = match of {
569 CtorOf::Struct => "struct",
570 CtorOf::Variant => "enum variant",
571 };
572 (call_span, None, *span, name, false)
573 } else {
574 (call_span, None, *span, "function", false)
575 }
576 }
577 hir::ExprKind::Call(hir::Expr { span, .. }, _) => {
578 (call_span, None, *span, "function", false)
579 }
580 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
581 let ident_span = path_segment.ident.span;
582 let ident_span = if let Some(args) = path_segment.args {
583 ident_span.with_hi(args.span_ext.hi())
584 } else {
585 ident_span
586 };
587 (*span, Some(path_segment.ident), ident_span, "method", true)
588 }
589 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
590 };
591 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
592
593 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
595 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
596 }
597
598 let tcx = self.tcx;
599
600 let normalize_span = |span: Span| -> Span {
604 let normalized_span = span.find_ancestor_inside_same_ctxt(error_span).unwrap_or(span);
605 if normalized_span.source_equal(error_span) { span } else { normalized_span }
609 };
610
611 let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
613 .iter()
614 .map(|expr| {
615 let ty = self
616 .typeck_results
617 .borrow()
618 .expr_ty_adjusted_opt(*expr)
619 .unwrap_or_else(|| Ty::new_misc_error(tcx));
620 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
621 })
622 .collect();
623 let callee_expr = match &call_expr.peel_blocks().kind {
624 hir::ExprKind::Call(callee, _) => Some(*callee),
625 hir::ExprKind::MethodCall(_, receiver, ..) => {
626 if let Some((DefKind::AssocFn, def_id)) =
627 self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
628 && let Some(assoc) = tcx.opt_associated_item(def_id)
629 && assoc.is_method()
630 {
631 Some(*receiver)
632 } else {
633 None
634 }
635 }
636 _ => None,
637 };
638 let callee_ty = callee_expr
639 .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
640
641 let similar_assoc = |call_name: Ident| -> Option<(ty::AssocItem, ty::FnSig<'_>)> {
643 if let Some(callee_ty) = callee_ty
644 && let Ok(Some(assoc)) = self.probe_op(
645 call_name.span,
646 MethodCall,
647 Some(call_name),
648 None,
649 IsSuggestion(true),
650 callee_ty.peel_refs(),
651 callee_expr.unwrap().hir_id,
652 TraitsInScope,
653 |mut ctxt| ctxt.probe_for_similar_candidate(),
654 )
655 && assoc.is_method()
656 {
657 let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
658 let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
659
660 self.instantiate_binder_with_fresh_vars(call_name.span, FnCall, fn_sig);
661 }
662 None
663 };
664
665 let suggest_confusable = |err: &mut Diag<'_>| {
666 let Some(call_name) = call_ident else {
667 return;
668 };
669 let Some(callee_ty) = callee_ty else {
670 return;
671 };
672 let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
673 if let Some(_name) = self.confusable_method_name(
681 err,
682 callee_ty.peel_refs(),
683 call_name,
684 Some(input_types.clone()),
685 ) {
686 return;
687 }
688 if let Some((assoc, fn_sig)) = similar_assoc(call_name)
690 && fn_sig.inputs()[1..]
691 .iter()
692 .zip(input_types.iter())
693 .all(|(expected, found)| self.may_coerce(*expected, *found))
694 && fn_sig.inputs()[1..].len() == input_types.len()
695 {
696 let assoc_name = assoc.name();
697 err.span_suggestion_verbose(
698 call_name.span,
699 format!("you might have meant to use `{}`", assoc_name),
700 assoc_name,
701 Applicability::MaybeIncorrect,
702 );
703 return;
704 }
705 if let Some(_name) =
707 self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
708 {
709 return;
710 }
711 if let Some((assoc, fn_sig)) = similar_assoc(call_name)
714 && fn_sig.inputs()[1..].len() == input_types.len()
715 {
716 err.span_note(
717 tcx.def_span(assoc.def_id),
718 format!(
719 "there's is a method with similar name `{}`, but the arguments don't match",
720 assoc.name(),
721 ),
722 );
723 return;
724 }
725 if let Some((assoc, _)) = similar_assoc(call_name) {
727 err.span_note(
728 tcx.def_span(assoc.def_id),
729 format!(
730 "there's is a method with similar name `{}`, but their argument count \
731 doesn't match",
732 assoc.name(),
733 ),
734 );
735 return;
736 }
737 };
738 let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
742 if provided_idx.as_usize() == expected_idx.as_usize() {
743 return compatibility_diagonal[provided_idx].clone();
744 }
745
746 let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
747 if (formal_input_ty, expected_input_ty).references_error() {
751 return Compatibility::Incompatible(None);
752 }
753
754 let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
755
756 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
757 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
758 let can_coerce = self.may_coerce(arg_ty, coerced_ty);
759 if !can_coerce {
760 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
761 ty::error::ExpectedFound::new(coerced_ty, arg_ty),
762 )));
763 }
764
765 let subtyping_error = self.probe(|_| {
767 self.at(&self.misc(arg_span), self.param_env)
768 .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
769 .err()
770 });
771
772 let references_error = (coerced_ty, arg_ty).references_error();
775 match (references_error, subtyping_error) {
776 (false, None) => Compatibility::Compatible,
777 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
778 }
779 };
780
781 let mk_trace = |span, (formal_ty, expected_ty), provided_ty| {
782 let mismatched_ty = if expected_ty == provided_ty {
783 formal_ty
787 } else {
788 expected_ty
789 };
790 TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
791 };
792
793 let (mut errors, matched_inputs) =
802 ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
803 .find_errors();
804
805 if let Some((mismatch_idx, terr)) =
807 compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
808 if let Compatibility::Incompatible(Some(terr)) = c {
809 Some((i, *terr))
810 } else {
811 None
812 }
813 })
814 {
815 if let Some(ty::Tuple(tys)) =
819 formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
820 && !tys.is_empty()
822 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
823 {
824 let provided_args_to_tuple = &provided_arg_tys[mismatch_idx..];
826 let (provided_args_to_tuple, provided_args_after_tuple) =
827 provided_args_to_tuple.split_at(tys.len());
828 let provided_as_tuple =
829 Ty::new_tup_from_iter(tcx, provided_args_to_tuple.iter().map(|&(ty, _)| ty));
830
831 let mut satisfied = true;
832 for ((_, expected_ty), provided_ty) in std::iter::zip(
834 formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
835 [provided_as_tuple]
836 .into_iter()
837 .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
838 ) {
839 if !self.may_coerce(provided_ty, *expected_ty) {
840 satisfied = false;
841 break;
842 }
843 }
844
845 if satisfied
849 && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
850 {
851 let mut err;
852 if tys.len() == 1 {
853 err = self.err_ctxt().report_and_explain_type_error(
856 mk_trace(
857 lo,
858 formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
859 provided_arg_tys[mismatch_idx].0,
860 ),
861 self.param_env,
862 terr,
863 );
864 err.span_label(
865 full_call_span,
866 format!("arguments to this {call_name} are incorrect"),
867 );
868 } else {
869 err = self.dcx().struct_span_err(
870 full_call_span,
871 format!(
872 "{call_name} takes {}{} but {} {} supplied",
873 if c_variadic { "at least " } else { "" },
874 potentially_plural_count(
875 formal_and_expected_inputs.len(),
876 "argument"
877 ),
878 potentially_plural_count(provided_args.len(), "argument"),
879 pluralize!("was", provided_args.len())
880 ),
881 );
882 err.code(err_code.to_owned());
883 err.multipart_suggestion_verbose(
884 "wrap these arguments in parentheses to construct a tuple",
885 vec![
886 (lo.shrink_to_lo(), "(".to_string()),
887 (hi.shrink_to_hi(), ")".to_string()),
888 ],
889 Applicability::MachineApplicable,
890 );
891 };
892 self.label_fn_like(
893 &mut err,
894 fn_def_id,
895 callee_ty,
896 call_expr,
897 None,
898 Some(mismatch_idx.as_usize()),
899 &matched_inputs,
900 &formal_and_expected_inputs,
901 is_method,
902 tuple_arguments,
903 );
904 suggest_confusable(&mut err);
905 return err.emit();
906 }
907 }
908 }
909
910 if errors.is_empty() {
926 if cfg!(debug_assertions) {
927 span_bug!(error_span, "expected errors from argument matrix");
928 } else {
929 let mut err =
930 self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
931 suggest_confusable(&mut err);
932 return err.emit();
933 }
934 }
935
936 let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
937 if let ty::Adt(adt, _) = ty.kind()
938 && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
939 && let hir::ExprKind::Struct(
940 hir::QPath::LangItem(hir::LangItem::RangeFull, _),
941 [],
942 _,
943 ) = expr.kind
944 {
945 let explanation = if self.tcx.features().default_field_values() {
948 "this is only supported on non-tuple struct literals"
949 } else if self.tcx.sess.is_nightly_build() {
950 "this is only supported on non-tuple struct literals when \
951 `#![feature(default_field_values)]` is enabled"
952 } else {
953 "this is not supported"
954 };
955 let msg = format!(
956 "you might have meant to use `..` to skip providing a value for \
957 expected fields, but {explanation}; it is instead interpreted as a \
958 `std::ops::RangeFull` literal",
959 );
960 err.span_help(expr.span, msg);
961 }
962 };
963
964 let mut reported = None;
965 errors.retain(|error| {
966 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
967 error
968 else {
969 return true;
970 };
971 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
972 let trace =
973 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
974 if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
975 let mut err =
976 self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e);
977 suggest_confusable(&mut err);
978 reported = Some(err.emit());
979 return false;
980 }
981 true
982 });
983
984 if let Some(reported) = reported
986 && errors.is_empty()
987 {
988 return reported;
989 }
990 assert!(!errors.is_empty());
991
992 if let &[
998 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
999 ] = &errors[..]
1000 {
1001 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
1002 let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
1003 let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
1004 let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
1005 self.emit_coerce_suggestions(
1006 &mut err,
1007 provided_args[provided_idx],
1008 provided_ty,
1009 Expectation::rvalue_hint(self, expected_ty)
1010 .only_has_type(self)
1011 .unwrap_or(formal_ty),
1012 None,
1013 None,
1014 );
1015 err.span_label(full_call_span, format!("arguments to this {call_name} are incorrect"));
1016
1017 self.label_generic_mismatches(
1018 &mut err,
1019 fn_def_id,
1020 &matched_inputs,
1021 &provided_arg_tys,
1022 &formal_and_expected_inputs,
1023 is_method,
1024 );
1025
1026 if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
1027 && provided_idx.as_usize() == expected_idx.as_usize()
1028 {
1029 self.note_source_of_type_mismatch_constraint(
1030 &mut err,
1031 rcvr,
1032 crate::demand::TypeMismatchSource::Arg {
1033 call_expr,
1034 incompatible_arg: provided_idx.as_usize(),
1035 },
1036 );
1037 }
1038
1039 self.suggest_ptr_null_mut(
1040 expected_ty,
1041 provided_ty,
1042 provided_args[provided_idx],
1043 &mut err,
1044 );
1045
1046 self.suggest_deref_unwrap_or(
1047 &mut err,
1048 callee_ty,
1049 call_ident,
1050 expected_ty,
1051 provided_ty,
1052 provided_args[provided_idx],
1053 is_method,
1054 );
1055
1056 self.label_fn_like(
1058 &mut err,
1059 fn_def_id,
1060 callee_ty,
1061 call_expr,
1062 Some(expected_ty),
1063 Some(expected_idx.as_usize()),
1064 &matched_inputs,
1065 &formal_and_expected_inputs,
1066 is_method,
1067 tuple_arguments,
1068 );
1069 suggest_confusable(&mut err);
1070 detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
1071 return err.emit();
1072 }
1073
1074 if let [Error::Extra(provided_idx)] = &errors[..] {
1079 let remove_idx_is_perfect = |idx: usize| -> bool {
1080 let removed_arg_tys = provided_arg_tys
1081 .iter()
1082 .enumerate()
1083 .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
1084 .collect::<IndexVec<ProvidedIdx, _>>();
1085 std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
1086 |((expected_ty, _), (provided_ty, _))| {
1087 !provided_ty.references_error()
1088 && self.may_coerce(*provided_ty, *expected_ty)
1089 },
1090 )
1091 };
1092
1093 if !remove_idx_is_perfect(provided_idx.as_usize()) {
1094 if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) {
1095 errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
1096 }
1097 }
1098 }
1099
1100 let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
1101 struct_span_code_err!(
1102 self.dcx(),
1103 full_call_span,
1104 E0308,
1105 "arguments to this {} are incorrect",
1106 call_name,
1107 )
1108 } else {
1109 self.dcx()
1110 .struct_span_err(
1111 full_call_span,
1112 format!(
1113 "this {} takes {}{} but {} {} supplied",
1114 call_name,
1115 if c_variadic { "at least " } else { "" },
1116 potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
1117 potentially_plural_count(provided_args.len(), "argument"),
1118 pluralize!("was", provided_args.len())
1119 ),
1120 )
1121 .with_code(err_code.to_owned())
1122 };
1123
1124 suggest_confusable(&mut err);
1125 let mut labels = vec![];
1127 enum SuggestionText {
1130 None,
1131 Provide(bool),
1132 Remove(bool),
1133 Swap,
1134 Reorder,
1135 DidYouMean,
1136 }
1137 let mut suggestion_text = SuggestionText::None;
1138
1139 let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
1140 if ty.is_unit() {
1141 "()".to_string()
1142 } else if ty.is_suggestable(tcx, false) {
1143 format!("/* {ty} */")
1144 } else if let Some(fn_def_id) = fn_def_id
1145 && self.tcx.def_kind(fn_def_id).is_fn_like()
1146 && let self_implicit =
1147 matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
1148 && let Some(Some(arg)) =
1149 self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
1150 && arg.name != kw::SelfLower
1151 {
1152 format!("/* {} */", arg.name)
1153 } else {
1154 "/* value */".to_string()
1155 }
1156 };
1157
1158 let mut errors = errors.into_iter().peekable();
1159 let mut only_extras_so_far = errors
1160 .peek()
1161 .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
1162 let mut prev_extra_idx = None;
1163 let mut suggestions = vec![];
1164 while let Some(error) = errors.next() {
1165 only_extras_so_far &= matches!(error, Error::Extra(_));
1166
1167 match error {
1168 Error::Invalid(provided_idx, expected_idx, compatibility) => {
1169 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
1170 let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
1171 if let Compatibility::Incompatible(error) = compatibility {
1172 let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
1173 if let Some(e) = error {
1174 self.err_ctxt().note_type_err(
1175 &mut err,
1176 &trace.cause,
1177 None,
1178 Some(self.param_env.and(trace.values)),
1179 e,
1180 true,
1181 None,
1182 );
1183 }
1184 }
1185
1186 self.emit_coerce_suggestions(
1187 &mut err,
1188 provided_args[provided_idx],
1189 provided_ty,
1190 Expectation::rvalue_hint(self, expected_ty)
1191 .only_has_type(self)
1192 .unwrap_or(formal_ty),
1193 None,
1194 None,
1195 );
1196 detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
1197 }
1198 Error::Extra(arg_idx) => {
1199 let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
1200 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1201 format!(" of type `{provided_ty}`")
1203 } else {
1204 "".to_string()
1205 };
1206 let idx = if provided_arg_tys.len() == 1 {
1207 "".to_string()
1208 } else {
1209 format!(" #{}", arg_idx.as_usize() + 1)
1210 };
1211 labels.push((
1212 provided_span,
1213 format!("unexpected argument{idx}{provided_ty_name}"),
1214 ));
1215 let mut span = provided_span;
1216 if span.can_be_used_for_suggestions()
1217 && error_span.can_be_used_for_suggestions()
1218 {
1219 if arg_idx.index() > 0
1220 && let Some((_, prev)) =
1221 provided_arg_tys.get(ProvidedIdx::from_usize(arg_idx.index() - 1))
1222 {
1223 span = prev.shrink_to_hi().to(span);
1225 }
1226
1227 let trim_next_comma = match errors.peek() {
1234 Some(Error::Extra(provided_idx))
1235 if only_extras_so_far
1236 && provided_idx.index() > arg_idx.index() + 1 =>
1237 {
1245 prev_extra_idx.is_none_or(|prev_extra_idx| {
1246 prev_extra_idx + 1 == arg_idx.index()
1247 })
1248 }
1249 None if only_extras_so_far => true,
1251 _ => false,
1253 };
1254
1255 if trim_next_comma {
1256 let next = provided_arg_tys
1257 .get(arg_idx + 1)
1258 .map(|&(_, sp)| sp)
1259 .unwrap_or_else(|| {
1260 self.tcx().sess.source_map().end_point(call_expr.span)
1265 });
1266
1267 span = span.until(next);
1269 }
1270
1271 suggestions.push((span, String::new()));
1272
1273 suggestion_text = match suggestion_text {
1274 SuggestionText::None => SuggestionText::Remove(false),
1275 SuggestionText::Remove(_) => SuggestionText::Remove(true),
1276 _ => SuggestionText::DidYouMean,
1277 };
1278 prev_extra_idx = Some(arg_idx.index())
1279 }
1280 detect_dotdot(&mut err, provided_ty, provided_args[arg_idx]);
1281 }
1282 Error::Missing(expected_idx) => {
1283 let mut missing_idxs = vec![expected_idx];
1287 while let Some(e) = errors.next_if(|e| {
1288 matches!(e, Error::Missing(next_expected_idx)
1289 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
1290 }) {
1291 match e {
1292 Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
1293 _ => unreachable!(
1294 "control flow ensures that we should always get an `Error::Missing`"
1295 ),
1296 }
1297 }
1298
1299 match &missing_idxs[..] {
1304 &[expected_idx] => {
1305 let (_, input_ty) = formal_and_expected_inputs[expected_idx];
1306 let span = if let Some((_, arg_span)) =
1307 provided_arg_tys.get(expected_idx.to_provided_idx())
1308 {
1309 *arg_span
1310 } else {
1311 args_span
1312 };
1313 let rendered = if !has_error_or_infer([input_ty]) {
1314 format!(" of type `{input_ty}`")
1315 } else {
1316 "".to_string()
1317 };
1318 labels.push((
1319 span,
1320 format!(
1321 "argument #{}{rendered} is missing",
1322 expected_idx.as_usize() + 1
1323 ),
1324 ));
1325
1326 suggestion_text = match suggestion_text {
1327 SuggestionText::None => SuggestionText::Provide(false),
1328 SuggestionText::Provide(_) => SuggestionText::Provide(true),
1329 _ => SuggestionText::DidYouMean,
1330 };
1331 }
1332 &[first_idx, second_idx] => {
1333 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
1334 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
1335 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
1336 provided_arg_tys.get(first_idx.to_provided_idx()),
1337 provided_arg_tys.get(second_idx.to_provided_idx()),
1338 ) {
1339 first_span.to(*second_span)
1340 } else {
1341 args_span
1342 };
1343 let rendered =
1344 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
1345 format!(
1346 " of type `{first_expected_ty}` and `{second_expected_ty}`"
1347 )
1348 } else {
1349 "".to_string()
1350 };
1351 labels.push((span, format!("two arguments{rendered} are missing")));
1352 suggestion_text = match suggestion_text {
1353 SuggestionText::None | SuggestionText::Provide(_) => {
1354 SuggestionText::Provide(true)
1355 }
1356 _ => SuggestionText::DidYouMean,
1357 };
1358 }
1359 &[first_idx, second_idx, third_idx] => {
1360 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
1361 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
1362 let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
1363 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
1364 provided_arg_tys.get(first_idx.to_provided_idx()),
1365 provided_arg_tys.get(third_idx.to_provided_idx()),
1366 ) {
1367 first_span.to(*third_span)
1368 } else {
1369 args_span
1370 };
1371 let rendered = if !has_error_or_infer([
1372 first_expected_ty,
1373 second_expected_ty,
1374 third_expected_ty,
1375 ]) {
1376 format!(
1377 " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
1378 )
1379 } else {
1380 "".to_string()
1381 };
1382 labels.push((span, format!("three arguments{rendered} are missing")));
1383 suggestion_text = match suggestion_text {
1384 SuggestionText::None | SuggestionText::Provide(_) => {
1385 SuggestionText::Provide(true)
1386 }
1387 _ => SuggestionText::DidYouMean,
1388 };
1389 }
1390 missing_idxs => {
1391 let first_idx = *missing_idxs.first().unwrap();
1392 let last_idx = *missing_idxs.last().unwrap();
1393 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
1397 provided_arg_tys.get(first_idx.to_provided_idx()),
1398 provided_arg_tys.get(last_idx.to_provided_idx()),
1399 ) {
1400 first_span.to(*last_span)
1401 } else {
1402 args_span
1403 };
1404 labels.push((span, "multiple arguments are missing".to_string()));
1405 suggestion_text = match suggestion_text {
1406 SuggestionText::None | SuggestionText::Provide(_) => {
1407 SuggestionText::Provide(true)
1408 }
1409 _ => SuggestionText::DidYouMean,
1410 };
1411 }
1412 }
1413 }
1414 Error::Swap(
1415 first_provided_idx,
1416 second_provided_idx,
1417 first_expected_idx,
1418 second_expected_idx,
1419 ) => {
1420 let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
1421 let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
1422 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
1423 format!(", found `{first_provided_ty}`")
1424 } else {
1425 String::new()
1426 };
1427 labels.push((
1428 first_span,
1429 format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
1430 ));
1431
1432 let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
1433 let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
1434 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
1435 format!(", found `{second_provided_ty}`")
1436 } else {
1437 String::new()
1438 };
1439 labels.push((
1440 second_span,
1441 format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
1442 ));
1443
1444 suggestion_text = match suggestion_text {
1445 SuggestionText::None => SuggestionText::Swap,
1446 _ => SuggestionText::DidYouMean,
1447 };
1448 }
1449 Error::Permutation(args) => {
1450 for (dst_arg, dest_input) in args {
1451 let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
1452 let (provided_ty, provided_span) = provided_arg_tys[dest_input];
1453 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1454 format!(", found `{provided_ty}`")
1455 } else {
1456 String::new()
1457 };
1458 labels.push((
1459 provided_span,
1460 format!("expected `{expected_ty}`{provided_ty_name}"),
1461 ));
1462 }
1463
1464 suggestion_text = match suggestion_text {
1465 SuggestionText::None => SuggestionText::Reorder,
1466 _ => SuggestionText::DidYouMean,
1467 };
1468 }
1469 }
1470 }
1471
1472 self.label_generic_mismatches(
1473 &mut err,
1474 fn_def_id,
1475 &matched_inputs,
1476 &provided_arg_tys,
1477 &formal_and_expected_inputs,
1478 is_method,
1479 );
1480
1481 let mut prev = -1;
1501 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1502 if let Some(provided_idx) = provided_idx {
1505 prev = provided_idx.index() as i64;
1506 continue;
1507 }
1508 let idx = ProvidedIdx::from_usize((prev + 1) as usize);
1509 if let Some((_, arg_span)) = provided_arg_tys.get(idx) {
1510 prev += 1;
1511 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1516 suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
1517 }
1518 }
1519
1520 if labels.len() <= 5 {
1522 for (span, label) in labels {
1523 err.span_label(span, label);
1524 }
1525 }
1526
1527 self.label_fn_like(
1529 &mut err,
1530 fn_def_id,
1531 callee_ty,
1532 call_expr,
1533 None,
1534 None,
1535 &matched_inputs,
1536 &formal_and_expected_inputs,
1537 is_method,
1538 tuple_arguments,
1539 );
1540
1541 let suggestion_text = match suggestion_text {
1543 SuggestionText::None => None,
1544 SuggestionText::Provide(plural) => {
1545 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
1546 }
1547 SuggestionText::Remove(plural) => {
1548 err.multipart_suggestion_verbose(
1549 format!("remove the extra argument{}", if plural { "s" } else { "" }),
1550 suggestions,
1551 Applicability::HasPlaceholders,
1552 );
1553 None
1554 }
1555 SuggestionText::Swap => Some("swap these arguments".to_string()),
1556 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
1557 SuggestionText::DidYouMean => Some("did you mean".to_string()),
1558 };
1559 if let Some(suggestion_text) = suggestion_text
1560 && !full_call_span.in_external_macro(self.sess().source_map())
1561 {
1562 let source_map = self.sess().source_map();
1563 let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) {
1564 args_span
1566 } else {
1567 full_call_span.shrink_to_hi()
1571 };
1572 let mut suggestion = "(".to_owned();
1573 let mut needs_comma = false;
1574 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1575 if needs_comma {
1576 suggestion += ", ";
1577 } else {
1578 needs_comma = true;
1579 }
1580 let suggestion_text = if let Some(provided_idx) = provided_idx
1581 && let (_, provided_span) = provided_arg_tys[*provided_idx]
1582 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
1583 {
1584 arg_text
1585 } else {
1586 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1588 ty_to_snippet(expected_ty, expected_idx)
1589 };
1590 suggestion += &suggestion_text;
1591 }
1592 suggestion += ")";
1593 err.span_suggestion_verbose(
1594 suggestion_span,
1595 suggestion_text,
1596 suggestion,
1597 Applicability::HasPlaceholders,
1598 );
1599 }
1600
1601 err.emit()
1602 }
1603
1604 fn suggest_ptr_null_mut(
1605 &self,
1606 expected_ty: Ty<'tcx>,
1607 provided_ty: Ty<'tcx>,
1608 arg: &hir::Expr<'tcx>,
1609 err: &mut Diag<'_>,
1610 ) {
1611 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
1612 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
1613 && let hir::ExprKind::Call(callee, _) = arg.kind
1614 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
1615 && let Res::Def(_, def_id) = path.res
1616 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
1617 {
1618 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
1621 }
1622 }
1623
1624 pub(in super::super) fn check_expr_lit(
1626 &self,
1627 lit: &hir::Lit,
1628 expected: Expectation<'tcx>,
1629 ) -> Ty<'tcx> {
1630 let tcx = self.tcx;
1631
1632 match lit.node {
1633 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
1634 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
1635 tcx,
1636 tcx.lifetimes.re_static,
1637 Ty::new_array(tcx, tcx.types.u8, v.len() as u64),
1638 ),
1639 ast::LitKind::Byte(_) => tcx.types.u8,
1640 ast::LitKind::Char(_) => tcx.types.char,
1641 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)),
1642 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)),
1643 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
1644 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1645 ty::Int(_) | ty::Uint(_) => Some(ty),
1646 ty::Char => Some(tcx.types.u8),
1650 ty::RawPtr(..) => Some(tcx.types.usize),
1651 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1652 &ty::Pat(base, _) if base.is_integral() => {
1653 let layout = tcx
1654 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1655 .ok()?;
1656 assert!(!layout.uninhabited);
1657
1658 match layout.backend_repr {
1659 rustc_abi::BackendRepr::Scalar(scalar) => {
1660 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1661 }
1662 _ => unreachable!(),
1663 }
1664 }
1665 _ => None,
1666 });
1667 opt_ty.unwrap_or_else(|| self.next_int_var())
1668 }
1669 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
1670 Ty::new_float(tcx, ty::float_ty(t))
1671 }
1672 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1673 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1674 ty::Float(_) => Some(ty),
1675 _ => None,
1676 });
1677 opt_ty.unwrap_or_else(|| self.next_float_var())
1678 }
1679 ast::LitKind::Bool(_) => tcx.types.bool,
1680 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1681 tcx,
1682 tcx.lifetimes.re_static,
1683 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span)))
1684 .skip_binder(),
1685 ),
1686 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1687 }
1688 }
1689
1690 pub(crate) fn check_struct_path(
1691 &self,
1692 qpath: &QPath<'tcx>,
1693 hir_id: HirId,
1694 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1695 let path_span = qpath.span();
1696 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1697 let variant = match def {
1698 Res::Err => {
1699 let guar =
1700 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1701 self.set_tainted_by_errors(guar);
1702 return Err(guar);
1703 }
1704 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1705 Some(adt) => {
1706 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1707 }
1708 _ => bug!("unexpected type: {:?}", ty.normalized),
1709 },
1710 Res::Def(
1711 DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
1712 _,
1713 )
1714 | Res::SelfTyParam { .. }
1715 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1716 Some(adt) if !adt.is_enum() => {
1717 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1718 }
1719 _ => None,
1720 },
1721 _ => bug!("unexpected definition: {:?}", def),
1722 };
1723
1724 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1725 debug!("check_struct_path: did={:?} args={:?}", did, args);
1726
1727 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1729
1730 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1732
1733 Ok((variant, ty.normalized))
1734 } else {
1735 Err(match *ty.normalized.kind() {
1736 ty::Error(guar) => {
1737 guar
1742 }
1743 _ => struct_span_code_err!(
1744 self.dcx(),
1745 path_span,
1746 E0071,
1747 "expected struct, variant or union type, found {}",
1748 ty.normalized.sort_string(self.tcx)
1749 )
1750 .with_span_label(path_span, "not a struct")
1751 .emit(),
1752 })
1753 }
1754 }
1755
1756 fn check_decl_initializer(
1757 &self,
1758 hir_id: HirId,
1759 pat: &'tcx hir::Pat<'tcx>,
1760 init: &'tcx hir::Expr<'tcx>,
1761 ) -> Ty<'tcx> {
1762 let ref_bindings = pat.contains_explicit_ref_binding();
1767
1768 let local_ty = self.local_ty(init.span, hir_id);
1769 if let Some(m) = ref_bindings {
1770 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1779 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1780 self.emit_type_mismatch_suggestions(
1781 &mut diag,
1782 init.peel_drop_temps(),
1783 init_ty,
1784 local_ty,
1785 None,
1786 None,
1787 );
1788 diag.emit();
1789 }
1790 init_ty
1791 } else {
1792 self.check_expr_coercible_to_type(init, local_ty, None)
1793 }
1794 }
1795
1796 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1797 let decl_ty = self.local_ty(decl.span, decl.hir_id);
1799
1800 if let Some(ref init) = decl.init {
1802 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1803 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1804 }
1805
1806 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1808 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
1810 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1811 } _ => (None, None), };
1814
1815 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1817 let pat_ty = self.node_ty(decl.pat.hir_id);
1818 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1819
1820 if let Some(blk) = decl.origin.try_get_else() {
1821 let previous_diverges = self.diverges.get();
1822 let else_ty = self.check_expr_block(blk, NoExpectation);
1823 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1824 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1825 {
1826 err.emit();
1827 }
1828 self.diverges.set(previous_diverges);
1829 }
1830 decl_ty
1831 }
1832
1833 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1835 GatherLocalsVisitor::gather_from_local(self, local);
1836
1837 let ty = self.check_decl(local.into());
1838 self.write_ty(local.hir_id, ty);
1839 if local.pat.is_never_pattern() {
1840 self.diverges.set(Diverges::Always {
1841 span: local.pat.span,
1842 custom_note: Some("any code following a never pattern is unreachable"),
1843 });
1844 }
1845 }
1846
1847 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1848 match stmt.kind {
1850 hir::StmtKind::Item(..) => return,
1851 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1852 }
1853
1854 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1855
1856 let old_diverges = self.diverges.replace(Diverges::Maybe);
1858
1859 match stmt.kind {
1860 hir::StmtKind::Let(l) => {
1861 self.check_decl_local(l);
1862 }
1863 hir::StmtKind::Item(_) => {}
1865 hir::StmtKind::Expr(ref expr) => {
1866 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1868 if expr.can_have_side_effects() {
1869 self.suggest_semicolon_at_end(expr.span, err);
1870 }
1871 });
1872 }
1873 hir::StmtKind::Semi(expr) => {
1874 self.check_expr(expr);
1875 }
1876 }
1877
1878 self.diverges.set(self.diverges.get() | old_diverges);
1880 }
1881
1882 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1883 let unit = self.tcx.types.unit;
1884 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1885
1886 if !ty.is_never() {
1889 self.demand_suptype(blk.span, unit, ty);
1890 }
1891 }
1892
1893 pub(in super::super) fn check_expr_block(
1894 &self,
1895 blk: &'tcx hir::Block<'tcx>,
1896 expected: Expectation<'tcx>,
1897 ) -> Ty<'tcx> {
1898 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1915 let coerce = if blk.targeted_by_break {
1916 CoerceMany::new(coerce_to_ty)
1917 } else {
1918 CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
1919 };
1920
1921 let prev_diverges = self.diverges.get();
1922 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1923
1924 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1925 for s in blk.stmts {
1926 self.check_stmt(s);
1927 }
1928
1929 let tail_expr_ty =
1932 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1933
1934 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1935 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1936 let coerce = ctxt.coerce.as_mut().unwrap();
1937 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1938 let span = self.get_expr_coercion_span(tail_expr);
1939 let cause = self.cause(
1940 span,
1941 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1942 );
1943 let ty_for_diagnostic = coerce.merged_ty();
1944 coerce.coerce_inner(
1948 self,
1949 &cause,
1950 Some(tail_expr),
1951 tail_expr_ty,
1952 |diag| {
1953 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1954 },
1955 false,
1956 );
1957 } else {
1958 if !self.diverges.get().is_always()
1969 || matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1970 {
1971 let mut sp = blk.span;
1977 let mut fn_span = None;
1978 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1979 let ret_sp = decl.output.span();
1980 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1981 if block_sp == blk.span {
1985 sp = ret_sp;
1986 fn_span = self.tcx.def_ident_span(fn_def_id);
1987 }
1988 }
1989 }
1990 coerce.coerce_forced_unit(
1991 self,
1992 &self.misc(sp),
1993 |err| {
1994 if let Some(expected_ty) = expected.only_has_type(self) {
1995 if blk.stmts.is_empty() && blk.expr.is_none() {
1996 self.suggest_boxing_when_appropriate(
1997 err,
1998 blk.span,
1999 blk.hir_id,
2000 expected_ty,
2001 self.tcx.types.unit,
2002 );
2003 }
2004 if !self.err_ctxt().consider_removing_semicolon(
2005 blk,
2006 expected_ty,
2007 err,
2008 ) {
2009 self.err_ctxt().consider_returning_binding(
2010 blk,
2011 expected_ty,
2012 err,
2013 );
2014 }
2015 if expected_ty == self.tcx.types.bool {
2016 if let hir::Block {
2021 stmts:
2022 [
2023 hir::Stmt {
2024 kind:
2025 hir::StmtKind::Let(hir::LetStmt {
2026 source:
2027 hir::LocalSource::AssignDesugar(_),
2028 ..
2029 }),
2030 ..
2031 },
2032 hir::Stmt {
2033 kind:
2034 hir::StmtKind::Expr(hir::Expr {
2035 kind: hir::ExprKind::Assign(lhs, ..),
2036 ..
2037 }),
2038 ..
2039 },
2040 ],
2041 ..
2042 } = blk
2043 {
2044 self.comes_from_while_condition(blk.hir_id, |_| {
2045 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
2049
2050 if !lhs.is_syntactic_place_expr()
2051 || res.references_error()
2052 {
2053 err.downgrade_to_delayed_bug();
2054 }
2055 })
2056 }
2057 }
2058 }
2059 if let Some(fn_span) = fn_span {
2060 err.span_label(
2061 fn_span,
2062 "implicitly returns `()` as its body has no tail or `return` \
2063 expression",
2064 );
2065 }
2066 },
2067 false,
2068 );
2069 }
2070 }
2071 });
2072
2073 if ctxt.may_break {
2074 self.diverges.set(prev_diverges);
2077 }
2078
2079 let ty = ctxt.coerce.unwrap().complete(self);
2080
2081 self.write_ty(blk.hir_id, ty);
2082
2083 ty
2084 }
2085
2086 fn parent_item_span(&self, id: HirId) -> Option<Span> {
2087 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
2088 match node {
2089 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
2090 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
2091 let body = self.tcx.hir_body(body_id);
2092 if let ExprKind::Block(block, _) = &body.value.kind {
2093 return Some(block.span);
2094 }
2095 }
2096 _ => {}
2097 }
2098 None
2099 }
2100
2101 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
2109 let check_in_progress = |elem: &hir::Expr<'_>| {
2110 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
2111 |_| match elem.kind {
2112 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
2114 _ => elem.span,
2115 },
2116 )
2117 };
2118
2119 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
2120 if let Some(rslt) = check_in_progress(el) {
2121 return rslt;
2122 }
2123 }
2124
2125 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
2126 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
2127 if let Some(span) = iter.next() {
2128 if iter.next().is_none() {
2129 return span;
2130 }
2131 }
2132 }
2133
2134 expr.span
2135 }
2136
2137 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
2138 if let Err(guar) = ty.error_reported() {
2139 struct OverwritePatternsWithError {
2140 pat_hir_ids: Vec<hir::HirId>,
2141 }
2142 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
2143 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
2144 self.pat_hir_ids.push(p.hir_id);
2145 hir::intravisit::walk_pat(self, p);
2146 }
2147 }
2148 let err = Ty::new_error(self.tcx, guar);
2150 self.write_ty(hir_id, err);
2151 self.write_ty(pat.hir_id, err);
2152 let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
2153 hir::intravisit::walk_pat(&mut visitor, pat);
2154 for hir_id in visitor.pat_hir_ids {
2157 self.write_ty(hir_id, err);
2158 }
2159 self.locals.borrow_mut().insert(hir_id, err);
2160 self.locals.borrow_mut().insert(pat.hir_id, err);
2161 }
2162 }
2163
2164 fn finish_resolving_struct_path(
2167 &self,
2168 qpath: &QPath<'tcx>,
2169 path_span: Span,
2170 hir_id: HirId,
2171 ) -> (Res, LoweredTy<'tcx>) {
2172 match *qpath {
2173 QPath::Resolved(ref maybe_qself, path) => {
2174 let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
2175 let ty = self.lowerer().lower_resolved_ty_path(
2176 self_ty,
2177 path,
2178 hir_id,
2179 PermitVariants::Yes,
2180 );
2181 (path.res, LoweredTy::from_raw(self, path_span, ty))
2182 }
2183 QPath::TypeRelative(hir_self_ty, segment) => {
2184 let self_ty = self.lower_ty(hir_self_ty);
2185
2186 let result = self.lowerer().lower_type_relative_ty_path(
2187 self_ty.raw,
2188 hir_self_ty,
2189 segment,
2190 hir_id,
2191 path_span,
2192 PermitVariants::Yes,
2193 );
2194 let ty = result
2195 .map(|(ty, _, _)| ty)
2196 .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
2197 let ty = LoweredTy::from_raw(self, path_span, ty);
2198 let result = result.map(|(_, kind, def_id)| (kind, def_id));
2199
2200 self.write_resolution(hir_id, result);
2202
2203 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
2204 }
2205 QPath::LangItem(lang_item, span) => {
2206 let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
2207 (res, LoweredTy::from_raw(self, path_span, ty))
2208 }
2209 }
2210 }
2211
2212 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
2219 &self,
2220 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
2221 ) {
2222 let mut remap_cause = FxIndexSet::default();
2228 let mut not_adjusted = vec![];
2229
2230 for error in errors {
2231 let before_span = error.obligation.cause.span;
2232 if self.adjust_fulfillment_error_for_expr_obligation(error)
2233 || before_span != error.obligation.cause.span
2234 {
2235 remap_cause.insert((
2236 before_span,
2237 error.obligation.predicate,
2238 error.obligation.cause.clone(),
2239 ));
2240 } else {
2241 not_adjusted.push(error);
2244 }
2245 }
2246
2247 for error in not_adjusted {
2255 for (span, predicate, cause) in &remap_cause {
2256 if *predicate == error.obligation.predicate
2257 && span.contains(error.obligation.cause.span)
2258 {
2259 error.obligation.cause = cause.clone();
2260 continue;
2261 }
2262 }
2263 }
2264 }
2265
2266 fn label_fn_like(
2267 &self,
2268 err: &mut Diag<'_>,
2269 callable_def_id: Option<DefId>,
2270 callee_ty: Option<Ty<'tcx>>,
2271 call_expr: &'tcx hir::Expr<'tcx>,
2272 expected_ty: Option<Ty<'tcx>>,
2273 expected_idx: Option<usize>,
2275 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2276 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2277 is_method: bool,
2278 tuple_arguments: TupleArgumentsFlag,
2279 ) {
2280 let Some(mut def_id) = callable_def_id else {
2281 return;
2282 };
2283
2284 if tuple_arguments == TupleArguments
2289 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
2290 && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
2295 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
2296 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
2298 && let Some(callee_ty) = callee_ty
2299 {
2300 let callee_ty = callee_ty.peel_refs();
2301 match *callee_ty.kind() {
2302 ty::Param(param) => {
2303 let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
2304 if param.kind.is_synthetic() {
2305 def_id = param.def_id;
2307 } else {
2308 let instantiated = self
2311 .tcx
2312 .explicit_predicates_of(self.body_id)
2313 .instantiate_identity(self.tcx);
2314 for (predicate, span) in instantiated {
2318 if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder()
2319 && pred.self_ty().peel_refs() == callee_ty
2320 && self.tcx.is_fn_trait(pred.def_id())
2321 {
2322 err.span_note(span, "callable defined here");
2323 return;
2324 }
2325 }
2326 }
2327 }
2328 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
2329 | ty::Closure(new_def_id, _)
2330 | ty::FnDef(new_def_id, _) => {
2331 def_id = new_def_id;
2332 }
2333 _ => {
2334 let new_def_id = self.probe(|_| {
2336 let trait_ref = ty::TraitRef::new(
2337 self.tcx,
2338 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
2339 [callee_ty, self.next_ty_var(DUMMY_SP)],
2340 );
2341 let obligation = traits::Obligation::new(
2342 self.tcx,
2343 traits::ObligationCause::dummy(),
2344 self.param_env,
2345 trait_ref,
2346 );
2347 match SelectionContext::new(self).select(&obligation) {
2348 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
2349 Some(impl_source.impl_def_id)
2350 }
2351 _ => None,
2352 }
2353 });
2354 if let Some(new_def_id) = new_def_id {
2355 def_id = new_def_id;
2356 } else {
2357 return;
2358 }
2359 }
2360 }
2361 }
2362
2363 if let Some(def_span) = self.tcx.def_ident_span(def_id)
2364 && !def_span.is_dummy()
2365 {
2366 let mut spans: MultiSpan = def_span.into();
2367 if let Some((params_with_generics, hir_generics)) =
2368 self.get_hir_param_info(def_id, is_method)
2369 {
2370 struct MismatchedParam<'a> {
2371 idx: ExpectedIdx,
2372 generic: GenericIdx,
2373 param: &'a FnParam<'a>,
2374 deps: SmallVec<[ExpectedIdx; 4]>,
2375 }
2376
2377 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2378 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
2380 if let Some(expected_idx) = expected_idx {
2381 let expected_idx = ExpectedIdx::from_usize(expected_idx);
2382 let &(expected_generic, ref expected_param) =
2383 ¶ms_with_generics[expected_idx];
2384 if let Some(expected_generic) = expected_generic {
2385 mismatched_params.push(MismatchedParam {
2386 idx: expected_idx,
2387 generic: expected_generic,
2388 param: expected_param,
2389 deps: SmallVec::new(),
2390 });
2391 } else {
2392 spans.push_span_label(expected_param.span(), "");
2394 }
2395 } else {
2396 mismatched_params.extend(
2397 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
2398 |((idx, &(generic, ref param)), matched_idx)| {
2399 if matched_idx.is_some() {
2400 None
2401 } else if let Some(generic) = generic {
2402 Some(MismatchedParam {
2403 idx,
2404 generic,
2405 param,
2406 deps: SmallVec::new(),
2407 })
2408 } else {
2409 spans.push_span_label(param.span(), "");
2411 None
2412 }
2413 },
2414 ),
2415 );
2416 }
2417
2418 if !mismatched_params.is_empty() {
2419 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
2422 |_| SmallVec::<[u32; 4]>::new(),
2423 params_with_generics.len(),
2424 );
2425 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
2426 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
2427 hir_generics.params.len(),
2428 );
2429 for (idx, param) in mismatched_params.iter_mut().enumerate() {
2430 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
2431 params_with_generics.iter_enumerated().zip(matched_inputs)
2432 {
2433 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
2434 generic_uses[param.generic].extend([param.idx, other_idx]);
2435 dependants[other_idx].push(idx as u32);
2436 param.deps.push(other_idx);
2437 }
2438 }
2439 }
2440
2441 for param in &mismatched_params {
2444 if let Some(deps_list) = listify(¶m.deps, |&dep| {
2445 params_with_generics[dep].1.display(dep.as_usize()).to_string()
2446 }) {
2447 spans.push_span_label(
2448 param.param.span(),
2449 format!(
2450 "this parameter needs to match the {} type of {deps_list}",
2451 self.resolve_vars_if_possible(
2452 formal_and_expected_inputs[param.deps[0]].1
2453 )
2454 .sort_string(self.tcx),
2455 ),
2456 );
2457 } else {
2458 spans.push_span_label(param.param.span(), "");
2460 }
2461 }
2462 for ((&(_, param), deps), &(_, expected_ty)) in
2464 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
2465 {
2466 if let Some(deps_list) = listify(deps, |&dep| {
2467 let param = &mismatched_params[dep as usize];
2468 param.param.display(param.idx.as_usize()).to_string()
2469 }) {
2470 spans.push_span_label(
2471 param.span(),
2472 format!(
2473 "{deps_list} need{} to match the {} type of this parameter",
2474 pluralize!((deps.len() != 1) as u32),
2475 self.resolve_vars_if_possible(expected_ty)
2476 .sort_string(self.tcx),
2477 ),
2478 );
2479 }
2480 }
2481 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
2483 uses.sort();
2484 uses.dedup();
2485 if let Some(param_list) = listify(uses, |&idx| {
2486 params_with_generics[idx].1.display(idx.as_usize()).to_string()
2487 }) {
2488 spans.push_span_label(
2489 param.span,
2490 format!(
2491 "{param_list} {} reference this parameter `{}`",
2492 if uses.len() == 2 { "both" } else { "all" },
2493 param.name.ident().name,
2494 ),
2495 );
2496 }
2497 }
2498 }
2499 }
2500 err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
2501 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
2502 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
2503 {
2504 let param = expected_idx
2505 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
2506 let (kind, span) = if let Some(param) = param {
2507 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] };
2510 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
2511 match self.tcx.hir_node_by_def_id(parent_def_id) {
2512 hir::Node::Item(item) => call_finder.visit_item(item),
2513 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
2514 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
2515 _ => {}
2516 }
2517 let typeck = self.typeck_results.borrow();
2518 for (rcvr, args) in call_finder.calls {
2519 if rcvr.hir_id.owner == typeck.hir_owner
2520 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
2521 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
2522 && def_id == *call_def_id
2523 && let Some(idx) = expected_idx
2524 && let Some(arg) = args.get(idx)
2525 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
2526 && let Some(expected_ty) = expected_ty
2527 && self.can_eq(self.param_env, arg_ty, expected_ty)
2528 {
2529 let mut sp: MultiSpan = vec![arg.span].into();
2530 sp.push_span_label(
2531 arg.span,
2532 format!("expected because this argument is of type `{arg_ty}`"),
2533 );
2534 sp.push_span_label(rcvr.span, "in this closure call");
2535 err.span_note(
2536 sp,
2537 format!(
2538 "expected because the closure was earlier called with an \
2539 argument of type `{arg_ty}`",
2540 ),
2541 );
2542 break;
2543 }
2544 }
2545
2546 ("closure parameter", param.span)
2547 } else {
2548 ("closure", self.tcx.def_span(def_id))
2549 };
2550 err.span_note(span, format!("{kind} defined here"));
2551 } else {
2552 err.span_note(
2553 self.tcx.def_span(def_id),
2554 format!("{} defined here", self.tcx.def_descr(def_id)),
2555 );
2556 }
2557 }
2558
2559 fn label_generic_mismatches(
2560 &self,
2561 err: &mut Diag<'_>,
2562 callable_def_id: Option<DefId>,
2563 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2564 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
2565 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2566 is_method: bool,
2567 ) {
2568 let Some(def_id) = callable_def_id else {
2569 return;
2570 };
2571
2572 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
2573 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2574 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
2575 if matched_inputs[idx].is_none() {
2576 continue;
2577 }
2578
2579 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
2580 else {
2581 continue;
2582 };
2583
2584 let Some(generic_param) = generic_param else {
2585 continue;
2586 };
2587
2588 let idxs_matched = params_with_generics
2589 .iter_enumerated()
2590 .filter(|&(other_idx, (other_generic_param, _))| {
2591 if other_idx == idx {
2592 return false;
2593 }
2594 let Some(other_generic_param) = other_generic_param else {
2595 return false;
2596 };
2597 if matched_inputs[other_idx].is_some() {
2598 return false;
2599 }
2600 other_generic_param == generic_param
2601 })
2602 .count();
2603
2604 if idxs_matched == 0 {
2605 continue;
2606 }
2607
2608 let expected_display_type = self
2609 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
2610 .sort_string(self.tcx);
2611 let label = if idxs_matched == params_with_generics.len() - 1 {
2612 format!(
2613 "expected all arguments to be this {} type because they need to match the type of this parameter",
2614 expected_display_type
2615 )
2616 } else {
2617 format!(
2618 "expected some other arguments to be {} {} type to match the type of this parameter",
2619 a_or_an(&expected_display_type),
2620 expected_display_type,
2621 )
2622 };
2623
2624 err.span_label(*matched_arg_span, label);
2625 }
2626 }
2627 }
2628
2629 fn get_hir_param_info(
2634 &self,
2635 def_id: DefId,
2636 is_method: bool,
2637 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2638 {
2639 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2640 hir::Node::TraitItem(&hir::TraitItem {
2641 generics,
2642 kind: hir::TraitItemKind::Fn(sig, trait_fn),
2643 ..
2644 }) => match trait_fn {
2645 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2646 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2647 },
2648 hir::Node::ImplItem(&hir::ImplItem {
2649 generics,
2650 kind: hir::ImplItemKind::Fn(sig, body),
2651 ..
2652 })
2653 | hir::Node::Item(&hir::Item {
2654 kind: hir::ItemKind::Fn { sig, generics, body, .. },
2655 ..
2656 }) => (sig, generics, Some(body), None),
2657 hir::Node::ForeignItem(&hir::ForeignItem {
2658 kind: hir::ForeignItemKind::Fn(sig, params, generics),
2659 ..
2660 }) => (sig, generics, None, Some(params)),
2661 _ => return None,
2662 };
2663
2664 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2667 if let hir::TyKind::Path(QPath::Resolved(
2668 _,
2669 &hir::Path { res: Res::Def(_, res_def_id), .. },
2670 )) = param.kind
2671 {
2672 generics
2673 .params
2674 .iter()
2675 .position(|param| param.def_id.to_def_id() == res_def_id)
2676 .map(GenericIdx::from_usize)
2677 } else {
2678 None
2679 }
2680 });
2681 match (body_id, params) {
2682 (Some(_), Some(_)) | (None, None) => unreachable!(),
2683 (Some(body), None) => {
2684 let params = self.tcx.hir_body(body).params;
2685 let params =
2686 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2687 debug_assert_eq!(params.len(), fn_inputs.len());
2688 Some((
2689 fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect(),
2690 generics,
2691 ))
2692 }
2693 (None, Some(params)) => {
2694 let params =
2695 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2696 debug_assert_eq!(params.len(), fn_inputs.len());
2697 Some((
2698 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2699 generics,
2700 ))
2701 }
2702 }
2703 }
2704}
2705
2706struct FindClosureArg<'tcx> {
2707 tcx: TyCtxt<'tcx>,
2708 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2709}
2710
2711impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2712 type NestedFilter = rustc_middle::hir::nested_filter::All;
2713
2714 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2715 self.tcx
2716 }
2717
2718 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2719 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2720 self.calls.push((rcvr, args));
2721 }
2722 hir::intravisit::walk_expr(self, ex);
2723 }
2724}
2725
2726#[derive(Clone, Copy)]
2727enum FnParam<'hir> {
2728 Param(&'hir hir::Param<'hir>),
2729 Ident(Option<Ident>),
2730}
2731
2732impl FnParam<'_> {
2733 fn span(&self) -> Span {
2734 match self {
2735 Self::Param(param) => param.span,
2736 Self::Ident(ident) => {
2737 if let Some(ident) = ident {
2738 ident.span
2739 } else {
2740 DUMMY_SP
2741 }
2742 }
2743 }
2744 }
2745
2746 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2747 struct D<'a>(FnParam<'a>, usize);
2748 impl fmt::Display for D<'_> {
2749 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2750 let unique_name = match self.0 {
2753 FnParam::Param(param)
2754 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2755 {
2756 Some(ident.name)
2757 }
2758 FnParam::Ident(ident)
2759 if let Some(ident) = ident
2760 && ident.name != kw::Underscore =>
2761 {
2762 Some(ident.name)
2763 }
2764 _ => None,
2765 };
2766 if let Some(unique_name) = unique_name {
2767 write!(f, "`{unique_name}`")
2768 } else {
2769 write!(f, "parameter #{}", self.1 + 1)
2770 }
2771 }
2772 }
2773 D(*self, idx)
2774 }
2775}