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::{BoundRegionConversionTime, 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::gather_locals::Declaration;
34use crate::inline_asm::InlineAsmCtxt;
35use crate::method::probe::IsSuggestion;
36use crate::method::probe::Mode::MethodCall;
37use crate::method::probe::ProbeScope::TraitsInScope;
38use crate::{
39 BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
40 TupleArgumentsFlag, errors, struct_span_code_err,
41};
42
43rustc_index::newtype_index! {
44 #[orderable]
45 #[debug_format = "GenericIdx({})"]
46 pub(crate) struct GenericIdx {}
47}
48
49#[derive(Clone, Copy, Default)]
50pub(crate) enum DivergingBlockBehavior {
51 #[default]
59 Never,
60
61 Unit,
70}
71
72impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
73 pub(in super::super) fn check_casts(&mut self) {
74 let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
77
78 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
79 for cast in deferred_cast_checks.drain(..) {
80 cast.check(self);
81 }
82
83 *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
84 }
85
86 pub(in super::super) fn check_asms(&self) {
87 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
88 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
89 for (asm, hir_id) in deferred_asm_checks.drain(..) {
90 let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
91 InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
92 }
93 }
94
95 pub(in super::super) fn check_repeat_exprs(&self) {
96 let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
97 debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
98
99 let deferred_repeat_expr_checks = deferred_repeat_expr_checks
100 .drain(..)
101 .flat_map(|(element, element_ty, count)| {
102 match &element.kind {
106 hir::ExprKind::ConstBlock(..) => return None,
107 hir::ExprKind::Path(qpath) => {
108 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
109 if let Res::Def(DefKind::Const | DefKind::AssocConst, _) = res {
110 return None;
111 }
112 }
113 _ => {}
114 }
115
116 let count = self
121 .structurally_resolve_const(element.span, self.normalize(element.span, count));
122
123 if count.references_error() {
127 return None;
128 }
129
130 Some((element, element_ty, count))
131 })
132 .collect::<Vec<_>>();
138
139 let enforce_copy_bound = |element: &hir::Expr<'_>, element_ty| {
140 let is_constable = match element.kind {
144 hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
145 ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
146 traits::IsConstable::Fn
147 }
148 _ => traits::IsConstable::No,
149 },
150 hir::ExprKind::Path(qpath) => {
151 match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
152 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
153 _ => traits::IsConstable::No,
154 }
155 }
156 _ => traits::IsConstable::No,
157 };
158
159 let lang_item = self.tcx.require_lang_item(LangItem::Copy, element.span);
160 let code = traits::ObligationCauseCode::RepeatElementCopy {
161 is_constable,
162 elt_span: element.span,
163 };
164 self.require_type_meets(element_ty, element.span, code, lang_item);
165 };
166
167 for (element, element_ty, count) in deferred_repeat_expr_checks {
168 match count.kind() {
169 ty::ConstKind::Value(val) => {
170 if val.try_to_target_usize(self.tcx).is_none_or(|count| count > 1) {
171 enforce_copy_bound(element, element_ty)
172 } else {
173 }
176 }
177
178 ty::ConstKind::Param(_)
181 | ty::ConstKind::Expr(_)
182 | ty::ConstKind::Placeholder(_)
183 | ty::ConstKind::Unevaluated(_) => enforce_copy_bound(element, element_ty),
184
185 ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => {
186 unreachable!()
187 }
188 }
189 }
190 }
191
192 pub(in super::super) fn check_argument_types(
195 &self,
196 call_span: Span,
198 call_expr: &'tcx hir::Expr<'tcx>,
200 formal_input_tys: &[Ty<'tcx>],
202 formal_output: Ty<'tcx>,
203 expectation: Expectation<'tcx>,
205 provided_args: &'tcx [hir::Expr<'tcx>],
207 c_variadic: bool,
209 tuple_arguments: TupleArgumentsFlag,
211 fn_def_id: Option<DefId>,
213 ) {
214 let tcx = self.tcx;
215
216 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
231 self.register_wf_obligation(
232 fn_input_ty.into(),
233 arg_expr.span,
234 ObligationCauseCode::WellFormed(None),
235 );
236
237 self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
238 }
239
240 let formal_output = self.resolve_vars_with_obligations(formal_output);
245 let expected_input_tys: Option<Vec<_>> = expectation
246 .only_has_type(self)
247 .and_then(|expected_output| {
248 self.fudge_inference_if_ok(|| {
249 let ocx = ObligationCtxt::new(self);
250
251 let origin = self.misc(call_span);
256 ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
257 if !ocx.select_where_possible().is_empty() {
258 return Err(TypeError::Mismatch);
259 }
260
261 Ok(Some(
264 formal_input_tys
265 .iter()
266 .map(|&ty| self.resolve_vars_if_possible(ty))
267 .collect(),
268 ))
269 })
270 .ok()
271 })
272 .unwrap_or_default();
273
274 let mut err_code = E0061;
275
276 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
278 let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]);
279 match tuple_type.kind() {
280 ty::Tuple(arg_types) => {
282 if arg_types.len() != provided_args.len() {
284 err_code = E0057;
285 }
286 let expected_input_tys = match expected_input_tys {
287 Some(expected_input_tys) => match expected_input_tys.get(0) {
288 Some(ty) => match ty.kind() {
289 ty::Tuple(tys) => Some(tys.iter().collect()),
290 _ => None,
291 },
292 None => None,
293 },
294 None => None,
295 };
296 (arg_types.iter().collect(), expected_input_tys)
297 }
298 _ => {
299 let guar = struct_span_code_err!(
302 self.dcx(),
303 call_span,
304 E0059,
305 "cannot use call notation; the first type parameter \
306 for the function trait is neither a tuple nor unit"
307 )
308 .emit();
309 (self.err_args(provided_args.len(), guar), None)
310 }
311 }
312 } else {
313 (formal_input_tys.to_vec(), expected_input_tys)
314 };
315
316 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
318 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
319 expected_input_tys
320 } else {
321 formal_input_tys.clone()
322 };
323
324 let minimum_input_count = expected_input_tys.len();
325 let provided_arg_count = provided_args.len();
326
327 let demand_compatible = |idx| {
331 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
332 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
333 let provided_arg = &provided_args[idx];
334
335 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
336
337 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
341
342 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
343
344 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
348
349 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
353
354 let coerce_error =
355 self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
356 if coerce_error.is_some() {
357 return Compatibility::Incompatible(coerce_error);
358 }
359
360 let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
363 DefineOpaqueTypes::Yes,
364 formal_input_ty,
365 coerced_ty,
366 );
367
368 match formal_ty_error {
370 Ok(InferOk { obligations, value: () }) => {
371 self.register_predicates(obligations);
372 Compatibility::Compatible
373 }
374 Err(err) => Compatibility::Incompatible(Some(err)),
375 }
376 };
377
378 let mut compatibility_diagonal =
381 vec![Compatibility::Incompatible(None); provided_args.len()];
382
383 let mut call_appears_satisfied = if c_variadic {
388 provided_arg_count >= minimum_input_count
389 } else {
390 provided_arg_count == minimum_input_count
391 };
392
393 for check_closures in [false, true] {
399 if check_closures {
403 self.select_obligations_where_possible(|_| {})
404 }
405
406 for (idx, arg) in provided_args.iter().enumerate() {
409 if !check_closures {
413 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
414 }
415
416 if idx >= minimum_input_count {
422 continue;
423 }
424
425 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
431 !tcx.coroutine_is_async(closure.def_id.to_def_id())
432 } else {
433 false
434 };
435 if is_closure != check_closures {
436 continue;
437 }
438
439 let compatible = demand_compatible(idx);
440 let is_compatible = matches!(compatible, Compatibility::Compatible);
441 compatibility_diagonal[idx] = compatible;
442
443 if !is_compatible {
444 call_appears_satisfied = false;
445 }
446 }
447 }
448
449 if c_variadic && provided_arg_count < minimum_input_count {
450 err_code = E0060;
451 }
452
453 for arg in provided_args.iter().skip(minimum_input_count) {
454 let arg_ty = self.check_expr(arg);
456
457 if c_variadic {
462 fn variadic_error<'tcx>(
463 sess: &'tcx Session,
464 span: Span,
465 ty: Ty<'tcx>,
466 cast_ty: &str,
467 ) {
468 sess.dcx().emit_err(errors::PassToVariadicFunction {
469 span,
470 ty,
471 cast_ty,
472 sugg_span: span.shrink_to_hi(),
473 teach: sess.teach(E0617),
474 });
475 }
476
477 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
480 match arg_ty.kind() {
481 ty::Float(ty::FloatTy::F32) => {
482 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
483 }
484 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
485 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
486 }
487 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
488 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
489 }
490 ty::FnDef(..) => {
491 let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
492 let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
493
494 let fn_item_spa = arg.span;
495 tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
496 span: fn_item_spa,
497 sugg_span: fn_item_spa.shrink_to_hi(),
498 replace: fn_ptr,
499 });
500 }
501 _ => {}
502 }
503 }
504 }
505
506 if !call_appears_satisfied {
507 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
508 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
509 minimum_input_count
510 } else {
511 provided_arg_count
512 }));
513 debug_assert_eq!(
514 formal_input_tys.len(),
515 expected_input_tys.len(),
516 "expected formal_input_tys to be the same size as expected_input_tys"
517 );
518 let formal_and_expected_inputs = IndexVec::from_iter(
519 formal_input_tys
520 .iter()
521 .copied()
522 .zip_eq(expected_input_tys.iter().copied())
523 .map(|vars| self.resolve_vars_if_possible(vars)),
524 );
525
526 self.report_arg_errors(
527 compatibility_diagonal,
528 formal_and_expected_inputs,
529 provided_args,
530 c_variadic,
531 err_code,
532 fn_def_id,
533 call_span,
534 call_expr,
535 tuple_arguments,
536 );
537 }
538 }
539
540 fn check_place_expr_if_unsized(&self, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
546 if self.tcx.features().unsized_fn_params() && !expr.is_syntactic_place_expr() {
547 self.require_type_is_sized(
548 ty,
549 expr.span,
550 ObligationCauseCode::UnsizedNonPlaceExpr(expr.span),
551 );
552 }
553 }
554
555 fn report_arg_errors(
556 &self,
557 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
558 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
559 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
560 c_variadic: bool,
561 err_code: ErrCode,
562 fn_def_id: Option<DefId>,
563 call_span: Span,
564 call_expr: &'tcx hir::Expr<'tcx>,
565 tuple_arguments: TupleArgumentsFlag,
566 ) -> ErrorGuaranteed {
567 let (error_span, call_ident, full_call_span, call_name, is_method) = match &call_expr.kind {
569 hir::ExprKind::Call(
570 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
571 _,
572 ) => {
573 if let Res::Def(DefKind::Ctor(of, _), _) =
574 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
575 {
576 let name = match of {
577 CtorOf::Struct => "struct",
578 CtorOf::Variant => "enum variant",
579 };
580 (call_span, None, *span, name, false)
581 } else {
582 (call_span, None, *span, "function", false)
583 }
584 }
585 hir::ExprKind::Call(hir::Expr { span, .. }, _) => {
586 (call_span, None, *span, "function", false)
587 }
588 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
589 let ident_span = path_segment.ident.span;
590 let ident_span = if let Some(args) = path_segment.args {
591 ident_span.with_hi(args.span_ext.hi())
592 } else {
593 ident_span
594 };
595 (*span, Some(path_segment.ident), ident_span, "method", true)
596 }
597 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
598 };
599 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
600
601 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
603 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
604 }
605
606 let tcx = self.tcx;
607
608 let normalize_span = |span: Span| -> Span {
612 let normalized_span = span.find_ancestor_inside_same_ctxt(error_span).unwrap_or(span);
613 if normalized_span.source_equal(error_span) { span } else { normalized_span }
617 };
618
619 let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
621 .iter()
622 .map(|expr| {
623 let ty = self
624 .typeck_results
625 .borrow()
626 .expr_ty_adjusted_opt(*expr)
627 .unwrap_or_else(|| Ty::new_misc_error(tcx));
628 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
629 })
630 .collect();
631 let callee_expr = match &call_expr.peel_blocks().kind {
632 hir::ExprKind::Call(callee, _) => Some(*callee),
633 hir::ExprKind::MethodCall(_, receiver, ..) => {
634 if let Some((DefKind::AssocFn, def_id)) =
635 self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
636 && let Some(assoc) = tcx.opt_associated_item(def_id)
637 && assoc.is_method()
638 {
639 Some(*receiver)
640 } else {
641 None
642 }
643 }
644 _ => None,
645 };
646 let callee_ty = callee_expr
647 .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
648
649 let similar_assoc = |call_name: Ident| -> Option<(ty::AssocItem, ty::FnSig<'_>)> {
651 if let Some(callee_ty) = callee_ty
652 && let Ok(Some(assoc)) = self.probe_op(
653 call_name.span,
654 MethodCall,
655 Some(call_name),
656 None,
657 IsSuggestion(true),
658 callee_ty.peel_refs(),
659 callee_expr.unwrap().hir_id,
660 TraitsInScope,
661 |mut ctxt| ctxt.probe_for_similar_candidate(),
662 )
663 && assoc.is_method()
664 {
665 let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
666 let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
667
668 self.instantiate_binder_with_fresh_vars(
669 call_name.span,
670 BoundRegionConversionTime::FnCall,
671 fn_sig,
672 );
673 }
674 None
675 };
676
677 let suggest_confusable = |err: &mut Diag<'_>| {
678 let Some(call_name) = call_ident else {
679 return;
680 };
681 let Some(callee_ty) = callee_ty else {
682 return;
683 };
684 let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
685 if let Some(_name) = self.confusable_method_name(
693 err,
694 callee_ty.peel_refs(),
695 call_name,
696 Some(input_types.clone()),
697 ) {
698 return;
699 }
700 if let Some((assoc, fn_sig)) = similar_assoc(call_name)
702 && fn_sig.inputs()[1..]
703 .iter()
704 .zip(input_types.iter())
705 .all(|(expected, found)| self.may_coerce(*expected, *found))
706 && fn_sig.inputs()[1..].len() == input_types.len()
707 {
708 let assoc_name = assoc.name();
709 err.span_suggestion_verbose(
710 call_name.span,
711 format!("you might have meant to use `{}`", assoc_name),
712 assoc_name,
713 Applicability::MaybeIncorrect,
714 );
715 return;
716 }
717 if let Some(_name) =
719 self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
720 {
721 return;
722 }
723 if let Some((assoc, fn_sig)) = similar_assoc(call_name)
726 && fn_sig.inputs()[1..].len() == input_types.len()
727 {
728 err.span_note(
729 tcx.def_span(assoc.def_id),
730 format!(
731 "there's is a method with similar name `{}`, but the arguments don't match",
732 assoc.name(),
733 ),
734 );
735 return;
736 }
737 if let Some((assoc, _)) = similar_assoc(call_name) {
739 err.span_note(
740 tcx.def_span(assoc.def_id),
741 format!(
742 "there's is a method with similar name `{}`, but their argument count \
743 doesn't match",
744 assoc.name(),
745 ),
746 );
747 return;
748 }
749 };
750 let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
754 if provided_idx.as_usize() == expected_idx.as_usize() {
755 return compatibility_diagonal[provided_idx].clone();
756 }
757
758 let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
759 if (formal_input_ty, expected_input_ty).references_error() {
763 return Compatibility::Incompatible(None);
764 }
765
766 let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
767
768 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
769 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
770 let can_coerce = self.may_coerce(arg_ty, coerced_ty);
771 if !can_coerce {
772 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
773 ty::error::ExpectedFound::new(coerced_ty, arg_ty),
774 )));
775 }
776
777 let subtyping_error = self.probe(|_| {
779 self.at(&self.misc(arg_span), self.param_env)
780 .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
781 .err()
782 });
783
784 let references_error = (coerced_ty, arg_ty).references_error();
787 match (references_error, subtyping_error) {
788 (false, None) => Compatibility::Compatible,
789 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
790 }
791 };
792
793 let mk_trace = |span, (formal_ty, expected_ty), provided_ty| {
794 let mismatched_ty = if expected_ty == provided_ty {
795 formal_ty
799 } else {
800 expected_ty
801 };
802 TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
803 };
804
805 let (mut errors, matched_inputs) =
814 ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
815 .find_errors();
816
817 if let Some((mismatch_idx, terr)) =
819 compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
820 if let Compatibility::Incompatible(Some(terr)) = c {
821 Some((i, *terr))
822 } else {
823 None
824 }
825 })
826 {
827 if let Some(ty::Tuple(tys)) =
831 formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
832 && !tys.is_empty()
834 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
835 {
836 let provided_args_to_tuple = &provided_arg_tys[mismatch_idx..];
838 let (provided_args_to_tuple, provided_args_after_tuple) =
839 provided_args_to_tuple.split_at(tys.len());
840 let provided_as_tuple =
841 Ty::new_tup_from_iter(tcx, provided_args_to_tuple.iter().map(|&(ty, _)| ty));
842
843 let mut satisfied = true;
844 for ((_, expected_ty), provided_ty) in std::iter::zip(
846 formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
847 [provided_as_tuple]
848 .into_iter()
849 .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
850 ) {
851 if !self.may_coerce(provided_ty, *expected_ty) {
852 satisfied = false;
853 break;
854 }
855 }
856
857 if satisfied
861 && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
862 {
863 let mut err;
864 if tys.len() == 1 {
865 err = self.err_ctxt().report_and_explain_type_error(
868 mk_trace(
869 lo,
870 formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
871 provided_arg_tys[mismatch_idx].0,
872 ),
873 self.param_env,
874 terr,
875 );
876 err.span_label(
877 full_call_span,
878 format!("arguments to this {call_name} are incorrect"),
879 );
880 } else {
881 err = self.dcx().struct_span_err(
882 full_call_span,
883 format!(
884 "{call_name} takes {}{} but {} {} supplied",
885 if c_variadic { "at least " } else { "" },
886 potentially_plural_count(
887 formal_and_expected_inputs.len(),
888 "argument"
889 ),
890 potentially_plural_count(provided_args.len(), "argument"),
891 pluralize!("was", provided_args.len())
892 ),
893 );
894 err.code(err_code.to_owned());
895 err.multipart_suggestion_verbose(
896 "wrap these arguments in parentheses to construct a tuple",
897 vec![
898 (lo.shrink_to_lo(), "(".to_string()),
899 (hi.shrink_to_hi(), ")".to_string()),
900 ],
901 Applicability::MachineApplicable,
902 );
903 };
904 self.label_fn_like(
905 &mut err,
906 fn_def_id,
907 callee_ty,
908 call_expr,
909 None,
910 Some(mismatch_idx.as_usize()),
911 &matched_inputs,
912 &formal_and_expected_inputs,
913 is_method,
914 tuple_arguments,
915 );
916 suggest_confusable(&mut err);
917 return err.emit();
918 }
919 }
920 }
921
922 if errors.is_empty() {
938 if cfg!(debug_assertions) {
939 span_bug!(error_span, "expected errors from argument matrix");
940 } else {
941 let mut err =
942 self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
943 suggest_confusable(&mut err);
944 return err.emit();
945 }
946 }
947
948 let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
949 if let ty::Adt(adt, _) = ty.kind()
950 && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
951 && let hir::ExprKind::Struct(
952 hir::QPath::LangItem(hir::LangItem::RangeFull, _),
953 [],
954 _,
955 ) = expr.kind
956 {
957 let explanation = if self.tcx.features().default_field_values() {
960 "this is only supported on non-tuple struct literals"
961 } else if self.tcx.sess.is_nightly_build() {
962 "this is only supported on non-tuple struct literals when \
963 `#![feature(default_field_values)]` is enabled"
964 } else {
965 "this is not supported"
966 };
967 let msg = format!(
968 "you might have meant to use `..` to skip providing a value for \
969 expected fields, but {explanation}; it is instead interpreted as a \
970 `std::ops::RangeFull` literal",
971 );
972 err.span_help(expr.span, msg);
973 }
974 };
975
976 let mut reported = None;
977 errors.retain(|error| {
978 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
979 error
980 else {
981 return true;
982 };
983 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
984 let trace =
985 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
986 if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
987 let mut err =
988 self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e);
989 suggest_confusable(&mut err);
990 reported = Some(err.emit());
991 return false;
992 }
993 true
994 });
995
996 if let Some(reported) = reported
998 && errors.is_empty()
999 {
1000 return reported;
1001 }
1002 assert!(!errors.is_empty());
1003
1004 if let &[
1010 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
1011 ] = &errors[..]
1012 {
1013 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
1014 let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
1015 let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
1016 let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
1017 self.emit_coerce_suggestions(
1018 &mut err,
1019 provided_args[provided_idx],
1020 provided_ty,
1021 Expectation::rvalue_hint(self, expected_ty)
1022 .only_has_type(self)
1023 .unwrap_or(formal_ty),
1024 None,
1025 None,
1026 );
1027 err.span_label(full_call_span, format!("arguments to this {call_name} are incorrect"));
1028
1029 self.label_generic_mismatches(
1030 &mut err,
1031 fn_def_id,
1032 &matched_inputs,
1033 &provided_arg_tys,
1034 &formal_and_expected_inputs,
1035 is_method,
1036 );
1037
1038 if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
1039 && provided_idx.as_usize() == expected_idx.as_usize()
1040 {
1041 self.note_source_of_type_mismatch_constraint(
1042 &mut err,
1043 rcvr,
1044 crate::demand::TypeMismatchSource::Arg {
1045 call_expr,
1046 incompatible_arg: provided_idx.as_usize(),
1047 },
1048 );
1049 }
1050
1051 self.suggest_ptr_null_mut(
1052 expected_ty,
1053 provided_ty,
1054 provided_args[provided_idx],
1055 &mut err,
1056 );
1057
1058 self.suggest_deref_unwrap_or(
1059 &mut err,
1060 callee_ty,
1061 call_ident,
1062 expected_ty,
1063 provided_ty,
1064 provided_args[provided_idx],
1065 is_method,
1066 );
1067
1068 self.label_fn_like(
1070 &mut err,
1071 fn_def_id,
1072 callee_ty,
1073 call_expr,
1074 Some(expected_ty),
1075 Some(expected_idx.as_usize()),
1076 &matched_inputs,
1077 &formal_and_expected_inputs,
1078 is_method,
1079 tuple_arguments,
1080 );
1081 suggest_confusable(&mut err);
1082 detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
1083 return err.emit();
1084 }
1085
1086 if let [Error::Extra(provided_idx)] = &errors[..] {
1091 let remove_idx_is_perfect = |idx: usize| -> bool {
1092 let removed_arg_tys = provided_arg_tys
1093 .iter()
1094 .enumerate()
1095 .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
1096 .collect::<IndexVec<ProvidedIdx, _>>();
1097 std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
1098 |((expected_ty, _), (provided_ty, _))| {
1099 !provided_ty.references_error()
1100 && self.may_coerce(*provided_ty, *expected_ty)
1101 },
1102 )
1103 };
1104
1105 if !remove_idx_is_perfect(provided_idx.as_usize()) {
1106 if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) {
1107 errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
1108 }
1109 }
1110 }
1111
1112 let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
1113 struct_span_code_err!(
1114 self.dcx(),
1115 full_call_span,
1116 E0308,
1117 "arguments to this {} are incorrect",
1118 call_name,
1119 )
1120 } else {
1121 self.dcx()
1122 .struct_span_err(
1123 full_call_span,
1124 format!(
1125 "this {} takes {}{} but {} {} supplied",
1126 call_name,
1127 if c_variadic { "at least " } else { "" },
1128 potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
1129 potentially_plural_count(provided_args.len(), "argument"),
1130 pluralize!("was", provided_args.len())
1131 ),
1132 )
1133 .with_code(err_code.to_owned())
1134 };
1135
1136 suggest_confusable(&mut err);
1137 let mut labels = vec![];
1139 enum SuggestionText {
1142 None,
1143 Provide(bool),
1144 Remove(bool),
1145 Swap,
1146 Reorder,
1147 DidYouMean,
1148 }
1149 let mut suggestion_text = SuggestionText::None;
1150
1151 let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
1152 if ty.is_unit() {
1153 "()".to_string()
1154 } else if ty.is_suggestable(tcx, false) {
1155 format!("/* {ty} */")
1156 } else if let Some(fn_def_id) = fn_def_id
1157 && self.tcx.def_kind(fn_def_id).is_fn_like()
1158 && let self_implicit =
1159 matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
1160 && let Some(Some(arg)) =
1161 self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
1162 && arg.name != kw::SelfLower
1163 {
1164 format!("/* {} */", arg.name)
1165 } else {
1166 "/* value */".to_string()
1167 }
1168 };
1169
1170 let mut errors = errors.into_iter().peekable();
1171 let mut only_extras_so_far = errors
1172 .peek()
1173 .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
1174 let mut prev_extra_idx = None;
1175 let mut suggestions = vec![];
1176 while let Some(error) = errors.next() {
1177 only_extras_so_far &= matches!(error, Error::Extra(_));
1178
1179 match error {
1180 Error::Invalid(provided_idx, expected_idx, compatibility) => {
1181 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
1182 let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
1183 if let Compatibility::Incompatible(error) = compatibility {
1184 let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
1185 if let Some(e) = error {
1186 self.err_ctxt().note_type_err(
1187 &mut err,
1188 &trace.cause,
1189 None,
1190 Some(self.param_env.and(trace.values)),
1191 e,
1192 true,
1193 None,
1194 );
1195 }
1196 }
1197
1198 self.emit_coerce_suggestions(
1199 &mut err,
1200 provided_args[provided_idx],
1201 provided_ty,
1202 Expectation::rvalue_hint(self, expected_ty)
1203 .only_has_type(self)
1204 .unwrap_or(formal_ty),
1205 None,
1206 None,
1207 );
1208 detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
1209 }
1210 Error::Extra(arg_idx) => {
1211 let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
1212 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1213 format!(" of type `{provided_ty}`")
1215 } else {
1216 "".to_string()
1217 };
1218 let idx = if provided_arg_tys.len() == 1 {
1219 "".to_string()
1220 } else {
1221 format!(" #{}", arg_idx.as_usize() + 1)
1222 };
1223 labels.push((
1224 provided_span,
1225 format!("unexpected argument{idx}{provided_ty_name}"),
1226 ));
1227 let mut span = provided_span;
1228 if span.can_be_used_for_suggestions()
1229 && error_span.can_be_used_for_suggestions()
1230 {
1231 if arg_idx.index() > 0
1232 && let Some((_, prev)) =
1233 provided_arg_tys.get(ProvidedIdx::from_usize(arg_idx.index() - 1))
1234 {
1235 span = prev.shrink_to_hi().to(span);
1237 }
1238
1239 let trim_next_comma = match errors.peek() {
1246 Some(Error::Extra(provided_idx))
1247 if only_extras_so_far
1248 && provided_idx.index() > arg_idx.index() + 1 =>
1249 {
1257 prev_extra_idx.is_none_or(|prev_extra_idx| {
1258 prev_extra_idx + 1 == arg_idx.index()
1259 })
1260 }
1261 None if only_extras_so_far => true,
1263 _ => false,
1265 };
1266
1267 if trim_next_comma {
1268 let next = provided_arg_tys
1269 .get(arg_idx + 1)
1270 .map(|&(_, sp)| sp)
1271 .unwrap_or_else(|| {
1272 self.tcx().sess.source_map().end_point(call_expr.span)
1277 });
1278
1279 span = span.until(next);
1281 }
1282
1283 suggestions.push((span, String::new()));
1284
1285 suggestion_text = match suggestion_text {
1286 SuggestionText::None => SuggestionText::Remove(false),
1287 SuggestionText::Remove(_) => SuggestionText::Remove(true),
1288 _ => SuggestionText::DidYouMean,
1289 };
1290 prev_extra_idx = Some(arg_idx.index())
1291 }
1292 detect_dotdot(&mut err, provided_ty, provided_args[arg_idx]);
1293 }
1294 Error::Missing(expected_idx) => {
1295 let mut missing_idxs = vec![expected_idx];
1299 while let Some(e) = errors.next_if(|e| {
1300 matches!(e, Error::Missing(next_expected_idx)
1301 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
1302 }) {
1303 match e {
1304 Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
1305 _ => unreachable!(
1306 "control flow ensures that we should always get an `Error::Missing`"
1307 ),
1308 }
1309 }
1310
1311 match &missing_idxs[..] {
1316 &[expected_idx] => {
1317 let (_, input_ty) = formal_and_expected_inputs[expected_idx];
1318 let span = if let Some((_, arg_span)) =
1319 provided_arg_tys.get(expected_idx.to_provided_idx())
1320 {
1321 *arg_span
1322 } else {
1323 args_span
1324 };
1325 let rendered = if !has_error_or_infer([input_ty]) {
1326 format!(" of type `{input_ty}`")
1327 } else {
1328 "".to_string()
1329 };
1330 labels.push((
1331 span,
1332 format!(
1333 "argument #{}{rendered} is missing",
1334 expected_idx.as_usize() + 1
1335 ),
1336 ));
1337
1338 suggestion_text = match suggestion_text {
1339 SuggestionText::None => SuggestionText::Provide(false),
1340 SuggestionText::Provide(_) => SuggestionText::Provide(true),
1341 _ => SuggestionText::DidYouMean,
1342 };
1343 }
1344 &[first_idx, second_idx] => {
1345 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
1346 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
1347 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
1348 provided_arg_tys.get(first_idx.to_provided_idx()),
1349 provided_arg_tys.get(second_idx.to_provided_idx()),
1350 ) {
1351 first_span.to(*second_span)
1352 } else {
1353 args_span
1354 };
1355 let rendered =
1356 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
1357 format!(
1358 " of type `{first_expected_ty}` and `{second_expected_ty}`"
1359 )
1360 } else {
1361 "".to_string()
1362 };
1363 labels.push((span, format!("two arguments{rendered} are missing")));
1364 suggestion_text = match suggestion_text {
1365 SuggestionText::None | SuggestionText::Provide(_) => {
1366 SuggestionText::Provide(true)
1367 }
1368 _ => SuggestionText::DidYouMean,
1369 };
1370 }
1371 &[first_idx, second_idx, third_idx] => {
1372 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
1373 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
1374 let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
1375 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
1376 provided_arg_tys.get(first_idx.to_provided_idx()),
1377 provided_arg_tys.get(third_idx.to_provided_idx()),
1378 ) {
1379 first_span.to(*third_span)
1380 } else {
1381 args_span
1382 };
1383 let rendered = if !has_error_or_infer([
1384 first_expected_ty,
1385 second_expected_ty,
1386 third_expected_ty,
1387 ]) {
1388 format!(
1389 " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
1390 )
1391 } else {
1392 "".to_string()
1393 };
1394 labels.push((span, format!("three arguments{rendered} are missing")));
1395 suggestion_text = match suggestion_text {
1396 SuggestionText::None | SuggestionText::Provide(_) => {
1397 SuggestionText::Provide(true)
1398 }
1399 _ => SuggestionText::DidYouMean,
1400 };
1401 }
1402 missing_idxs => {
1403 let first_idx = *missing_idxs.first().unwrap();
1404 let last_idx = *missing_idxs.last().unwrap();
1405 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
1409 provided_arg_tys.get(first_idx.to_provided_idx()),
1410 provided_arg_tys.get(last_idx.to_provided_idx()),
1411 ) {
1412 first_span.to(*last_span)
1413 } else {
1414 args_span
1415 };
1416 labels.push((span, "multiple arguments are missing".to_string()));
1417 suggestion_text = match suggestion_text {
1418 SuggestionText::None | SuggestionText::Provide(_) => {
1419 SuggestionText::Provide(true)
1420 }
1421 _ => SuggestionText::DidYouMean,
1422 };
1423 }
1424 }
1425 }
1426 Error::Swap(
1427 first_provided_idx,
1428 second_provided_idx,
1429 first_expected_idx,
1430 second_expected_idx,
1431 ) => {
1432 let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
1433 let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
1434 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
1435 format!(", found `{first_provided_ty}`")
1436 } else {
1437 String::new()
1438 };
1439 labels.push((
1440 first_span,
1441 format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
1442 ));
1443
1444 let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
1445 let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
1446 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
1447 format!(", found `{second_provided_ty}`")
1448 } else {
1449 String::new()
1450 };
1451 labels.push((
1452 second_span,
1453 format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
1454 ));
1455
1456 suggestion_text = match suggestion_text {
1457 SuggestionText::None => SuggestionText::Swap,
1458 _ => SuggestionText::DidYouMean,
1459 };
1460 }
1461 Error::Permutation(args) => {
1462 for (dst_arg, dest_input) in args {
1463 let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
1464 let (provided_ty, provided_span) = provided_arg_tys[dest_input];
1465 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1466 format!(", found `{provided_ty}`")
1467 } else {
1468 String::new()
1469 };
1470 labels.push((
1471 provided_span,
1472 format!("expected `{expected_ty}`{provided_ty_name}"),
1473 ));
1474 }
1475
1476 suggestion_text = match suggestion_text {
1477 SuggestionText::None => SuggestionText::Reorder,
1478 _ => SuggestionText::DidYouMean,
1479 };
1480 }
1481 }
1482 }
1483
1484 self.label_generic_mismatches(
1485 &mut err,
1486 fn_def_id,
1487 &matched_inputs,
1488 &provided_arg_tys,
1489 &formal_and_expected_inputs,
1490 is_method,
1491 );
1492
1493 let mut prev = -1;
1513 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1514 if let Some(provided_idx) = provided_idx {
1517 prev = provided_idx.index() as i64;
1518 continue;
1519 }
1520 let idx = ProvidedIdx::from_usize((prev + 1) as usize);
1521 if let Some((_, arg_span)) = provided_arg_tys.get(idx) {
1522 prev += 1;
1523 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1528 suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
1529 }
1530 }
1531
1532 if labels.len() <= 5 {
1534 for (span, label) in labels {
1535 err.span_label(span, label);
1536 }
1537 }
1538
1539 self.label_fn_like(
1541 &mut err,
1542 fn_def_id,
1543 callee_ty,
1544 call_expr,
1545 None,
1546 None,
1547 &matched_inputs,
1548 &formal_and_expected_inputs,
1549 is_method,
1550 tuple_arguments,
1551 );
1552
1553 let suggestion_text = match suggestion_text {
1555 SuggestionText::None => None,
1556 SuggestionText::Provide(plural) => {
1557 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
1558 }
1559 SuggestionText::Remove(plural) => {
1560 err.multipart_suggestion_verbose(
1561 format!("remove the extra argument{}", if plural { "s" } else { "" }),
1562 suggestions,
1563 Applicability::HasPlaceholders,
1564 );
1565 None
1566 }
1567 SuggestionText::Swap => Some("swap these arguments".to_string()),
1568 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
1569 SuggestionText::DidYouMean => Some("did you mean".to_string()),
1570 };
1571 if let Some(suggestion_text) = suggestion_text
1572 && !full_call_span.in_external_macro(self.sess().source_map())
1573 {
1574 let source_map = self.sess().source_map();
1575 let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) {
1576 args_span
1578 } else {
1579 full_call_span.shrink_to_hi()
1583 };
1584
1585 enum ArgumentsFormatting {
1587 SingleLine,
1588 Multiline { fallback_indent: String, brace_indent: String },
1589 }
1590 let arguments_formatting = {
1591 let mut provided_inputs = matched_inputs.iter().filter_map(|a| *a);
1592 if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
1593 && let Some(first_idx) = provided_inputs.by_ref().next()
1594 && let Some(last_idx) = provided_inputs.by_ref().next()
1595 && let (_, first_span) = provided_arg_tys[first_idx]
1596 && let (_, last_span) = provided_arg_tys[last_idx]
1597 && source_map.is_multiline(first_span.to(last_span))
1598 && let Some(fallback_indent) = source_map.indentation_before(first_span)
1599 {
1600 ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
1601 } else {
1602 ArgumentsFormatting::SingleLine
1603 }
1604 };
1605
1606 let mut suggestion = "(".to_owned();
1607 let mut needs_comma = false;
1608 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1609 if needs_comma {
1610 suggestion += ",";
1611 }
1612 match &arguments_formatting {
1613 ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
1614 ArgumentsFormatting::SingleLine => {}
1615 ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
1616 }
1617 needs_comma = true;
1618 let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
1619 && let (_, provided_span) = provided_arg_tys[*provided_idx]
1620 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
1621 {
1622 (Some(provided_span), arg_text)
1623 } else {
1624 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1626 (None, ty_to_snippet(expected_ty, expected_idx))
1627 };
1628 if let ArgumentsFormatting::Multiline { fallback_indent, .. } =
1629 &arguments_formatting
1630 {
1631 let indent = suggestion_span
1632 .and_then(|span| source_map.indentation_before(span))
1633 .unwrap_or_else(|| fallback_indent.clone());
1634 suggestion += &indent;
1635 }
1636 suggestion += &suggestion_text;
1637 }
1638 if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
1639 suggestion += ",\n";
1640 suggestion += &brace_indent;
1641 }
1642 suggestion += ")";
1643 err.span_suggestion_verbose(
1644 suggestion_span,
1645 suggestion_text,
1646 suggestion,
1647 Applicability::HasPlaceholders,
1648 );
1649 }
1650
1651 err.emit()
1652 }
1653
1654 fn suggest_ptr_null_mut(
1655 &self,
1656 expected_ty: Ty<'tcx>,
1657 provided_ty: Ty<'tcx>,
1658 arg: &hir::Expr<'tcx>,
1659 err: &mut Diag<'_>,
1660 ) {
1661 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
1662 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
1663 && let hir::ExprKind::Call(callee, _) = arg.kind
1664 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
1665 && let Res::Def(_, def_id) = path.res
1666 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
1667 {
1668 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
1671 }
1672 }
1673
1674 pub(in super::super) fn check_expr_lit(
1676 &self,
1677 lit: &hir::Lit,
1678 expected: Expectation<'tcx>,
1679 ) -> Ty<'tcx> {
1680 let tcx = self.tcx;
1681
1682 match lit.node {
1683 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
1684 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
1685 tcx,
1686 tcx.lifetimes.re_static,
1687 Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
1688 ),
1689 ast::LitKind::Byte(_) => tcx.types.u8,
1690 ast::LitKind::Char(_) => tcx.types.char,
1691 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, t),
1692 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, t),
1693 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
1694 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1695 ty::Int(_) | ty::Uint(_) => Some(ty),
1696 ty::Char => Some(tcx.types.u8),
1700 ty::RawPtr(..) => Some(tcx.types.usize),
1701 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1702 &ty::Pat(base, _) if base.is_integral() => {
1703 let layout = tcx
1704 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1705 .ok()?;
1706 assert!(!layout.uninhabited);
1707
1708 match layout.backend_repr {
1709 rustc_abi::BackendRepr::Scalar(scalar) => {
1710 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1711 }
1712 _ => unreachable!(),
1713 }
1714 }
1715 _ => None,
1716 });
1717 opt_ty.unwrap_or_else(|| self.next_int_var())
1718 }
1719 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => Ty::new_float(tcx, t),
1720 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1721 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1722 ty::Float(_) => Some(ty),
1723 _ => None,
1724 });
1725 opt_ty.unwrap_or_else(|| self.next_float_var())
1726 }
1727 ast::LitKind::Bool(_) => tcx.types.bool,
1728 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1729 tcx,
1730 tcx.lifetimes.re_static,
1731 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, lit.span)).skip_binder(),
1732 ),
1733 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1734 }
1735 }
1736
1737 pub(crate) fn check_struct_path(
1738 &self,
1739 qpath: &QPath<'tcx>,
1740 hir_id: HirId,
1741 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1742 let path_span = qpath.span();
1743 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1744 let variant = match def {
1745 Res::Err => {
1746 let guar =
1747 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1748 self.set_tainted_by_errors(guar);
1749 return Err(guar);
1750 }
1751 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1752 Some(adt) => {
1753 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1754 }
1755 _ => bug!("unexpected type: {:?}", ty.normalized),
1756 },
1757 Res::Def(
1758 DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
1759 _,
1760 )
1761 | Res::SelfTyParam { .. }
1762 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1763 Some(adt) if !adt.is_enum() => {
1764 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1765 }
1766 _ => None,
1767 },
1768 _ => bug!("unexpected definition: {:?}", def),
1769 };
1770
1771 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1772 debug!("check_struct_path: did={:?} args={:?}", did, args);
1773
1774 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1776
1777 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1779
1780 Ok((variant, ty.normalized))
1781 } else {
1782 Err(match *ty.normalized.kind() {
1783 ty::Error(guar) => {
1784 guar
1789 }
1790 _ => struct_span_code_err!(
1791 self.dcx(),
1792 path_span,
1793 E0071,
1794 "expected struct, variant or union type, found {}",
1795 ty.normalized.sort_string(self.tcx)
1796 )
1797 .with_span_label(path_span, "not a struct")
1798 .emit(),
1799 })
1800 }
1801 }
1802
1803 fn check_decl_initializer(
1804 &self,
1805 hir_id: HirId,
1806 pat: &'tcx hir::Pat<'tcx>,
1807 init: &'tcx hir::Expr<'tcx>,
1808 ) -> Ty<'tcx> {
1809 let ref_bindings = pat.contains_explicit_ref_binding();
1814
1815 let local_ty = self.local_ty(init.span, hir_id);
1816 if let Some(m) = ref_bindings {
1817 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1826 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1827 self.emit_type_mismatch_suggestions(
1828 &mut diag,
1829 init.peel_drop_temps(),
1830 init_ty,
1831 local_ty,
1832 None,
1833 None,
1834 );
1835 diag.emit();
1836 }
1837 init_ty
1838 } else {
1839 self.check_expr_coercible_to_type(init, local_ty, None)
1840 }
1841 }
1842
1843 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1844 let decl_ty = self.local_ty(decl.span, decl.hir_id);
1846
1847 if let Some(ref init) = decl.init {
1849 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1850 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1851 }
1852
1853 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1855 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
1857 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1858 } _ => (None, None), };
1861
1862 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1864 let pat_ty = self.node_ty(decl.pat.hir_id);
1865 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1866
1867 if let Some(blk) = decl.origin.try_get_else() {
1868 let previous_diverges = self.diverges.get();
1869 let else_ty = self.check_expr_block(blk, NoExpectation);
1870 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1871 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1872 {
1873 err.emit();
1874 }
1875 self.diverges.set(previous_diverges);
1876 }
1877 decl_ty
1878 }
1879
1880 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1882 GatherLocalsVisitor::gather_from_local(self, local);
1883
1884 let ty = self.check_decl(local.into());
1885 self.write_ty(local.hir_id, ty);
1886 if local.pat.is_never_pattern() {
1887 self.diverges.set(Diverges::Always {
1888 span: local.pat.span,
1889 custom_note: Some("any code following a never pattern is unreachable"),
1890 });
1891 }
1892 }
1893
1894 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1895 match stmt.kind {
1897 hir::StmtKind::Item(..) => return,
1898 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1899 }
1900
1901 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1902
1903 let old_diverges = self.diverges.replace(Diverges::Maybe);
1905
1906 match stmt.kind {
1907 hir::StmtKind::Let(l) => {
1908 self.check_decl_local(l);
1909 }
1910 hir::StmtKind::Item(_) => {}
1912 hir::StmtKind::Expr(ref expr) => {
1913 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1915 if self.is_next_stmt_expr_continuation(stmt.hir_id)
1916 && let hir::ExprKind::Match(..) | hir::ExprKind::If(..) = expr.kind
1917 {
1918 err.multipart_suggestion(
1923 "parentheses are required to parse this as an expression",
1924 vec![
1925 (expr.span.shrink_to_lo(), "(".to_string()),
1926 (expr.span.shrink_to_hi(), ")".to_string()),
1927 ],
1928 Applicability::MachineApplicable,
1929 );
1930 } else if expr.can_have_side_effects() {
1931 self.suggest_semicolon_at_end(expr.span, err);
1932 }
1933 });
1934 }
1935 hir::StmtKind::Semi(expr) => {
1936 let ty = self.check_expr(expr);
1937 self.check_place_expr_if_unsized(ty, expr);
1938 }
1939 }
1940
1941 self.diverges.set(self.diverges.get() | old_diverges);
1943 }
1944
1945 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1946 let unit = self.tcx.types.unit;
1947 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1948
1949 if !ty.is_never() {
1952 self.demand_suptype(blk.span, unit, ty);
1953 }
1954 }
1955
1956 pub(in super::super) fn check_expr_block(
1957 &self,
1958 blk: &'tcx hir::Block<'tcx>,
1959 expected: Expectation<'tcx>,
1960 ) -> Ty<'tcx> {
1961 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1978 let coerce = if blk.targeted_by_break {
1979 CoerceMany::new(coerce_to_ty)
1980 } else {
1981 CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
1982 };
1983
1984 let prev_diverges = self.diverges.get();
1985 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1986
1987 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1988 for s in blk.stmts {
1989 self.check_stmt(s);
1990 }
1991
1992 let tail_expr_ty =
1995 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1996
1997 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1998 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1999 let coerce = ctxt.coerce.as_mut().unwrap();
2000 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
2001 let span = self.get_expr_coercion_span(tail_expr);
2002 let cause = self.cause(
2003 span,
2004 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
2005 );
2006 let ty_for_diagnostic = coerce.merged_ty();
2007 coerce.coerce_inner(
2011 self,
2012 &cause,
2013 Some(tail_expr),
2014 tail_expr_ty,
2015 |diag| {
2016 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
2017 },
2018 false,
2019 );
2020 } else {
2021 if !self.diverges.get().is_always()
2032 || matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
2033 {
2034 let mut sp = blk.span;
2040 let mut fn_span = None;
2041 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
2042 let ret_sp = decl.output.span();
2043 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
2044 if block_sp == blk.span {
2048 sp = ret_sp;
2049 fn_span = self.tcx.def_ident_span(fn_def_id);
2050 }
2051 }
2052 }
2053 coerce.coerce_forced_unit(
2054 self,
2055 &self.misc(sp),
2056 |err| {
2057 if let Some(expected_ty) = expected.only_has_type(self) {
2058 if blk.stmts.is_empty() && blk.expr.is_none() {
2059 self.suggest_boxing_when_appropriate(
2060 err,
2061 blk.span,
2062 blk.hir_id,
2063 expected_ty,
2064 self.tcx.types.unit,
2065 );
2066 }
2067 if !self.err_ctxt().consider_removing_semicolon(
2068 blk,
2069 expected_ty,
2070 err,
2071 ) {
2072 self.err_ctxt().consider_returning_binding(
2073 blk,
2074 expected_ty,
2075 err,
2076 );
2077 }
2078 if expected_ty == self.tcx.types.bool {
2079 if let hir::Block {
2084 stmts:
2085 [
2086 hir::Stmt {
2087 kind:
2088 hir::StmtKind::Let(hir::LetStmt {
2089 source:
2090 hir::LocalSource::AssignDesugar(_),
2091 ..
2092 }),
2093 ..
2094 },
2095 hir::Stmt {
2096 kind:
2097 hir::StmtKind::Expr(hir::Expr {
2098 kind: hir::ExprKind::Assign(lhs, ..),
2099 ..
2100 }),
2101 ..
2102 },
2103 ],
2104 ..
2105 } = blk
2106 {
2107 self.comes_from_while_condition(blk.hir_id, |_| {
2108 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
2112
2113 if !lhs.is_syntactic_place_expr()
2114 || res.references_error()
2115 {
2116 err.downgrade_to_delayed_bug();
2117 }
2118 })
2119 }
2120 }
2121 }
2122 if let Some(fn_span) = fn_span {
2123 err.span_label(
2124 fn_span,
2125 "implicitly returns `()` as its body has no tail or `return` \
2126 expression",
2127 );
2128 }
2129 },
2130 false,
2131 );
2132 }
2133 }
2134 });
2135
2136 if ctxt.may_break {
2137 self.diverges.set(prev_diverges);
2140 }
2141
2142 let ty = ctxt.coerce.unwrap().complete(self);
2143
2144 self.write_ty(blk.hir_id, ty);
2145
2146 ty
2147 }
2148
2149 fn parent_item_span(&self, id: HirId) -> Option<Span> {
2150 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
2151 match node {
2152 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
2153 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
2154 let body = self.tcx.hir_body(body_id);
2155 if let ExprKind::Block(block, _) = &body.value.kind {
2156 return Some(block.span);
2157 }
2158 }
2159 _ => {}
2160 }
2161 None
2162 }
2163
2164 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
2172 let check_in_progress = |elem: &hir::Expr<'_>| {
2173 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
2174 |_| match elem.kind {
2175 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
2177 _ => elem.span,
2178 },
2179 )
2180 };
2181
2182 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
2183 && let Some(rslt) = check_in_progress(el)
2184 {
2185 return rslt;
2186 }
2187
2188 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
2189 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
2190 if let Some(span) = iter.next() {
2191 if iter.next().is_none() {
2192 return span;
2193 }
2194 }
2195 }
2196
2197 expr.span
2198 }
2199
2200 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
2201 if let Err(guar) = ty.error_reported() {
2202 struct OverwritePatternsWithError {
2203 pat_hir_ids: Vec<hir::HirId>,
2204 }
2205 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
2206 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
2207 self.pat_hir_ids.push(p.hir_id);
2208 hir::intravisit::walk_pat(self, p);
2209 }
2210 }
2211 let err = Ty::new_error(self.tcx, guar);
2213 self.write_ty(hir_id, err);
2214 self.write_ty(pat.hir_id, err);
2215 let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
2216 hir::intravisit::walk_pat(&mut visitor, pat);
2217 for hir_id in visitor.pat_hir_ids {
2220 self.write_ty(hir_id, err);
2221 }
2222 self.locals.borrow_mut().insert(hir_id, err);
2223 self.locals.borrow_mut().insert(pat.hir_id, err);
2224 }
2225 }
2226
2227 fn finish_resolving_struct_path(
2230 &self,
2231 qpath: &QPath<'tcx>,
2232 path_span: Span,
2233 hir_id: HirId,
2234 ) -> (Res, LoweredTy<'tcx>) {
2235 match *qpath {
2236 QPath::Resolved(ref maybe_qself, path) => {
2237 let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
2238 let ty = self.lowerer().lower_resolved_ty_path(
2239 self_ty,
2240 path,
2241 hir_id,
2242 PermitVariants::Yes,
2243 );
2244 (path.res, LoweredTy::from_raw(self, path_span, ty))
2245 }
2246 QPath::TypeRelative(hir_self_ty, segment) => {
2247 let self_ty = self.lower_ty(hir_self_ty);
2248
2249 let result = self.lowerer().lower_type_relative_ty_path(
2250 self_ty.raw,
2251 hir_self_ty,
2252 segment,
2253 hir_id,
2254 path_span,
2255 PermitVariants::Yes,
2256 );
2257 let ty = result
2258 .map(|(ty, _, _)| ty)
2259 .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
2260 let ty = LoweredTy::from_raw(self, path_span, ty);
2261 let result = result.map(|(_, kind, def_id)| (kind, def_id));
2262
2263 self.write_resolution(hir_id, result);
2265
2266 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
2267 }
2268 QPath::LangItem(lang_item, span) => {
2269 let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
2270 (res, LoweredTy::from_raw(self, path_span, ty))
2271 }
2272 }
2273 }
2274
2275 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
2282 &self,
2283 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
2284 ) {
2285 let mut remap_cause = FxIndexSet::default();
2291 let mut not_adjusted = vec![];
2292
2293 for error in errors {
2294 let before_span = error.obligation.cause.span;
2295 if self.adjust_fulfillment_error_for_expr_obligation(error)
2296 || before_span != error.obligation.cause.span
2297 {
2298 remap_cause.insert((
2299 before_span,
2300 error.obligation.predicate,
2301 error.obligation.cause.clone(),
2302 ));
2303 } else {
2304 not_adjusted.push(error);
2307 }
2308 }
2309
2310 for error in not_adjusted {
2318 for (span, predicate, cause) in &remap_cause {
2319 if *predicate == error.obligation.predicate
2320 && span.contains(error.obligation.cause.span)
2321 {
2322 error.obligation.cause = cause.clone();
2323 continue;
2324 }
2325 }
2326 }
2327 }
2328
2329 fn label_fn_like(
2330 &self,
2331 err: &mut Diag<'_>,
2332 callable_def_id: Option<DefId>,
2333 callee_ty: Option<Ty<'tcx>>,
2334 call_expr: &'tcx hir::Expr<'tcx>,
2335 expected_ty: Option<Ty<'tcx>>,
2336 expected_idx: Option<usize>,
2338 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2339 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2340 is_method: bool,
2341 tuple_arguments: TupleArgumentsFlag,
2342 ) {
2343 let Some(mut def_id) = callable_def_id else {
2344 return;
2345 };
2346
2347 if tuple_arguments == TupleArguments
2352 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
2353 && let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
2358 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
2359 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
2361 && let Some(callee_ty) = callee_ty
2362 {
2363 let callee_ty = callee_ty.peel_refs();
2364 match *callee_ty.kind() {
2365 ty::Param(param) => {
2366 let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
2367 if param.kind.is_synthetic() {
2368 def_id = param.def_id;
2370 } else {
2371 let instantiated = self
2374 .tcx
2375 .explicit_predicates_of(self.body_id)
2376 .instantiate_identity(self.tcx);
2377 for (predicate, span) in instantiated {
2381 if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder()
2382 && pred.self_ty().peel_refs() == callee_ty
2383 && self.tcx.is_fn_trait(pred.def_id())
2384 {
2385 err.span_note(span, "callable defined here");
2386 return;
2387 }
2388 }
2389 }
2390 }
2391 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
2392 | ty::Closure(new_def_id, _)
2393 | ty::FnDef(new_def_id, _) => {
2394 def_id = new_def_id;
2395 }
2396 _ => {
2397 let new_def_id = self.probe(|_| {
2399 let trait_ref = ty::TraitRef::new(
2400 self.tcx,
2401 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
2402 [callee_ty, self.next_ty_var(DUMMY_SP)],
2403 );
2404 let obligation = traits::Obligation::new(
2405 self.tcx,
2406 traits::ObligationCause::dummy(),
2407 self.param_env,
2408 trait_ref,
2409 );
2410 match SelectionContext::new(self).select(&obligation) {
2411 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
2412 Some(impl_source.impl_def_id)
2413 }
2414 _ => None,
2415 }
2416 });
2417 if let Some(new_def_id) = new_def_id {
2418 def_id = new_def_id;
2419 } else {
2420 return;
2421 }
2422 }
2423 }
2424 }
2425
2426 if let Some(def_span) = self.tcx.def_ident_span(def_id)
2427 && !def_span.is_dummy()
2428 {
2429 let mut spans: MultiSpan = def_span.into();
2430 if let Some((params_with_generics, hir_generics)) =
2431 self.get_hir_param_info(def_id, is_method)
2432 {
2433 struct MismatchedParam<'a> {
2434 idx: ExpectedIdx,
2435 generic: GenericIdx,
2436 param: &'a FnParam<'a>,
2437 deps: SmallVec<[ExpectedIdx; 4]>,
2438 }
2439
2440 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2441 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
2443 if let Some(expected_idx) = expected_idx {
2444 let expected_idx = ExpectedIdx::from_usize(expected_idx);
2445 let &(expected_generic, ref expected_param) =
2446 ¶ms_with_generics[expected_idx];
2447 if let Some(expected_generic) = expected_generic {
2448 mismatched_params.push(MismatchedParam {
2449 idx: expected_idx,
2450 generic: expected_generic,
2451 param: expected_param,
2452 deps: SmallVec::new(),
2453 });
2454 } else {
2455 spans.push_span_label(expected_param.span(), "");
2457 }
2458 } else {
2459 mismatched_params.extend(
2460 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
2461 |((idx, &(generic, ref param)), matched_idx)| {
2462 if matched_idx.is_some() {
2463 None
2464 } else if let Some(generic) = generic {
2465 Some(MismatchedParam {
2466 idx,
2467 generic,
2468 param,
2469 deps: SmallVec::new(),
2470 })
2471 } else {
2472 spans.push_span_label(param.span(), "");
2474 None
2475 }
2476 },
2477 ),
2478 );
2479 }
2480
2481 if !mismatched_params.is_empty() {
2482 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
2485 |_| SmallVec::<[u32; 4]>::new(),
2486 params_with_generics.len(),
2487 );
2488 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
2489 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
2490 hir_generics.params.len(),
2491 );
2492 for (idx, param) in mismatched_params.iter_mut().enumerate() {
2493 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
2494 params_with_generics.iter_enumerated().zip(matched_inputs)
2495 {
2496 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
2497 generic_uses[param.generic].extend([param.idx, other_idx]);
2498 dependants[other_idx].push(idx as u32);
2499 param.deps.push(other_idx);
2500 }
2501 }
2502 }
2503
2504 for param in &mismatched_params {
2507 if let Some(deps_list) = listify(¶m.deps, |&dep| {
2508 params_with_generics[dep].1.display(dep.as_usize()).to_string()
2509 }) {
2510 spans.push_span_label(
2511 param.param.span(),
2512 format!(
2513 "this parameter needs to match the {} type of {deps_list}",
2514 self.resolve_vars_if_possible(
2515 formal_and_expected_inputs[param.deps[0]].1
2516 )
2517 .sort_string(self.tcx),
2518 ),
2519 );
2520 } else {
2521 spans.push_span_label(param.param.span(), "");
2523 }
2524 }
2525 for ((&(_, param), deps), &(_, expected_ty)) in
2527 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
2528 {
2529 if let Some(deps_list) = listify(deps, |&dep| {
2530 let param = &mismatched_params[dep as usize];
2531 param.param.display(param.idx.as_usize()).to_string()
2532 }) {
2533 spans.push_span_label(
2534 param.span(),
2535 format!(
2536 "{deps_list} need{} to match the {} type of this parameter",
2537 pluralize!((deps.len() != 1) as u32),
2538 self.resolve_vars_if_possible(expected_ty)
2539 .sort_string(self.tcx),
2540 ),
2541 );
2542 }
2543 }
2544 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
2546 uses.sort();
2547 uses.dedup();
2548 if let Some(param_list) = listify(uses, |&idx| {
2549 params_with_generics[idx].1.display(idx.as_usize()).to_string()
2550 }) {
2551 spans.push_span_label(
2552 param.span,
2553 format!(
2554 "{param_list} {} reference this parameter `{}`",
2555 if uses.len() == 2 { "both" } else { "all" },
2556 param.name.ident().name,
2557 ),
2558 );
2559 }
2560 }
2561 }
2562 }
2563 err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
2564 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
2565 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
2566 {
2567 let param = expected_idx
2568 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
2569 let (kind, span) = if let Some(param) = param {
2570 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] };
2573 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
2574 match self.tcx.hir_node_by_def_id(parent_def_id) {
2575 hir::Node::Item(item) => call_finder.visit_item(item),
2576 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
2577 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
2578 _ => {}
2579 }
2580 let typeck = self.typeck_results.borrow();
2581 for (rcvr, args) in call_finder.calls {
2582 if rcvr.hir_id.owner == typeck.hir_owner
2583 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
2584 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
2585 && def_id == *call_def_id
2586 && let Some(idx) = expected_idx
2587 && let Some(arg) = args.get(idx)
2588 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
2589 && let Some(expected_ty) = expected_ty
2590 && self.can_eq(self.param_env, arg_ty, expected_ty)
2591 {
2592 let mut sp: MultiSpan = vec![arg.span].into();
2593 sp.push_span_label(
2594 arg.span,
2595 format!("expected because this argument is of type `{arg_ty}`"),
2596 );
2597 sp.push_span_label(rcvr.span, "in this closure call");
2598 err.span_note(
2599 sp,
2600 format!(
2601 "expected because the closure was earlier called with an \
2602 argument of type `{arg_ty}`",
2603 ),
2604 );
2605 break;
2606 }
2607 }
2608
2609 ("closure parameter", param.span)
2610 } else {
2611 ("closure", self.tcx.def_span(def_id))
2612 };
2613 err.span_note(span, format!("{kind} defined here"));
2614 } else {
2615 err.span_note(
2616 self.tcx.def_span(def_id),
2617 format!("{} defined here", self.tcx.def_descr(def_id)),
2618 );
2619 }
2620 }
2621
2622 fn label_generic_mismatches(
2623 &self,
2624 err: &mut Diag<'_>,
2625 callable_def_id: Option<DefId>,
2626 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2627 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
2628 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2629 is_method: bool,
2630 ) {
2631 let Some(def_id) = callable_def_id else {
2632 return;
2633 };
2634
2635 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
2636 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2637 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
2638 if matched_inputs[idx].is_none() {
2639 continue;
2640 }
2641
2642 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
2643 else {
2644 continue;
2645 };
2646
2647 let Some(generic_param) = generic_param else {
2648 continue;
2649 };
2650
2651 let idxs_matched = params_with_generics
2652 .iter_enumerated()
2653 .filter(|&(other_idx, (other_generic_param, _))| {
2654 if other_idx == idx {
2655 return false;
2656 }
2657 let Some(other_generic_param) = other_generic_param else {
2658 return false;
2659 };
2660 if matched_inputs[other_idx].is_some() {
2661 return false;
2662 }
2663 other_generic_param == generic_param
2664 })
2665 .count();
2666
2667 if idxs_matched == 0 {
2668 continue;
2669 }
2670
2671 let expected_display_type = self
2672 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
2673 .sort_string(self.tcx);
2674 let label = if idxs_matched == params_with_generics.len() - 1 {
2675 format!(
2676 "expected all arguments to be this {} type because they need to match the type of this parameter",
2677 expected_display_type
2678 )
2679 } else {
2680 format!(
2681 "expected some other arguments to be {} {} type to match the type of this parameter",
2682 a_or_an(&expected_display_type),
2683 expected_display_type,
2684 )
2685 };
2686
2687 err.span_label(*matched_arg_span, label);
2688 }
2689 }
2690 }
2691
2692 fn get_hir_param_info(
2697 &self,
2698 def_id: DefId,
2699 is_method: bool,
2700 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2701 {
2702 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2703 hir::Node::TraitItem(&hir::TraitItem {
2704 generics,
2705 kind: hir::TraitItemKind::Fn(sig, trait_fn),
2706 ..
2707 }) => match trait_fn {
2708 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2709 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2710 },
2711 hir::Node::ImplItem(&hir::ImplItem {
2712 generics,
2713 kind: hir::ImplItemKind::Fn(sig, body),
2714 ..
2715 })
2716 | hir::Node::Item(&hir::Item {
2717 kind: hir::ItemKind::Fn { sig, generics, body, .. },
2718 ..
2719 }) => (sig, generics, Some(body), None),
2720 hir::Node::ForeignItem(&hir::ForeignItem {
2721 kind: hir::ForeignItemKind::Fn(sig, params, generics),
2722 ..
2723 }) => (sig, generics, None, Some(params)),
2724 _ => return None,
2725 };
2726
2727 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2730 if let hir::TyKind::Path(QPath::Resolved(
2731 _,
2732 &hir::Path { res: Res::Def(_, res_def_id), .. },
2733 )) = param.kind
2734 {
2735 generics
2736 .params
2737 .iter()
2738 .position(|param| param.def_id.to_def_id() == res_def_id)
2739 .map(GenericIdx::from_usize)
2740 } else {
2741 None
2742 }
2743 });
2744 match (body_id, params) {
2745 (Some(_), Some(_)) | (None, None) => unreachable!(),
2746 (Some(body), None) => {
2747 let params = self.tcx.hir_body(body).params;
2748 let params =
2749 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2750 debug_assert_eq!(params.len(), fn_inputs.len());
2751 Some((
2752 fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect(),
2753 generics,
2754 ))
2755 }
2756 (None, Some(params)) => {
2757 let params =
2758 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2759 debug_assert_eq!(params.len(), fn_inputs.len());
2760 Some((
2761 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2762 generics,
2763 ))
2764 }
2765 }
2766 }
2767}
2768
2769struct FindClosureArg<'tcx> {
2770 tcx: TyCtxt<'tcx>,
2771 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2772}
2773
2774impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2775 type NestedFilter = rustc_middle::hir::nested_filter::All;
2776
2777 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2778 self.tcx
2779 }
2780
2781 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2782 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2783 self.calls.push((rcvr, args));
2784 }
2785 hir::intravisit::walk_expr(self, ex);
2786 }
2787}
2788
2789#[derive(Clone, Copy)]
2790enum FnParam<'hir> {
2791 Param(&'hir hir::Param<'hir>),
2792 Ident(Option<Ident>),
2793}
2794
2795impl FnParam<'_> {
2796 fn span(&self) -> Span {
2797 match self {
2798 Self::Param(param) => param.span,
2799 Self::Ident(ident) => {
2800 if let Some(ident) = ident {
2801 ident.span
2802 } else {
2803 DUMMY_SP
2804 }
2805 }
2806 }
2807 }
2808
2809 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2810 struct D<'a>(FnParam<'a>, usize);
2811 impl fmt::Display for D<'_> {
2812 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2813 let unique_name = match self.0 {
2816 FnParam::Param(param)
2817 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2818 {
2819 Some(ident.name)
2820 }
2821 FnParam::Ident(ident)
2822 if let Some(ident) = ident
2823 && ident.name != kw::Underscore =>
2824 {
2825 Some(ident.name)
2826 }
2827 _ => None,
2828 };
2829 if let Some(unique_name) = unique_name {
2830 write!(f, "`{unique_name}`")
2831 } else {
2832 write!(f, "parameter #{}", self.1 + 1)
2833 }
2834 }
2835 }
2836 D(*self, idx)
2837 }
2838}