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