1use std::ops::Deref;
2use std::{fmt, iter};
3
4use itertools::Itertools;
5use rustc_data_structures::fx::FxIndexSet;
6use rustc_errors::codes::*;
7use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
8use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
9use rustc_hir::def_id::DefId;
10use rustc_hir::intravisit::Visitor;
11use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath, is_range_literal};
12use rustc_hir_analysis::check::potentially_plural_count;
13use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, PermitVariants};
14use rustc_index::IndexVec;
15use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace};
16use rustc_middle::ty::adjustment::AllowTwoPhase;
17use rustc_middle::ty::error::TypeError;
18use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
19use rustc_middle::{bug, span_bug};
20use rustc_session::Session;
21use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
22use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
23use rustc_trait_selection::infer::InferCtxtExt;
24use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
25use smallvec::SmallVec;
26use tracing::debug;
27use {rustc_ast as ast, rustc_hir as hir};
28
29use crate::Expectation::*;
30use crate::TupleArgumentsFlag::*;
31use crate::coercion::CoerceMany;
32use crate::errors::SuggestPtrNullMut;
33use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
34use crate::gather_locals::Declaration;
35use crate::inline_asm::InlineAsmCtxt;
36use crate::method::probe::IsSuggestion;
37use crate::method::probe::Mode::MethodCall;
38use crate::method::probe::ProbeScope::TraitsInScope;
39use crate::{
40 BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
41 TupleArgumentsFlag, errors, struct_span_code_err,
42};
43
44rustc_index::newtype_index! {
45 #[orderable]
46 #[debug_format = "GenericIdx({})"]
47 pub(crate) struct GenericIdx {}
48}
49
50#[derive(Clone, Copy, Default)]
51pub(crate) enum DivergingBlockBehavior {
52 #[default]
60 Never,
61
62 Unit,
71}
72
73impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
74 pub(in super::super) fn check_casts(&mut self) {
75 let mut deferred_cast_checks = self.root_ctxt.deferred_cast_checks.borrow_mut();
76 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
77 for cast in deferred_cast_checks.drain(..) {
78 let body_id = std::mem::replace(&mut self.body_id, cast.body_id);
79 cast.check(self);
80 self.body_id = body_id;
81 }
82 }
83
84 pub(in super::super) fn check_asms(&self) {
85 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
86 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
87 for (asm, hir_id) in deferred_asm_checks.drain(..) {
88 let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
89 InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
90 }
91 }
92
93 pub(in super::super) fn check_repeat_exprs(&self) {
94 let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
95 debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
96
97 let deferred_repeat_expr_checks = deferred_repeat_expr_checks
98 .drain(..)
99 .flat_map(|(element, element_ty, count)| {
100 match &element.kind {
104 hir::ExprKind::ConstBlock(..) => return None,
105 hir::ExprKind::Path(qpath) => {
106 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
107 if let Res::Def(DefKind::Const | DefKind::AssocConst, _) = res {
108 return None;
109 }
110 }
111 _ => {}
112 }
113
114 let count = self
119 .structurally_resolve_const(element.span, self.normalize(element.span, count));
120
121 if count.references_error() {
125 return None;
126 }
127
128 Some((element, element_ty, count))
129 })
130 .collect::<Vec<_>>();
136
137 let enforce_copy_bound = |element: &hir::Expr<'_>, element_ty| {
138 let is_constable = match element.kind {
142 hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
143 ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
144 traits::IsConstable::Fn
145 }
146 _ => traits::IsConstable::No,
147 },
148 hir::ExprKind::Path(qpath) => {
149 match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
150 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
151 _ => traits::IsConstable::No,
152 }
153 }
154 _ => traits::IsConstable::No,
155 };
156
157 let lang_item = self.tcx.require_lang_item(LangItem::Copy, element.span);
158 let code = traits::ObligationCauseCode::RepeatElementCopy {
159 is_constable,
160 elt_span: element.span,
161 };
162 self.require_type_meets(element_ty, element.span, code, lang_item);
163 };
164
165 for (element, element_ty, count) in deferred_repeat_expr_checks {
166 match count.kind() {
167 ty::ConstKind::Value(val) => {
168 if val.try_to_target_usize(self.tcx).is_none_or(|count| count > 1) {
169 enforce_copy_bound(element, element_ty)
170 } else {
171 }
174 }
175
176 ty::ConstKind::Param(_)
179 | ty::ConstKind::Expr(_)
180 | ty::ConstKind::Placeholder(_)
181 | ty::ConstKind::Unevaluated(_) => enforce_copy_bound(element, element_ty),
182
183 ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => {
184 unreachable!()
185 }
186 }
187 }
188 }
189
190 pub(in super::super) fn check_argument_types(
193 &self,
194 call_span: Span,
196 call_expr: &'tcx hir::Expr<'tcx>,
198 formal_input_tys: &[Ty<'tcx>],
200 formal_output: Ty<'tcx>,
201 expectation: Expectation<'tcx>,
203 provided_args: &'tcx [hir::Expr<'tcx>],
205 c_variadic: bool,
207 tuple_arguments: TupleArgumentsFlag,
209 fn_def_id: Option<DefId>,
211 ) {
212 let tcx = self.tcx;
213
214 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
229 self.register_wf_obligation(
230 fn_input_ty.into(),
231 arg_expr.span,
232 ObligationCauseCode::WellFormed(None),
233 );
234
235 self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
236 }
237
238 let formal_output = self.resolve_vars_with_obligations(formal_output);
243 let expected_input_tys: Option<Vec<_>> = expectation
244 .only_has_type(self)
245 .and_then(|expected_output| {
246 self.fudge_inference_if_ok(|| {
252 let ocx = ObligationCtxt::new(self);
253
254 let origin = self.misc(call_span);
259 ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
260
261 let formal_input_tys_ns;
262 let formal_input_tys = if self.next_trait_solver() {
263 formal_input_tys_ns = formal_input_tys
271 .iter()
272 .map(|&ty| {
273 if ty.is_ty_var() {
279 return ty;
280 }
281
282 let generalized_ty = self.next_ty_var(call_span);
283 ocx.eq(&origin, self.param_env, ty, generalized_ty).unwrap();
284 generalized_ty
285 })
286 .collect_vec();
287
288 formal_input_tys_ns.as_slice()
289 } else {
290 formal_input_tys
291 };
292
293 if !ocx.try_evaluate_obligations().is_empty() {
294 return Err(TypeError::Mismatch);
295 }
296
297 Ok(Some(
300 formal_input_tys
301 .iter()
302 .map(|&ty| self.resolve_vars_if_possible(ty))
303 .collect(),
304 ))
305 })
306 .ok()
307 })
308 .unwrap_or_default();
309
310 let mut err_code = E0061;
311
312 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
314 let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]);
315 match tuple_type.kind() {
316 ty::Tuple(arg_types) => {
318 if arg_types.len() != provided_args.len() {
320 err_code = E0057;
321 }
322 let expected_input_tys = match expected_input_tys {
323 Some(expected_input_tys) => match expected_input_tys.get(0) {
324 Some(ty) => match ty.kind() {
325 ty::Tuple(tys) => Some(tys.iter().collect()),
326 _ => None,
327 },
328 None => None,
329 },
330 None => None,
331 };
332 (arg_types.iter().collect(), expected_input_tys)
333 }
334 _ => {
335 let guar = struct_span_code_err!(
338 self.dcx(),
339 call_span,
340 E0059,
341 "cannot use call notation; the first type parameter \
342 for the function trait is neither a tuple nor unit"
343 )
344 .emit();
345 (self.err_args(provided_args.len(), guar), None)
346 }
347 }
348 } else {
349 (formal_input_tys.to_vec(), expected_input_tys)
350 };
351
352 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
354 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
355 expected_input_tys
356 } else {
357 formal_input_tys.clone()
358 };
359
360 let minimum_input_count = expected_input_tys.len();
361 let provided_arg_count = provided_args.len();
362
363 let demand_compatible = |idx| {
367 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
368 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
369 let provided_arg = &provided_args[idx];
370
371 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
372
373 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
377
378 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
379
380 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
384
385 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
389
390 let coerce_error =
391 self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
392 if coerce_error.is_some() {
393 return Compatibility::Incompatible(coerce_error);
394 }
395
396 let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
399 DefineOpaqueTypes::Yes,
400 formal_input_ty,
401 coerced_ty,
402 );
403
404 match formal_ty_error {
406 Ok(InferOk { obligations, value: () }) => {
407 self.register_predicates(obligations);
408 Compatibility::Compatible
409 }
410 Err(err) => Compatibility::Incompatible(Some(err)),
411 }
412 };
413
414 let mut compatibility_diagonal =
417 vec![Compatibility::Incompatible(None); provided_args.len()];
418
419 let mut call_appears_satisfied = if c_variadic {
424 provided_arg_count >= minimum_input_count
425 } else {
426 provided_arg_count == minimum_input_count
427 };
428
429 for check_closures in [false, true] {
435 if check_closures {
439 self.select_obligations_where_possible(|_| {})
440 }
441
442 for (idx, arg) in provided_args.iter().enumerate() {
445 if !check_closures {
449 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
450 }
451
452 if idx >= minimum_input_count {
458 continue;
459 }
460
461 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
467 !tcx.coroutine_is_async(closure.def_id.to_def_id())
468 } else {
469 false
470 };
471 if is_closure != check_closures {
472 continue;
473 }
474
475 let compatible = demand_compatible(idx);
476 let is_compatible = matches!(compatible, Compatibility::Compatible);
477 compatibility_diagonal[idx] = compatible;
478
479 if !is_compatible {
480 call_appears_satisfied = false;
481 }
482 }
483 }
484
485 if c_variadic && provided_arg_count < minimum_input_count {
486 err_code = E0060;
487 }
488
489 for arg in provided_args.iter().skip(minimum_input_count) {
490 let arg_ty = self.check_expr(arg);
492
493 if c_variadic {
498 fn variadic_error<'tcx>(
499 sess: &'tcx Session,
500 span: Span,
501 ty: Ty<'tcx>,
502 cast_ty: &str,
503 ) {
504 sess.dcx().emit_err(errors::PassToVariadicFunction {
505 span,
506 ty,
507 cast_ty,
508 sugg_span: span.shrink_to_hi(),
509 teach: sess.teach(E0617),
510 });
511 }
512
513 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
516 match arg_ty.kind() {
517 ty::Float(ty::FloatTy::F32) => {
518 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
519 }
520 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
521 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
522 }
523 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
524 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
525 }
526 ty::FnDef(..) => {
527 let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
528 let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
529
530 let fn_item_spa = arg.span;
531 tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
532 span: fn_item_spa,
533 sugg_span: fn_item_spa.shrink_to_hi(),
534 replace: fn_ptr,
535 });
536 }
537 _ => {}
538 }
539 }
540 }
541
542 if !call_appears_satisfied {
543 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
544 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
545 minimum_input_count
546 } else {
547 provided_arg_count
548 }));
549 debug_assert_eq!(
550 formal_input_tys.len(),
551 expected_input_tys.len(),
552 "expected formal_input_tys to be the same size as expected_input_tys"
553 );
554 let formal_and_expected_inputs = IndexVec::from_iter(
555 formal_input_tys
556 .iter()
557 .copied()
558 .zip_eq(expected_input_tys.iter().copied())
559 .map(|vars| self.resolve_vars_if_possible(vars)),
560 );
561
562 self.report_arg_errors(
563 compatibility_diagonal,
564 formal_and_expected_inputs,
565 provided_args,
566 c_variadic,
567 err_code,
568 fn_def_id,
569 call_span,
570 call_expr,
571 tuple_arguments,
572 );
573 }
574 }
575
576 fn check_place_expr_if_unsized(&self, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
582 if self.tcx.features().unsized_fn_params() && !expr.is_syntactic_place_expr() {
583 self.require_type_is_sized(
584 ty,
585 expr.span,
586 ObligationCauseCode::UnsizedNonPlaceExpr(expr.span),
587 );
588 }
589 }
590
591 fn report_arg_errors(
592 &self,
593 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
594 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
595 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
596 c_variadic: bool,
597 err_code: ErrCode,
598 fn_def_id: Option<DefId>,
599 call_span: Span,
600 call_expr: &'tcx hir::Expr<'tcx>,
601 tuple_arguments: TupleArgumentsFlag,
602 ) -> ErrorGuaranteed {
603 let mut fn_call_diag_ctxt = FnCallDiagCtxt::new(
606 self,
607 compatibility_diagonal,
608 formal_and_expected_inputs,
609 provided_args,
610 c_variadic,
611 err_code,
612 fn_def_id,
613 call_span,
614 call_expr,
615 tuple_arguments,
616 );
617
618 if let Some(err) = fn_call_diag_ctxt.check_wrap_args_in_tuple() {
620 return err;
621 }
622
623 if let Some(fallback_error) = fn_call_diag_ctxt.ensure_has_errors() {
624 return fallback_error;
625 }
626
627 if let Some(err) = fn_call_diag_ctxt.filter_out_invalid_arguments()
642 && fn_call_diag_ctxt.errors.is_empty()
643 {
644 return err;
646 }
647
648 assert!(!fn_call_diag_ctxt.errors.is_empty());
649
650 if let Some(err) = fn_call_diag_ctxt.check_single_incompatible() {
652 return err;
653 }
654
655 fn_call_diag_ctxt.maybe_optimize_extra_arg_suggestion();
664
665 let mut err = fn_call_diag_ctxt.initial_final_diagnostic();
666 fn_call_diag_ctxt.suggest_confusable(&mut err);
667
668 let (mut suggestions, labels, suggestion_text) =
671 fn_call_diag_ctxt.labels_and_suggestion_text(&mut err);
672
673 fn_call_diag_ctxt.label_generic_mismatches(&mut err);
674 fn_call_diag_ctxt.append_arguments_changes(&mut suggestions);
675
676 if labels.len() <= 5 {
678 for (span, label) in labels {
679 err.span_label(span, label);
680 }
681 }
682
683 fn_call_diag_ctxt.label_fn_like(
685 &mut err,
686 fn_def_id,
687 fn_call_diag_ctxt.callee_ty,
688 call_expr,
689 None,
690 None,
691 &fn_call_diag_ctxt.matched_inputs,
692 &fn_call_diag_ctxt.formal_and_expected_inputs,
693 fn_call_diag_ctxt.call_metadata.is_method,
694 tuple_arguments,
695 );
696
697 if let Some(suggestion_message) =
699 FnCallDiagCtxt::format_suggestion_text(&mut err, suggestions, suggestion_text)
700 && !fn_call_diag_ctxt.call_is_in_macro()
701 {
702 let (suggestion_span, suggestion_code) = fn_call_diag_ctxt.suggestion_code();
703
704 err.span_suggestion_verbose(
705 suggestion_span,
706 suggestion_message,
707 suggestion_code,
708 Applicability::HasPlaceholders,
709 );
710 }
711
712 err.emit()
713 }
714
715 fn suggest_ptr_null_mut(
716 &self,
717 expected_ty: Ty<'tcx>,
718 provided_ty: Ty<'tcx>,
719 arg: &hir::Expr<'tcx>,
720 err: &mut Diag<'_>,
721 ) {
722 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
723 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
724 && let hir::ExprKind::Call(callee, _) = arg.kind
725 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
726 && let Res::Def(_, def_id) = path.res
727 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
728 {
729 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
732 }
733 }
734
735 pub(in super::super) fn check_expr_lit(
737 &self,
738 lit: &hir::Lit,
739 expected: Expectation<'tcx>,
740 ) -> Ty<'tcx> {
741 let tcx = self.tcx;
742
743 match lit.node {
744 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
745 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
746 tcx,
747 tcx.lifetimes.re_static,
748 Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
749 ),
750 ast::LitKind::Byte(_) => tcx.types.u8,
751 ast::LitKind::Char(_) => tcx.types.char,
752 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, t),
753 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, t),
754 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
755 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
756 ty::Int(_) | ty::Uint(_) => Some(ty),
757 ty::Char => Some(tcx.types.u8),
761 ty::RawPtr(..) => Some(tcx.types.usize),
762 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
763 &ty::Pat(base, _) if base.is_integral() => {
764 let layout = tcx
765 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
766 .ok()?;
767 assert!(!layout.uninhabited);
768
769 match layout.backend_repr {
770 rustc_abi::BackendRepr::Scalar(scalar) => {
771 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
772 }
773 _ => unreachable!(),
774 }
775 }
776 _ => None,
777 });
778 opt_ty.unwrap_or_else(|| self.next_int_var())
779 }
780 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => Ty::new_float(tcx, t),
781 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
782 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
783 ty::Float(_) => Some(ty),
784 _ => None,
785 });
786 opt_ty.unwrap_or_else(|| self.next_float_var())
787 }
788 ast::LitKind::Bool(_) => tcx.types.bool,
789 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
790 tcx,
791 tcx.lifetimes.re_static,
792 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, lit.span)).skip_binder(),
793 ),
794 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
795 }
796 }
797
798 pub(crate) fn check_struct_path(
799 &self,
800 qpath: &QPath<'tcx>,
801 hir_id: HirId,
802 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
803 let path_span = qpath.span();
804 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
805 let variant = match def {
806 Res::Err => {
807 let guar =
808 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
809 self.set_tainted_by_errors(guar);
810 return Err(guar);
811 }
812 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
813 Some(adt) => {
814 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
815 }
816 _ => bug!("unexpected type: {:?}", ty.normalized),
817 },
818 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
819 | Res::SelfTyParam { .. }
820 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
821 Some(adt) if !adt.is_enum() => {
822 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
823 }
824 _ => None,
825 },
826 _ => bug!("unexpected definition: {:?}", def),
827 };
828
829 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
830 debug!("check_struct_path: did={:?} args={:?}", did, args);
831
832 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
834
835 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
837
838 Ok((variant, ty.normalized))
839 } else {
840 Err(match *ty.normalized.kind() {
841 ty::Error(guar) => {
842 guar
847 }
848 _ => struct_span_code_err!(
849 self.dcx(),
850 path_span,
851 E0071,
852 "expected struct, variant or union type, found {}",
853 ty.normalized.sort_string(self.tcx)
854 )
855 .with_span_label(path_span, "not a struct")
856 .emit(),
857 })
858 }
859 }
860
861 fn check_decl_initializer(
862 &self,
863 hir_id: HirId,
864 pat: &'tcx hir::Pat<'tcx>,
865 init: &'tcx hir::Expr<'tcx>,
866 ) -> Ty<'tcx> {
867 let ref_bindings = pat.contains_explicit_ref_binding();
872
873 let local_ty = self.local_ty(init.span, hir_id);
874 if let Some(m) = ref_bindings {
875 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
884 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
885 self.emit_type_mismatch_suggestions(
886 &mut diag,
887 init.peel_drop_temps(),
888 init_ty,
889 local_ty,
890 None,
891 None,
892 );
893 diag.emit();
894 }
895 init_ty
896 } else {
897 self.check_expr_coercible_to_type(init, local_ty, None)
898 }
899 }
900
901 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
902 let decl_ty = self.local_ty(decl.span, decl.hir_id);
904
905 if let Some(init) = decl.init {
907 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
908 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
909 }
910
911 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
913 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
915 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
916 } _ => (None, None), };
919
920 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
922 let pat_ty = self.node_ty(decl.pat.hir_id);
923 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
924
925 if let Some(blk) = decl.origin.try_get_else() {
926 let previous_diverges = self.diverges.get();
927 let else_ty = self.check_expr_block(blk, NoExpectation);
928 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
929 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
930 {
931 err.emit();
932 }
933 self.diverges.set(previous_diverges);
934 }
935 decl_ty
936 }
937
938 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
940 GatherLocalsVisitor::gather_from_local(self, local);
941
942 let ty = self.check_decl(local.into());
943 self.write_ty(local.hir_id, ty);
944 if local.pat.is_never_pattern() {
945 self.diverges.set(Diverges::Always {
946 span: local.pat.span,
947 custom_note: Some("any code following a never pattern is unreachable"),
948 });
949 }
950 }
951
952 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
953 match stmt.kind {
955 hir::StmtKind::Item(..) => return,
956 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
957 }
958
959 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
960
961 let old_diverges = self.diverges.replace(Diverges::Maybe);
963
964 match stmt.kind {
965 hir::StmtKind::Let(l) => {
966 self.check_decl_local(l);
967 }
968 hir::StmtKind::Item(_) => {}
970 hir::StmtKind::Expr(expr) => {
971 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
973 if self.is_next_stmt_expr_continuation(stmt.hir_id)
974 && let hir::ExprKind::Match(..) | hir::ExprKind::If(..) = expr.kind
975 {
976 err.multipart_suggestion(
981 "parentheses are required to parse this as an expression",
982 vec![
983 (expr.span.shrink_to_lo(), "(".to_string()),
984 (expr.span.shrink_to_hi(), ")".to_string()),
985 ],
986 Applicability::MachineApplicable,
987 );
988 } else if expr.can_have_side_effects() {
989 self.suggest_semicolon_at_end(expr.span, err);
990 }
991 });
992 }
993 hir::StmtKind::Semi(expr) => {
994 let ty = self.check_expr(expr);
995 self.check_place_expr_if_unsized(ty, expr);
996 }
997 }
998
999 self.diverges.set(self.diverges.get() | old_diverges);
1001 }
1002
1003 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1004 let unit = self.tcx.types.unit;
1005 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1006
1007 if !ty.is_never() {
1010 self.demand_suptype(blk.span, unit, ty);
1011 }
1012 }
1013
1014 pub(in super::super) fn check_expr_block(
1015 &self,
1016 blk: &'tcx hir::Block<'tcx>,
1017 expected: Expectation<'tcx>,
1018 ) -> Ty<'tcx> {
1019 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1036 let coerce = if blk.targeted_by_break {
1037 CoerceMany::new(coerce_to_ty)
1038 } else {
1039 CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
1040 };
1041
1042 let prev_diverges = self.diverges.get();
1043 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1044
1045 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1046 for s in blk.stmts {
1047 self.check_stmt(s);
1048 }
1049
1050 let tail_expr_ty =
1053 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1054
1055 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1056 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1057 let coerce = ctxt.coerce.as_mut().unwrap();
1058 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1059 let span = self.get_expr_coercion_span(tail_expr);
1060 let cause = self.cause(
1061 span,
1062 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1063 );
1064 let ty_for_diagnostic = coerce.merged_ty();
1065 coerce.coerce_inner(
1069 self,
1070 &cause,
1071 Some(tail_expr),
1072 tail_expr_ty,
1073 |diag| {
1074 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1075 },
1076 false,
1077 );
1078 } else {
1079 if !self.diverges.get().is_always()
1090 || matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1091 {
1092 let mut sp = blk.span;
1098 let mut fn_span = None;
1099 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1100 let ret_sp = decl.output.span();
1101 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1102 if block_sp == blk.span {
1106 sp = ret_sp;
1107 fn_span = self.tcx.def_ident_span(fn_def_id);
1108 }
1109 }
1110 }
1111 coerce.coerce_forced_unit(
1112 self,
1113 &self.misc(sp),
1114 |err| {
1115 if let Some(expected_ty) = expected.only_has_type(self) {
1116 if blk.stmts.is_empty() && blk.expr.is_none() {
1117 self.suggest_boxing_when_appropriate(
1118 err,
1119 blk.span,
1120 blk.hir_id,
1121 expected_ty,
1122 self.tcx.types.unit,
1123 );
1124 }
1125 if !self.err_ctxt().consider_removing_semicolon(
1126 blk,
1127 expected_ty,
1128 err,
1129 ) {
1130 self.err_ctxt().consider_returning_binding(
1131 blk,
1132 expected_ty,
1133 err,
1134 );
1135 }
1136 if expected_ty == self.tcx.types.bool {
1137 if let hir::Block {
1142 stmts:
1143 [
1144 hir::Stmt {
1145 kind:
1146 hir::StmtKind::Let(hir::LetStmt {
1147 source: hir::LocalSource::AssignDesugar,
1148 ..
1149 }),
1150 ..
1151 },
1152 hir::Stmt {
1153 kind:
1154 hir::StmtKind::Expr(hir::Expr {
1155 kind: hir::ExprKind::Assign(lhs, ..),
1156 ..
1157 }),
1158 ..
1159 },
1160 ],
1161 ..
1162 } = blk
1163 {
1164 self.comes_from_while_condition(blk.hir_id, |_| {
1165 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
1169
1170 if !lhs.is_syntactic_place_expr()
1171 || res.references_error()
1172 {
1173 err.downgrade_to_delayed_bug();
1174 }
1175 })
1176 }
1177 }
1178 }
1179 if let Some(fn_span) = fn_span {
1180 err.span_label(
1181 fn_span,
1182 "implicitly returns `()` as its body has no tail or `return` \
1183 expression",
1184 );
1185 }
1186 },
1187 false,
1188 );
1189 }
1190 }
1191 });
1192
1193 if ctxt.may_break {
1194 self.diverges.set(prev_diverges);
1197 }
1198
1199 let ty = ctxt.coerce.unwrap().complete(self);
1200
1201 self.write_ty(blk.hir_id, ty);
1202
1203 ty
1204 }
1205
1206 fn parent_item_span(&self, id: HirId) -> Option<Span> {
1207 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
1208 match node {
1209 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
1210 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1211 let body = self.tcx.hir_body(body_id);
1212 if let ExprKind::Block(block, _) = &body.value.kind {
1213 return Some(block.span);
1214 }
1215 }
1216 _ => {}
1217 }
1218 None
1219 }
1220
1221 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1229 let check_in_progress = |elem: &hir::Expr<'_>| {
1230 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
1231 |_| match elem.kind {
1232 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
1234 _ => elem.span,
1235 },
1236 )
1237 };
1238
1239 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
1240 && let Some(rslt) = check_in_progress(el)
1241 {
1242 return rslt;
1243 }
1244
1245 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1246 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1247 if let Some(span) = iter.next() {
1248 if iter.next().is_none() {
1249 return span;
1250 }
1251 }
1252 }
1253
1254 expr.span
1255 }
1256
1257 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
1258 if let Err(guar) = ty.error_reported() {
1259 struct OverwritePatternsWithError {
1260 pat_hir_ids: Vec<hir::HirId>,
1261 }
1262 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
1263 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
1264 self.pat_hir_ids.push(p.hir_id);
1265 hir::intravisit::walk_pat(self, p);
1266 }
1267 }
1268 let err = Ty::new_error(self.tcx, guar);
1270 self.write_ty(hir_id, err);
1271 self.write_ty(pat.hir_id, err);
1272 let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
1273 hir::intravisit::walk_pat(&mut visitor, pat);
1274 for hir_id in visitor.pat_hir_ids {
1277 self.write_ty(hir_id, err);
1278 }
1279 self.locals.borrow_mut().insert(hir_id, err);
1280 self.locals.borrow_mut().insert(pat.hir_id, err);
1281 }
1282 }
1283
1284 fn finish_resolving_struct_path(
1287 &self,
1288 qpath: &QPath<'tcx>,
1289 path_span: Span,
1290 hir_id: HirId,
1291 ) -> (Res, LoweredTy<'tcx>) {
1292 match *qpath {
1293 QPath::Resolved(ref maybe_qself, path) => {
1294 let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
1295 let ty = self.lowerer().lower_resolved_ty_path(
1296 self_ty,
1297 path,
1298 hir_id,
1299 PermitVariants::Yes,
1300 );
1301 (path.res, LoweredTy::from_raw(self, path_span, ty))
1302 }
1303 QPath::TypeRelative(hir_self_ty, segment) => {
1304 let self_ty = self.lower_ty(hir_self_ty);
1305
1306 let result = self.lowerer().lower_type_relative_ty_path(
1307 self_ty.raw,
1308 hir_self_ty,
1309 segment,
1310 hir_id,
1311 path_span,
1312 PermitVariants::Yes,
1313 );
1314 let ty = result
1315 .map(|(ty, _, _)| ty)
1316 .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
1317 let ty = LoweredTy::from_raw(self, path_span, ty);
1318 let result = result.map(|(_, kind, def_id)| (kind, def_id));
1319
1320 self.write_resolution(hir_id, result);
1322
1323 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1324 }
1325 }
1326 }
1327
1328 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
1335 &self,
1336 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1337 ) {
1338 let mut remap_cause = FxIndexSet::default();
1344 let mut not_adjusted = vec![];
1345
1346 for error in errors {
1347 let before_span = error.obligation.cause.span;
1348 if self.adjust_fulfillment_error_for_expr_obligation(error)
1349 || before_span != error.obligation.cause.span
1350 {
1351 remap_cause.insert((
1352 before_span,
1353 error.obligation.predicate,
1354 error.obligation.cause.clone(),
1355 ));
1356 } else {
1357 not_adjusted.push(error);
1360 }
1361 }
1362
1363 for error in not_adjusted {
1371 for (span, predicate, cause) in &remap_cause {
1372 if *predicate == error.obligation.predicate
1373 && span.contains(error.obligation.cause.span)
1374 {
1375 error.obligation.cause = cause.clone();
1376 continue;
1377 }
1378 }
1379 }
1380 }
1381
1382 fn label_fn_like(
1383 &self,
1384 err: &mut Diag<'_>,
1385 callable_def_id: Option<DefId>,
1386 callee_ty: Option<Ty<'tcx>>,
1387 call_expr: &'tcx hir::Expr<'tcx>,
1388 expected_ty: Option<Ty<'tcx>>,
1389 expected_idx: Option<usize>,
1391 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1392 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1393 is_method: bool,
1394 tuple_arguments: TupleArgumentsFlag,
1395 ) {
1396 let Some(mut def_id) = callable_def_id else {
1397 return;
1398 };
1399
1400 if tuple_arguments == TupleArguments
1405 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1406 && let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
1411 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1412 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
1414 && let Some(callee_ty) = callee_ty
1415 {
1416 let callee_ty = callee_ty.peel_refs();
1417 match *callee_ty.kind() {
1418 ty::Param(param) => {
1419 let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
1420 if param.kind.is_synthetic() {
1421 def_id = param.def_id;
1423 } else {
1424 let instantiated = self
1427 .tcx
1428 .explicit_predicates_of(self.body_id)
1429 .instantiate_identity(self.tcx);
1430 for (predicate, span) in instantiated {
1434 if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder()
1435 && pred.self_ty().peel_refs() == callee_ty
1436 && self.tcx.is_fn_trait(pred.def_id())
1437 {
1438 err.span_note(span, "callable defined here");
1439 return;
1440 }
1441 }
1442 }
1443 }
1444 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
1445 | ty::Closure(new_def_id, _)
1446 | ty::FnDef(new_def_id, _) => {
1447 def_id = new_def_id;
1448 }
1449 _ => {
1450 let new_def_id = self.probe(|_| {
1452 let trait_ref = ty::TraitRef::new(
1453 self.tcx,
1454 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
1455 [callee_ty, self.next_ty_var(DUMMY_SP)],
1456 );
1457 let obligation = traits::Obligation::new(
1458 self.tcx,
1459 traits::ObligationCause::dummy(),
1460 self.param_env,
1461 trait_ref,
1462 );
1463 match SelectionContext::new(self).select(&obligation) {
1464 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1465 Some(impl_source.impl_def_id)
1466 }
1467 _ => None,
1468 }
1469 });
1470 if let Some(new_def_id) = new_def_id {
1471 def_id = new_def_id;
1472 } else {
1473 return;
1474 }
1475 }
1476 }
1477 }
1478
1479 if let Some(def_span) = self.tcx.def_ident_span(def_id)
1480 && !def_span.is_dummy()
1481 {
1482 let mut spans: MultiSpan = def_span.into();
1483 if let Some((params_with_generics, hir_generics)) =
1484 self.get_hir_param_info(def_id, is_method)
1485 {
1486 struct MismatchedParam<'a> {
1487 idx: ExpectedIdx,
1488 generic: GenericIdx,
1489 param: &'a FnParam<'a>,
1490 deps: SmallVec<[ExpectedIdx; 4]>,
1491 }
1492
1493 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
1494 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
1496 if let Some(expected_idx) = expected_idx {
1497 let expected_idx = ExpectedIdx::from_usize(expected_idx);
1498 let &(expected_generic, ref expected_param) =
1499 ¶ms_with_generics[expected_idx];
1500 if let Some(expected_generic) = expected_generic {
1501 mismatched_params.push(MismatchedParam {
1502 idx: expected_idx,
1503 generic: expected_generic,
1504 param: expected_param,
1505 deps: SmallVec::new(),
1506 });
1507 } else {
1508 spans.push_span_label(expected_param.span(), "");
1510 }
1511 } else {
1512 mismatched_params.extend(
1513 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
1514 |((idx, &(generic, ref param)), matched_idx)| {
1515 if matched_idx.is_some() {
1516 None
1517 } else if let Some(generic) = generic {
1518 Some(MismatchedParam {
1519 idx,
1520 generic,
1521 param,
1522 deps: SmallVec::new(),
1523 })
1524 } else {
1525 spans.push_span_label(param.span(), "");
1527 None
1528 }
1529 },
1530 ),
1531 );
1532 }
1533
1534 if !mismatched_params.is_empty() {
1535 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
1538 |_| SmallVec::<[u32; 4]>::new(),
1539 params_with_generics.len(),
1540 );
1541 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
1542 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
1543 hir_generics.params.len(),
1544 );
1545 for (idx, param) in mismatched_params.iter_mut().enumerate() {
1546 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
1547 params_with_generics.iter_enumerated().zip(matched_inputs)
1548 {
1549 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
1550 generic_uses[param.generic].extend([param.idx, other_idx]);
1551 dependants[other_idx].push(idx as u32);
1552 param.deps.push(other_idx);
1553 }
1554 }
1555 }
1556
1557 for param in &mismatched_params {
1560 if let Some(deps_list) = listify(¶m.deps, |&dep| {
1561 params_with_generics[dep].1.display(dep.as_usize()).to_string()
1562 }) {
1563 spans.push_span_label(
1564 param.param.span(),
1565 format!(
1566 "this parameter needs to match the {} type of {deps_list}",
1567 self.resolve_vars_if_possible(
1568 formal_and_expected_inputs[param.deps[0]].1
1569 )
1570 .sort_string(self.tcx),
1571 ),
1572 );
1573 } else {
1574 spans.push_span_label(param.param.span(), "");
1576 }
1577 }
1578 for ((&(_, param), deps), &(_, expected_ty)) in
1580 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
1581 {
1582 if let Some(deps_list) = listify(deps, |&dep| {
1583 let param = &mismatched_params[dep as usize];
1584 param.param.display(param.idx.as_usize()).to_string()
1585 }) {
1586 spans.push_span_label(
1587 param.span(),
1588 format!(
1589 "{deps_list} need{} to match the {} type of this parameter",
1590 pluralize!((deps.len() != 1) as u32),
1591 self.resolve_vars_if_possible(expected_ty)
1592 .sort_string(self.tcx),
1593 ),
1594 );
1595 }
1596 }
1597 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
1599 uses.sort();
1600 uses.dedup();
1601 if let Some(param_list) = listify(uses, |&idx| {
1602 params_with_generics[idx].1.display(idx.as_usize()).to_string()
1603 }) {
1604 spans.push_span_label(
1605 param.span,
1606 format!(
1607 "{param_list} {} reference this parameter `{}`",
1608 if uses.len() == 2 { "both" } else { "all" },
1609 param.name.ident().name,
1610 ),
1611 );
1612 }
1613 }
1614 }
1615 }
1616 err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
1617 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
1618 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
1619 {
1620 let param = expected_idx
1621 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
1622 let (kind, span) = if let Some(param) = param {
1623 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] };
1626 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
1627 match self.tcx.hir_node_by_def_id(parent_def_id) {
1628 hir::Node::Item(item) => call_finder.visit_item(item),
1629 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
1630 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
1631 _ => {}
1632 }
1633 let typeck = self.typeck_results.borrow();
1634 for (rcvr, args) in call_finder.calls {
1635 if rcvr.hir_id.owner == typeck.hir_owner
1636 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
1637 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
1638 && def_id == *call_def_id
1639 && let Some(idx) = expected_idx
1640 && let Some(arg) = args.get(idx)
1641 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
1642 && let Some(expected_ty) = expected_ty
1643 && self.can_eq(self.param_env, arg_ty, expected_ty)
1644 {
1645 let mut sp: MultiSpan = vec![arg.span].into();
1646 sp.push_span_label(
1647 arg.span,
1648 format!("expected because this argument is of type `{arg_ty}`"),
1649 );
1650 sp.push_span_label(rcvr.span, "in this closure call");
1651 err.span_note(
1652 sp,
1653 format!(
1654 "expected because the closure was earlier called with an \
1655 argument of type `{arg_ty}`",
1656 ),
1657 );
1658 break;
1659 }
1660 }
1661
1662 ("closure parameter", param.span)
1663 } else {
1664 ("closure", self.tcx.def_span(def_id))
1665 };
1666 err.span_note(span, format!("{kind} defined here"));
1667 } else {
1668 err.span_note(
1669 self.tcx.def_span(def_id),
1670 format!("{} defined here", self.tcx.def_descr(def_id)),
1671 );
1672 }
1673 }
1674
1675 fn label_generic_mismatches(
1676 &self,
1677 err: &mut Diag<'_>,
1678 callable_def_id: Option<DefId>,
1679 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1680 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
1681 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1682 is_method: bool,
1683 ) {
1684 let Some(def_id) = callable_def_id else {
1685 return;
1686 };
1687
1688 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
1689 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
1690 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
1691 if matched_inputs[idx].is_none() {
1692 continue;
1693 }
1694
1695 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
1696 else {
1697 continue;
1698 };
1699
1700 let Some(generic_param) = generic_param else {
1701 continue;
1702 };
1703
1704 let idxs_matched = params_with_generics
1705 .iter_enumerated()
1706 .filter(|&(other_idx, (other_generic_param, _))| {
1707 if other_idx == idx {
1708 return false;
1709 }
1710 let Some(other_generic_param) = other_generic_param else {
1711 return false;
1712 };
1713 if matched_inputs[other_idx].is_some() {
1714 return false;
1715 }
1716 other_generic_param == generic_param
1717 })
1718 .count();
1719
1720 if idxs_matched == 0 {
1721 continue;
1722 }
1723
1724 let expected_display_type = self
1725 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
1726 .sort_string(self.tcx);
1727 let label = if idxs_matched == params_with_generics.len() - 1 {
1728 format!(
1729 "expected all arguments to be this {} type because they need to match the type of this parameter",
1730 expected_display_type
1731 )
1732 } else {
1733 format!(
1734 "expected some other arguments to be {} {} type to match the type of this parameter",
1735 a_or_an(&expected_display_type),
1736 expected_display_type,
1737 )
1738 };
1739
1740 err.span_label(*matched_arg_span, label);
1741 }
1742 }
1743 }
1744
1745 fn get_hir_param_info(
1750 &self,
1751 def_id: DefId,
1752 is_method: bool,
1753 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
1754 {
1755 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
1756 hir::Node::TraitItem(&hir::TraitItem {
1757 generics,
1758 kind: hir::TraitItemKind::Fn(sig, trait_fn),
1759 ..
1760 }) => match trait_fn {
1761 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
1762 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
1763 },
1764 hir::Node::ImplItem(&hir::ImplItem {
1765 generics,
1766 kind: hir::ImplItemKind::Fn(sig, body),
1767 ..
1768 })
1769 | hir::Node::Item(&hir::Item {
1770 kind: hir::ItemKind::Fn { sig, generics, body, .. },
1771 ..
1772 }) => (sig, generics, Some(body), None),
1773 hir::Node::ForeignItem(&hir::ForeignItem {
1774 kind: hir::ForeignItemKind::Fn(sig, params, generics),
1775 ..
1776 }) => (sig, generics, None, Some(params)),
1777 _ => return None,
1778 };
1779
1780 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
1783 if let hir::TyKind::Path(QPath::Resolved(
1784 _,
1785 &hir::Path { res: Res::Def(_, res_def_id), .. },
1786 )) = param.kind
1787 {
1788 generics
1789 .params
1790 .iter()
1791 .position(|param| param.def_id.to_def_id() == res_def_id)
1792 .map(GenericIdx::from_usize)
1793 } else {
1794 None
1795 }
1796 });
1797 match (body_id, params) {
1798 (Some(_), Some(_)) | (None, None) => unreachable!(),
1799 (Some(body), None) => {
1800 let params = self.tcx.hir_body(body).params;
1801 let params =
1802 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
1803 debug_assert_eq!(params.len(), fn_inputs.len());
1804 Some((fn_inputs.zip(params.iter().map(FnParam::Param)).collect(), generics))
1805 }
1806 (None, Some(params)) => {
1807 let params =
1808 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
1809 debug_assert_eq!(params.len(), fn_inputs.len());
1810 Some((
1811 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
1812 generics,
1813 ))
1814 }
1815 }
1816 }
1817}
1818
1819struct FindClosureArg<'tcx> {
1820 tcx: TyCtxt<'tcx>,
1821 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
1822}
1823
1824impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
1825 type NestedFilter = rustc_middle::hir::nested_filter::All;
1826
1827 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
1828 self.tcx
1829 }
1830
1831 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
1832 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
1833 self.calls.push((rcvr, args));
1834 }
1835 hir::intravisit::walk_expr(self, ex);
1836 }
1837}
1838
1839#[derive(Clone, Copy)]
1840enum FnParam<'hir> {
1841 Param(&'hir hir::Param<'hir>),
1842 Ident(Option<Ident>),
1843}
1844
1845impl FnParam<'_> {
1846 fn span(&self) -> Span {
1847 match self {
1848 Self::Param(param) => param.span,
1849 Self::Ident(ident) => {
1850 if let Some(ident) = ident {
1851 ident.span
1852 } else {
1853 DUMMY_SP
1854 }
1855 }
1856 }
1857 }
1858
1859 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
1860 struct D<'a>(FnParam<'a>, usize);
1861 impl fmt::Display for D<'_> {
1862 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1863 let unique_name = match self.0 {
1866 FnParam::Param(param)
1867 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
1868 {
1869 Some(ident.name)
1870 }
1871 FnParam::Ident(ident)
1872 if let Some(ident) = ident
1873 && ident.name != kw::Underscore =>
1874 {
1875 Some(ident.name)
1876 }
1877 _ => None,
1878 };
1879 if let Some(unique_name) = unique_name {
1880 write!(f, "`{unique_name}`")
1881 } else {
1882 write!(f, "parameter #{}", self.1 + 1)
1883 }
1884 }
1885 }
1886 D(*self, idx)
1887 }
1888}
1889
1890struct FnCallDiagCtxt<'a, 'b, 'tcx> {
1891 arg_matching_ctxt: ArgMatchingCtxt<'a, 'b, 'tcx>,
1892 errors: Vec<Error<'tcx>>,
1893 matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1894}
1895
1896impl<'a, 'b, 'tcx> Deref for FnCallDiagCtxt<'a, 'b, 'tcx> {
1897 type Target = ArgMatchingCtxt<'a, 'b, 'tcx>;
1898
1899 fn deref(&self) -> &Self::Target {
1900 &self.arg_matching_ctxt
1901 }
1902}
1903
1904enum ArgumentsFormatting {
1906 SingleLine,
1907 Multiline { fallback_indent: String, brace_indent: String },
1908}
1909
1910impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> {
1911 fn new(
1912 arg: &'a FnCtxt<'b, 'tcx>,
1913 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
1914 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1915 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
1916 c_variadic: bool,
1917 err_code: ErrCode,
1918 fn_def_id: Option<DefId>,
1919 call_span: Span,
1920 call_expr: &'tcx Expr<'tcx>,
1921 tuple_arguments: TupleArgumentsFlag,
1922 ) -> Self {
1923 let arg_matching_ctxt = ArgMatchingCtxt::new(
1924 arg,
1925 compatibility_diagonal,
1926 formal_and_expected_inputs,
1927 provided_args,
1928 c_variadic,
1929 err_code,
1930 fn_def_id,
1931 call_span,
1932 call_expr,
1933 tuple_arguments,
1934 );
1935
1936 let (errors, matched_inputs) = ArgMatrix::new(
1943 arg_matching_ctxt.provided_args.len(),
1944 arg_matching_ctxt.formal_and_expected_inputs.len(),
1945 |provided, expected| arg_matching_ctxt.check_compatible(provided, expected),
1946 )
1947 .find_errors();
1948
1949 FnCallDiagCtxt { arg_matching_ctxt, errors, matched_inputs }
1950 }
1951
1952 fn check_wrap_args_in_tuple(&self) -> Option<ErrorGuaranteed> {
1953 if let Some((mismatch_idx, terr)) = self.first_incompatible_error() {
1954 if let Some(ty::Tuple(tys)) =
1958 self.formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
1959 && !tys.is_empty()
1961 && self.provided_arg_tys.len() == self.formal_and_expected_inputs.len() - 1 + tys.len()
1962 {
1963 let provided_args_to_tuple = &self.provided_arg_tys[mismatch_idx..];
1965 let (provided_args_to_tuple, provided_args_after_tuple) =
1966 provided_args_to_tuple.split_at(tys.len());
1967 let provided_as_tuple = Ty::new_tup_from_iter(
1968 self.tcx,
1969 provided_args_to_tuple.iter().map(|&(ty, _)| ty),
1970 );
1971
1972 let mut satisfied = true;
1973 for ((_, expected_ty), provided_ty) in std::iter::zip(
1975 self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
1976 [provided_as_tuple]
1977 .into_iter()
1978 .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
1979 ) {
1980 if !self.may_coerce(provided_ty, *expected_ty) {
1981 satisfied = false;
1982 break;
1983 }
1984 }
1985
1986 if satisfied
1990 && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
1991 {
1992 let mut err;
1993 if tys.len() == 1 {
1994 err = self.err_ctxt().report_and_explain_type_error(
1997 self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
1998 lo,
1999 self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
2000 self.provided_arg_tys[mismatch_idx].0,
2001 ),
2002 self.param_env,
2003 terr,
2004 );
2005 let call_name = self.call_metadata.call_name;
2006 err.span_label(
2007 self.call_metadata.full_call_span,
2008 format!("arguments to this {call_name} are incorrect"),
2009 );
2010 } else {
2011 let call_name = self.call_metadata.call_name;
2012 err = self.dcx().struct_span_err(
2013 self.arg_matching_ctxt.args_ctxt.call_metadata.full_call_span,
2014 format!(
2015 "{call_name} takes {}{} but {} {} supplied",
2016 if self.c_variadic { "at least " } else { "" },
2017 potentially_plural_count(
2018 self.formal_and_expected_inputs.len(),
2019 "argument"
2020 ),
2021 potentially_plural_count(self.provided_args.len(), "argument"),
2022 pluralize!("was", self.provided_args.len())
2023 ),
2024 );
2025 err.code(self.err_code.to_owned());
2026 err.multipart_suggestion_verbose(
2027 "wrap these arguments in parentheses to construct a tuple",
2028 vec![
2029 (lo.shrink_to_lo(), "(".to_string()),
2030 (hi.shrink_to_hi(), ")".to_string()),
2031 ],
2032 Applicability::MachineApplicable,
2033 );
2034 };
2035 self.arg_matching_ctxt.args_ctxt.call_ctxt.fn_ctxt.label_fn_like(
2036 &mut err,
2037 self.fn_def_id,
2038 self.callee_ty,
2039 self.call_expr,
2040 None,
2041 Some(mismatch_idx.as_usize()),
2042 &self.matched_inputs,
2043 &self.formal_and_expected_inputs,
2044 self.call_metadata.is_method,
2045 self.tuple_arguments,
2046 );
2047 self.suggest_confusable(&mut err);
2048 Some(err.emit())
2049 } else {
2050 None
2051 }
2052 } else {
2053 None
2054 }
2055 } else {
2056 None
2057 }
2058 }
2059
2060 fn ensure_has_errors(&self) -> Option<ErrorGuaranteed> {
2061 if self.errors.is_empty() {
2062 if cfg!(debug_assertions) {
2063 span_bug!(self.call_metadata.error_span, "expected errors from argument matrix");
2064 } else {
2065 let mut err = self.dcx().create_err(errors::ArgMismatchIndeterminate {
2066 span: self.call_metadata.error_span,
2067 });
2068 self.arg_matching_ctxt.suggest_confusable(&mut err);
2069 return Some(err.emit());
2070 }
2071 }
2072
2073 None
2074 }
2075
2076 fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) {
2077 if let ty::Adt(adt, _) = ty.kind()
2078 && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
2079 && is_range_literal(expr)
2080 && let hir::ExprKind::Struct(&path, [], _) = expr.kind
2081 && self.tcx().qpath_is_lang_item(path, hir::LangItem::RangeFull)
2082 {
2083 let explanation = if self.tcx.features().default_field_values() {
2086 "this is only supported on non-tuple struct literals"
2087 } else if self.tcx.sess.is_nightly_build() {
2088 "this is only supported on non-tuple struct literals when \
2089 `#![feature(default_field_values)]` is enabled"
2090 } else {
2091 "this is not supported"
2092 };
2093 let msg = format!(
2094 "you might have meant to use `..` to skip providing a value for \
2095 expected fields, but {explanation}; it is instead interpreted as a \
2096 `std::ops::RangeFull` literal",
2097 );
2098 err.span_help(expr.span, msg);
2099 }
2100 }
2101
2102 fn filter_out_invalid_arguments(&mut self) -> Option<ErrorGuaranteed> {
2103 let mut reported = None;
2104
2105 self.errors.retain(|error| {
2106 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
2107 error
2108 else {
2109 return true;
2110 };
2111 let (provided_ty, provided_span) =
2112 self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2113 let trace = self.arg_matching_ctxt.mk_trace(
2114 provided_span,
2115 self.arg_matching_ctxt.formal_and_expected_inputs[*expected_idx],
2116 provided_ty,
2117 );
2118 if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
2119 let mut err = self.arg_matching_ctxt.err_ctxt().report_and_explain_type_error(
2120 trace,
2121 self.arg_matching_ctxt.param_env,
2122 *e,
2123 );
2124 self.arg_matching_ctxt.suggest_confusable(&mut err);
2125 reported = Some(err.emit());
2126 return false;
2127 }
2128 true
2129 });
2130
2131 reported
2132 }
2133
2134 fn check_single_incompatible(&self) -> Option<ErrorGuaranteed> {
2135 if let &[
2136 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
2137 ] = &self.errors[..]
2138 {
2139 let (formal_ty, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2140 let (provided_ty, provided_arg_span) = self.provided_arg_tys[provided_idx];
2141 let trace = self.mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
2142 let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
2143 self.emit_coerce_suggestions(
2144 &mut err,
2145 self.provided_args[provided_idx],
2146 provided_ty,
2147 Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2148 .only_has_type(self.fn_ctxt)
2149 .unwrap_or(formal_ty),
2150 None,
2151 None,
2152 );
2153 let call_name = self.call_metadata.call_name;
2154 err.span_label(
2155 self.call_metadata.full_call_span,
2156 format!("arguments to this {call_name} are incorrect"),
2157 );
2158
2159 self.fn_ctxt.label_generic_mismatches(
2160 &mut err,
2161 self.fn_def_id,
2162 &self.matched_inputs,
2163 &self.provided_arg_tys,
2164 &self.formal_and_expected_inputs,
2165 self.call_metadata.is_method,
2166 );
2167
2168 if let hir::ExprKind::MethodCall(_, rcvr, _, _) =
2169 self.arg_matching_ctxt.args_ctxt.call_ctxt.call_expr.kind
2170 && provided_idx.as_usize() == expected_idx.as_usize()
2171 {
2172 self.note_source_of_type_mismatch_constraint(
2173 &mut err,
2174 rcvr,
2175 crate::demand::TypeMismatchSource::Arg {
2176 call_expr: self.call_expr,
2177 incompatible_arg: provided_idx.as_usize(),
2178 },
2179 );
2180 }
2181
2182 self.suggest_ptr_null_mut(
2183 expected_ty,
2184 provided_ty,
2185 self.provided_args[provided_idx],
2186 &mut err,
2187 );
2188
2189 self.suggest_deref_unwrap_or(
2190 &mut err,
2191 self.callee_ty,
2192 self.call_metadata.call_ident,
2193 expected_ty,
2194 provided_ty,
2195 self.provided_args[provided_idx],
2196 self.call_metadata.is_method,
2197 );
2198
2199 self.label_fn_like(
2201 &mut err,
2202 self.fn_def_id,
2203 self.callee_ty,
2204 self.call_expr,
2205 Some(expected_ty),
2206 Some(expected_idx.as_usize()),
2207 &self.matched_inputs,
2208 &self.formal_and_expected_inputs,
2209 self.call_metadata.is_method,
2210 self.tuple_arguments,
2211 );
2212 self.arg_matching_ctxt.suggest_confusable(&mut err);
2213 self.detect_dotdot(&mut err, provided_ty, self.provided_args[provided_idx]);
2214 return Some(err.emit());
2215 }
2216
2217 None
2218 }
2219
2220 fn maybe_optimize_extra_arg_suggestion(&mut self) {
2221 if let [Error::Extra(provided_idx)] = &self.errors[..] {
2222 if !self.remove_idx_is_perfect(provided_idx.as_usize()) {
2223 if let Some(i) = (0..self.args_ctxt.call_ctxt.provided_args.len())
2224 .find(|&i| self.remove_idx_is_perfect(i))
2225 {
2226 self.errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
2227 }
2228 }
2229 }
2230 }
2231
2232 fn initial_final_diagnostic(&self) -> Diag<'_> {
2233 if self.formal_and_expected_inputs.len() == self.provided_args.len() {
2234 struct_span_code_err!(
2235 self.dcx(),
2236 self.call_metadata.full_call_span,
2237 E0308,
2238 "arguments to this {} are incorrect",
2239 self.call_metadata.call_name,
2240 )
2241 } else {
2242 self.arg_matching_ctxt
2243 .dcx()
2244 .struct_span_err(
2245 self.call_metadata.full_call_span,
2246 format!(
2247 "this {} takes {}{} but {} {} supplied",
2248 self.call_metadata.call_name,
2249 if self.c_variadic { "at least " } else { "" },
2250 potentially_plural_count(self.formal_and_expected_inputs.len(), "argument"),
2251 potentially_plural_count(self.provided_args.len(), "argument"),
2252 pluralize!("was", self.provided_args.len())
2253 ),
2254 )
2255 .with_code(self.err_code.to_owned())
2256 }
2257 }
2258
2259 fn labels_and_suggestion_text(
2260 &self,
2261 err: &mut Diag<'_>,
2262 ) -> (Vec<(Span, String)>, Vec<(Span, String)>, SuggestionText) {
2263 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
2265 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
2266 }
2267
2268 let mut labels = Vec::new();
2269 let mut suggestion_text = SuggestionText::None;
2270
2271 let mut errors = self.errors.iter().peekable();
2272 let mut only_extras_so_far = errors
2273 .peek()
2274 .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
2275 let mut prev_extra_idx = None;
2276 let mut suggestions = vec![];
2277 while let Some(error) = errors.next() {
2278 only_extras_so_far &= matches!(error, Error::Extra(_));
2279
2280 match error {
2281 Error::Invalid(provided_idx, expected_idx, compatibility) => {
2282 let (formal_ty, expected_ty) =
2283 self.arg_matching_ctxt.args_ctxt.call_ctxt.formal_and_expected_inputs
2284 [*expected_idx];
2285 let (provided_ty, provided_span) =
2286 self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2287 if let Compatibility::Incompatible(error) = compatibility {
2288 let trace = self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2289 provided_span,
2290 (formal_ty, expected_ty),
2291 provided_ty,
2292 );
2293 if let Some(e) = error {
2294 self.err_ctxt().note_type_err(
2295 err,
2296 &trace.cause,
2297 None,
2298 Some(self.param_env.and(trace.values)),
2299 *e,
2300 true,
2301 None,
2302 );
2303 }
2304 }
2305
2306 self.emit_coerce_suggestions(
2307 err,
2308 self.provided_args[*provided_idx],
2309 provided_ty,
2310 Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2311 .only_has_type(self.fn_ctxt)
2312 .unwrap_or(formal_ty),
2313 None,
2314 None,
2315 );
2316 self.detect_dotdot(err, provided_ty, self.provided_args[*provided_idx]);
2317 }
2318 Error::Extra(arg_idx) => {
2319 let (provided_ty, provided_span) = self.provided_arg_tys[*arg_idx];
2320 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2321 format!(" of type `{provided_ty}`")
2323 } else {
2324 "".to_string()
2325 };
2326 let idx = if self.provided_arg_tys.len() == 1 {
2327 "".to_string()
2328 } else {
2329 format!(" #{}", arg_idx.as_usize() + 1)
2330 };
2331 labels.push((
2332 provided_span,
2333 format!("unexpected argument{idx}{provided_ty_name}"),
2334 ));
2335 let mut span = provided_span;
2336 if span.can_be_used_for_suggestions()
2337 && self.call_metadata.error_span.can_be_used_for_suggestions()
2338 {
2339 if arg_idx.index() > 0
2340 && let Some((_, prev)) = self
2341 .provided_arg_tys
2342 .get(ProvidedIdx::from_usize(arg_idx.index() - 1))
2343 {
2344 span = prev.shrink_to_hi().to(span);
2346 }
2347
2348 let trim_next_comma = match errors.peek() {
2355 Some(Error::Extra(provided_idx))
2356 if only_extras_so_far
2357 && provided_idx.index() > arg_idx.index() + 1 =>
2358 {
2366 prev_extra_idx.is_none_or(|prev_extra_idx| {
2367 prev_extra_idx + 1 == arg_idx.index()
2368 })
2369 }
2370 None if only_extras_so_far => true,
2372 _ => false,
2374 };
2375
2376 if trim_next_comma {
2377 let next = self
2378 .provided_arg_tys
2379 .get(*arg_idx + 1)
2380 .map(|&(_, sp)| sp)
2381 .unwrap_or_else(|| {
2382 self.arg_matching_ctxt
2387 .tcx()
2388 .sess
2389 .source_map()
2390 .end_point(self.call_expr.span)
2391 });
2392
2393 span = span.until(next);
2395 }
2396
2397 suggestions.push((span, String::new()));
2398
2399 suggestion_text = match suggestion_text {
2400 SuggestionText::None => SuggestionText::Remove(false),
2401 SuggestionText::Remove(_) => SuggestionText::Remove(true),
2402 _ => SuggestionText::DidYouMean,
2403 };
2404 prev_extra_idx = Some(arg_idx.index())
2405 }
2406 self.detect_dotdot(err, provided_ty, self.provided_args[*arg_idx]);
2407 }
2408 Error::Missing(expected_idx) => {
2409 let mut missing_idxs = vec![*expected_idx];
2413 while let Some(e) = errors.next_if(|e| {
2414 matches!(e, Error::Missing(next_expected_idx)
2415 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
2416 }) {
2417 match e {
2418 Error::Missing(expected_idx) => missing_idxs.push(*expected_idx),
2419 _ => unreachable!(
2420 "control flow ensures that we should always get an `Error::Missing`"
2421 ),
2422 }
2423 }
2424
2425 match &missing_idxs[..] {
2430 &[expected_idx] => {
2431 let (_, input_ty) = self.formal_and_expected_inputs[expected_idx];
2432 let span = if let Some((_, arg_span)) =
2433 self.provided_arg_tys.get(expected_idx.to_provided_idx())
2434 {
2435 *arg_span
2436 } else {
2437 self.args_span
2438 };
2439 let rendered = if !has_error_or_infer([input_ty]) {
2440 format!(" of type `{input_ty}`")
2441 } else {
2442 "".to_string()
2443 };
2444 labels.push((
2445 span,
2446 format!(
2447 "argument #{}{rendered} is missing",
2448 expected_idx.as_usize() + 1
2449 ),
2450 ));
2451
2452 suggestion_text = match suggestion_text {
2453 SuggestionText::None => SuggestionText::Provide(false),
2454 SuggestionText::Provide(_) => SuggestionText::Provide(true),
2455 _ => SuggestionText::DidYouMean,
2456 };
2457 }
2458 &[first_idx, second_idx] => {
2459 let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2460 let (_, second_expected_ty) =
2461 self.formal_and_expected_inputs[second_idx];
2462 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
2463 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2464 self.provided_arg_tys.get(second_idx.to_provided_idx()),
2465 ) {
2466 first_span.to(*second_span)
2467 } else {
2468 self.args_span
2469 };
2470 let rendered =
2471 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
2472 format!(
2473 " of type `{first_expected_ty}` and `{second_expected_ty}`"
2474 )
2475 } else {
2476 "".to_string()
2477 };
2478 labels.push((span, format!("two arguments{rendered} are missing")));
2479 suggestion_text = match suggestion_text {
2480 SuggestionText::None | SuggestionText::Provide(_) => {
2481 SuggestionText::Provide(true)
2482 }
2483 _ => SuggestionText::DidYouMean,
2484 };
2485 }
2486 &[first_idx, second_idx, third_idx] => {
2487 let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2488 let (_, second_expected_ty) =
2489 self.formal_and_expected_inputs[second_idx];
2490 let (_, third_expected_ty) = self.formal_and_expected_inputs[third_idx];
2491 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
2492 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2493 self.provided_arg_tys.get(third_idx.to_provided_idx()),
2494 ) {
2495 first_span.to(*third_span)
2496 } else {
2497 self.args_span
2498 };
2499 let rendered = if !has_error_or_infer([
2500 first_expected_ty,
2501 second_expected_ty,
2502 third_expected_ty,
2503 ]) {
2504 format!(
2505 " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
2506 )
2507 } else {
2508 "".to_string()
2509 };
2510 labels.push((span, format!("three arguments{rendered} are missing")));
2511 suggestion_text = match suggestion_text {
2512 SuggestionText::None | SuggestionText::Provide(_) => {
2513 SuggestionText::Provide(true)
2514 }
2515 _ => SuggestionText::DidYouMean,
2516 };
2517 }
2518 missing_idxs => {
2519 let first_idx = *missing_idxs.first().unwrap();
2520 let last_idx = *missing_idxs.last().unwrap();
2521 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
2525 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2526 self.provided_arg_tys.get(last_idx.to_provided_idx()),
2527 ) {
2528 first_span.to(*last_span)
2529 } else {
2530 self.args_span
2531 };
2532 labels.push((span, "multiple arguments are missing".to_string()));
2533 suggestion_text = match suggestion_text {
2534 SuggestionText::None | SuggestionText::Provide(_) => {
2535 SuggestionText::Provide(true)
2536 }
2537 _ => SuggestionText::DidYouMean,
2538 };
2539 }
2540 }
2541 }
2542 Error::Swap(
2543 first_provided_idx,
2544 second_provided_idx,
2545 first_expected_idx,
2546 second_expected_idx,
2547 ) => {
2548 let (first_provided_ty, first_span) =
2549 self.provided_arg_tys[*first_provided_idx];
2550 let (_, first_expected_ty) =
2551 self.formal_and_expected_inputs[*first_expected_idx];
2552 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
2553 format!(", found `{first_provided_ty}`")
2554 } else {
2555 String::new()
2556 };
2557 labels.push((
2558 first_span,
2559 format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
2560 ));
2561
2562 let (second_provided_ty, second_span) =
2563 self.provided_arg_tys[*second_provided_idx];
2564 let (_, second_expected_ty) =
2565 self.formal_and_expected_inputs[*second_expected_idx];
2566 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
2567 format!(", found `{second_provided_ty}`")
2568 } else {
2569 String::new()
2570 };
2571 labels.push((
2572 second_span,
2573 format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
2574 ));
2575
2576 suggestion_text = match suggestion_text {
2577 SuggestionText::None => SuggestionText::Swap,
2578 _ => SuggestionText::DidYouMean,
2579 };
2580 }
2581 Error::Permutation(args) => {
2582 for (dst_arg, dest_input) in args {
2583 let (_, expected_ty) = self.formal_and_expected_inputs[*dst_arg];
2584 let (provided_ty, provided_span) = self.provided_arg_tys[*dest_input];
2585 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2586 format!(", found `{provided_ty}`")
2587 } else {
2588 String::new()
2589 };
2590 labels.push((
2591 provided_span,
2592 format!("expected `{expected_ty}`{provided_ty_name}"),
2593 ));
2594 }
2595
2596 suggestion_text = match suggestion_text {
2597 SuggestionText::None => SuggestionText::Reorder,
2598 _ => SuggestionText::DidYouMean,
2599 };
2600 }
2601 }
2602 }
2603
2604 (suggestions, labels, suggestion_text)
2605 }
2606
2607 fn label_generic_mismatches(&self, err: &mut Diag<'b>) {
2608 self.fn_ctxt.label_generic_mismatches(
2609 err,
2610 self.fn_def_id,
2611 &self.matched_inputs,
2612 &self.provided_arg_tys,
2613 &self.formal_and_expected_inputs,
2614 self.call_metadata.is_method,
2615 );
2616 }
2617
2618 fn append_arguments_changes(&self, suggestions: &mut Vec<(Span, String)>) {
2627 let mut prev = -1;
2642 for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
2643 if let Some(provided_idx) = provided_idx {
2646 prev = provided_idx.index() as i64;
2647 continue;
2648 }
2649 let idx = ProvidedIdx::from_usize((prev + 1) as usize);
2650 if let Some((_, arg_span)) = self.provided_arg_tys.get(idx) {
2651 prev += 1;
2652 let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2657 suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
2658 }
2659 }
2660 }
2661
2662 fn format_suggestion_text(
2663 err: &mut Diag<'_>,
2664 suggestions: Vec<(Span, String)>,
2665 suggestion_text: SuggestionText,
2666 ) -> Option<String> {
2667 match suggestion_text {
2668 SuggestionText::None => None,
2669 SuggestionText::Provide(plural) => {
2670 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
2671 }
2672 SuggestionText::Remove(plural) => {
2673 err.multipart_suggestion_verbose(
2674 format!("remove the extra argument{}", if plural { "s" } else { "" }),
2675 suggestions,
2676 Applicability::HasPlaceholders,
2677 );
2678 None
2679 }
2680 SuggestionText::Swap => Some("swap these arguments".to_string()),
2681 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
2682 SuggestionText::DidYouMean => Some("did you mean".to_string()),
2683 }
2684 }
2685
2686 fn arguments_formatting(&self, suggestion_span: Span) -> ArgumentsFormatting {
2687 let source_map = self.sess().source_map();
2688 let mut provided_inputs = self.matched_inputs.iter().filter_map(|a| *a);
2689 if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
2690 && let Some(first_idx) = provided_inputs.by_ref().next()
2691 && let Some(last_idx) = provided_inputs.by_ref().next()
2692 && let (_, first_span) = self.provided_arg_tys[first_idx]
2693 && let (_, last_span) = self.provided_arg_tys[last_idx]
2694 && source_map.is_multiline(first_span.to(last_span))
2695 && let Some(fallback_indent) = source_map.indentation_before(first_span)
2696 {
2697 ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
2698 } else {
2699 ArgumentsFormatting::SingleLine
2700 }
2701 }
2702
2703 fn suggestion_code(&self) -> (Span, String) {
2704 let source_map = self.sess().source_map();
2705 let suggestion_span = if let Some(args_span) =
2706 self.call_metadata.error_span.trim_start(self.call_metadata.full_call_span)
2707 {
2708 args_span
2710 } else {
2711 self.call_metadata.full_call_span.shrink_to_hi()
2715 };
2716
2717 let arguments_formatting = self.arguments_formatting(suggestion_span);
2718
2719 let mut suggestion = "(".to_owned();
2720 let mut needs_comma = false;
2721 for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
2722 if needs_comma {
2723 suggestion += ",";
2724 }
2725 match &arguments_formatting {
2726 ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
2727 ArgumentsFormatting::SingleLine => {}
2728 ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
2729 }
2730 needs_comma = true;
2731 let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
2732 && let (_, provided_span) = self.provided_arg_tys[*provided_idx]
2733 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
2734 {
2735 (Some(provided_span), arg_text)
2736 } else {
2737 let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2739 (None, self.ty_to_snippet(expected_ty, expected_idx))
2740 };
2741 if let ArgumentsFormatting::Multiline { fallback_indent, .. } = &arguments_formatting {
2742 let indent = suggestion_span
2743 .and_then(|span| source_map.indentation_before(span))
2744 .unwrap_or_else(|| fallback_indent.clone());
2745 suggestion += &indent;
2746 }
2747 suggestion += &suggestion_text;
2748 }
2749 if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
2750 suggestion += ",\n";
2751 suggestion += &brace_indent;
2752 }
2753 suggestion += ")";
2754
2755 (suggestion_span, suggestion)
2756 }
2757}
2758
2759struct ArgMatchingCtxt<'a, 'b, 'tcx> {
2760 args_ctxt: ArgsCtxt<'a, 'b, 'tcx>,
2761 provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
2762}
2763
2764impl<'a, 'b, 'tcx> Deref for ArgMatchingCtxt<'a, 'b, 'tcx> {
2765 type Target = ArgsCtxt<'a, 'b, 'tcx>;
2766
2767 fn deref(&self) -> &Self::Target {
2768 &self.args_ctxt
2769 }
2770}
2771
2772impl<'a, 'b, 'tcx> ArgMatchingCtxt<'a, 'b, 'tcx> {
2773 fn new(
2774 arg: &'a FnCtxt<'b, 'tcx>,
2775 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
2776 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2777 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
2778 c_variadic: bool,
2779 err_code: ErrCode,
2780 fn_def_id: Option<DefId>,
2781 call_span: Span,
2782 call_expr: &'tcx Expr<'tcx>,
2783 tuple_arguments: TupleArgumentsFlag,
2784 ) -> Self {
2785 let args_ctxt = ArgsCtxt::new(
2786 arg,
2787 compatibility_diagonal,
2788 formal_and_expected_inputs,
2789 provided_args,
2790 c_variadic,
2791 err_code,
2792 fn_def_id,
2793 call_span,
2794 call_expr,
2795 tuple_arguments,
2796 );
2797 let provided_arg_tys = args_ctxt.provided_arg_tys();
2798
2799 ArgMatchingCtxt { args_ctxt, provided_arg_tys }
2800 }
2801
2802 fn suggest_confusable(&self, err: &mut Diag<'_>) {
2803 let Some(call_name) = self.call_metadata.call_ident else {
2804 return;
2805 };
2806 let Some(callee_ty) = self.callee_ty else {
2807 return;
2808 };
2809 let input_types: Vec<Ty<'_>> = self.provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
2810
2811 if let Some(_name) = self.confusable_method_name(
2819 err,
2820 callee_ty.peel_refs(),
2821 call_name,
2822 Some(input_types.clone()),
2823 ) {
2824 return;
2825 }
2826 if let Some((assoc, fn_sig)) = self.similar_assoc(call_name)
2828 && fn_sig.inputs()[1..]
2829 .iter()
2830 .eq_by(input_types, |expected, found| self.may_coerce(*expected, found))
2831 {
2832 let assoc_name = assoc.name();
2833 err.span_suggestion_verbose(
2834 call_name.span,
2835 format!("you might have meant to use `{}`", assoc_name),
2836 assoc_name,
2837 Applicability::MaybeIncorrect,
2838 );
2839 return;
2840 }
2841 }
2842
2843 fn check_compatible(
2847 &self,
2848 provided_idx: ProvidedIdx,
2849 expected_idx: ExpectedIdx,
2850 ) -> Compatibility<'tcx> {
2851 if provided_idx.as_usize() == expected_idx.as_usize() {
2852 return self.compatibility_diagonal[provided_idx].clone();
2853 }
2854
2855 let (formal_input_ty, expected_input_ty) = self.formal_and_expected_inputs[expected_idx];
2856 if (formal_input_ty, expected_input_ty).references_error() {
2860 return Compatibility::Incompatible(None);
2861 }
2862
2863 let (arg_ty, arg_span) = self.provided_arg_tys[provided_idx];
2864
2865 let expectation = Expectation::rvalue_hint(self.fn_ctxt, expected_input_ty);
2866 let coerced_ty = expectation.only_has_type(self.fn_ctxt).unwrap_or(formal_input_ty);
2867 let can_coerce = self.may_coerce(arg_ty, coerced_ty);
2868 if !can_coerce {
2869 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
2870 ty::error::ExpectedFound::new(coerced_ty, arg_ty),
2871 )));
2872 }
2873
2874 let subtyping_error = self.probe(|_| {
2876 self.at(&self.misc(arg_span), self.param_env)
2877 .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
2878 .err()
2879 });
2880
2881 let references_error = (coerced_ty, arg_ty).references_error();
2884 match (references_error, subtyping_error) {
2885 (false, None) => Compatibility::Compatible,
2886 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
2887 }
2888 }
2889
2890 fn remove_idx_is_perfect(&self, idx: usize) -> bool {
2891 let removed_arg_tys = self
2892 .provided_arg_tys
2893 .iter()
2894 .enumerate()
2895 .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
2896 .collect::<IndexVec<ProvidedIdx, _>>();
2897 std::iter::zip(self.formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
2898 |((expected_ty, _), (provided_ty, _))| {
2899 !provided_ty.references_error() && self.may_coerce(*provided_ty, *expected_ty)
2900 },
2901 )
2902 }
2903}
2904
2905struct ArgsCtxt<'a, 'b, 'tcx> {
2906 call_ctxt: CallCtxt<'a, 'b, 'tcx>,
2907 call_metadata: CallMetadata,
2908 args_span: Span,
2909}
2910
2911impl<'a, 'b, 'tcx> Deref for ArgsCtxt<'a, 'b, 'tcx> {
2912 type Target = CallCtxt<'a, 'b, 'tcx>;
2913
2914 fn deref(&self) -> &Self::Target {
2915 &self.call_ctxt
2916 }
2917}
2918
2919impl<'a, 'b, 'tcx> ArgsCtxt<'a, 'b, 'tcx> {
2920 fn new(
2921 arg: &'a FnCtxt<'b, 'tcx>,
2922 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
2923 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2924 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
2925 c_variadic: bool,
2926 err_code: ErrCode,
2927 fn_def_id: Option<DefId>,
2928 call_span: Span,
2929 call_expr: &'tcx Expr<'tcx>,
2930 tuple_arguments: TupleArgumentsFlag,
2931 ) -> Self {
2932 let call_ctxt: CallCtxt<'_, '_, '_> = CallCtxt::new(
2933 arg,
2934 compatibility_diagonal,
2935 formal_and_expected_inputs,
2936 provided_args,
2937 c_variadic,
2938 err_code,
2939 fn_def_id,
2940 call_span,
2941 call_expr,
2942 tuple_arguments,
2943 );
2944
2945 let call_metadata = call_ctxt.call_metadata();
2946 let args_span = call_metadata
2947 .error_span
2948 .trim_start(call_metadata.full_call_span)
2949 .unwrap_or(call_metadata.error_span);
2950
2951 ArgsCtxt { args_span, call_metadata, call_ctxt }
2952 }
2953
2954 fn normalize_span(&self, span: Span) -> Span {
2958 let normalized_span =
2959 span.find_ancestor_inside_same_ctxt(self.call_metadata.error_span).unwrap_or(span);
2960 if normalized_span.source_equal(self.call_metadata.error_span) {
2964 span
2965 } else {
2966 normalized_span
2967 }
2968 }
2969
2970 fn provided_arg_tys(&self) -> IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> {
2972 self.call_ctxt
2973 .provided_args
2974 .iter()
2975 .map(|expr| {
2976 let ty = self
2977 .call_ctxt
2978 .fn_ctxt
2979 .typeck_results
2980 .borrow()
2981 .expr_ty_adjusted_opt(expr)
2982 .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx));
2983 (
2984 self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty),
2985 self.normalize_span(expr.span),
2986 )
2987 })
2988 .collect()
2989 }
2990
2991 fn similar_assoc(&self, call_name: Ident) -> Option<(ty::AssocItem, ty::FnSig<'tcx>)> {
2993 if let Some(callee_ty) = self.call_ctxt.callee_ty
2994 && let Ok(Some(assoc)) = self.call_ctxt.fn_ctxt.probe_op(
2995 call_name.span,
2996 MethodCall,
2997 Some(call_name),
2998 None,
2999 IsSuggestion(true),
3000 callee_ty.peel_refs(),
3001 self.call_ctxt.callee_expr.unwrap().hir_id,
3002 TraitsInScope,
3003 |mut ctxt| ctxt.probe_for_similar_candidate(),
3004 )
3005 && assoc.is_method()
3006 {
3007 let args =
3008 self.call_ctxt.fn_ctxt.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
3009 let fn_sig = self
3010 .call_ctxt
3011 .fn_ctxt
3012 .tcx
3013 .fn_sig(assoc.def_id)
3014 .instantiate(self.call_ctxt.fn_ctxt.tcx, args);
3015
3016 self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars(
3017 call_name.span,
3018 BoundRegionConversionTime::FnCall,
3019 fn_sig,
3020 );
3021 }
3022 None
3023 }
3024
3025 fn call_is_in_macro(&self) -> bool {
3026 self.call_metadata.full_call_span.in_external_macro(self.sess().source_map())
3027 }
3028}
3029
3030struct CallMetadata {
3031 error_span: Span,
3032 call_ident: Option<Ident>,
3033 full_call_span: Span,
3034 call_name: &'static str,
3035 is_method: bool,
3036}
3037
3038struct CallCtxt<'a, 'b, 'tcx> {
3039 fn_ctxt: &'a FnCtxt<'b, 'tcx>,
3040 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3041 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3042 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3043 c_variadic: bool,
3044 err_code: ErrCode,
3045 fn_def_id: Option<DefId>,
3046 call_span: Span,
3047 call_expr: &'tcx hir::Expr<'tcx>,
3048 tuple_arguments: TupleArgumentsFlag,
3049 callee_expr: Option<&'tcx Expr<'tcx>>,
3050 callee_ty: Option<Ty<'tcx>>,
3051}
3052
3053impl<'a, 'b, 'tcx> Deref for CallCtxt<'a, 'b, 'tcx> {
3054 type Target = &'a FnCtxt<'b, 'tcx>;
3055
3056 fn deref(&self) -> &Self::Target {
3057 &self.fn_ctxt
3058 }
3059}
3060
3061impl<'a, 'b, 'tcx> CallCtxt<'a, 'b, 'tcx> {
3062 fn new(
3063 fn_ctxt: &'a FnCtxt<'b, 'tcx>,
3064 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3065 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3066 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3067 c_variadic: bool,
3068 err_code: ErrCode,
3069 fn_def_id: Option<DefId>,
3070 call_span: Span,
3071 call_expr: &'tcx hir::Expr<'tcx>,
3072 tuple_arguments: TupleArgumentsFlag,
3073 ) -> CallCtxt<'a, 'b, 'tcx> {
3074 let callee_expr = match &call_expr.peel_blocks().kind {
3075 hir::ExprKind::Call(callee, _) => Some(*callee),
3076 hir::ExprKind::MethodCall(_, receiver, ..) => {
3077 if let Some((DefKind::AssocFn, def_id)) =
3078 fn_ctxt.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
3079 && let Some(assoc) = fn_ctxt.tcx.opt_associated_item(def_id)
3080 && assoc.is_method()
3081 {
3082 Some(*receiver)
3083 } else {
3084 None
3085 }
3086 }
3087 _ => None,
3088 };
3089
3090 let callee_ty = callee_expr.and_then(|callee_expr| {
3091 fn_ctxt.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
3092 });
3093
3094 CallCtxt {
3095 fn_ctxt,
3096 compatibility_diagonal,
3097 formal_and_expected_inputs,
3098 provided_args,
3099 c_variadic,
3100 err_code,
3101 fn_def_id,
3102 call_span,
3103 call_expr,
3104 tuple_arguments,
3105 callee_expr,
3106 callee_ty,
3107 }
3108 }
3109
3110 fn call_metadata(&self) -> CallMetadata {
3111 match &self.call_expr.kind {
3112 hir::ExprKind::Call(
3113 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
3114 _,
3115 ) => {
3116 if let Res::Def(DefKind::Ctor(of, _), _) =
3117 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
3118 {
3119 let name = match of {
3120 CtorOf::Struct => "struct",
3121 CtorOf::Variant => "enum variant",
3122 };
3123 CallMetadata {
3124 error_span: self.call_span,
3125 call_ident: None,
3126 full_call_span: *span,
3127 call_name: name,
3128 is_method: false,
3129 }
3130 } else {
3131 CallMetadata {
3132 error_span: self.call_span,
3133 call_ident: None,
3134 full_call_span: *span,
3135 call_name: "function",
3136 is_method: false,
3137 }
3138 }
3139 }
3140 hir::ExprKind::Call(hir::Expr { span, .. }, _) => CallMetadata {
3141 error_span: self.call_span,
3142 call_ident: None,
3143 full_call_span: *span,
3144 call_name: "function",
3145 is_method: false,
3146 },
3147 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
3148 let ident_span = path_segment.ident.span;
3149 let ident_span = if let Some(args) = path_segment.args {
3150 ident_span.with_hi(args.span_ext.hi())
3151 } else {
3152 ident_span
3153 };
3154 CallMetadata {
3155 error_span: *span,
3156 call_ident: Some(path_segment.ident),
3157 full_call_span: ident_span,
3158 call_name: "method",
3159 is_method: true,
3160 }
3161 }
3162 k => span_bug!(self.call_span, "checking argument types on a non-call: `{:?}`", k),
3163 }
3164 }
3165
3166 fn mk_trace(
3167 &self,
3168 span: Span,
3169 (formal_ty, expected_ty): (Ty<'tcx>, Ty<'tcx>),
3170 provided_ty: Ty<'tcx>,
3171 ) -> TypeTrace<'tcx> {
3172 let mismatched_ty = if expected_ty == provided_ty {
3173 formal_ty
3177 } else {
3178 expected_ty
3179 };
3180 TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
3181 }
3182
3183 fn ty_to_snippet(&self, ty: Ty<'tcx>, expected_idx: ExpectedIdx) -> String {
3184 if ty.is_unit() {
3185 "()".to_string()
3186 } else if ty.is_suggestable(self.tcx, false) {
3187 format!("/* {ty} */")
3188 } else if let Some(fn_def_id) = self.fn_def_id
3189 && self.tcx.def_kind(fn_def_id).is_fn_like()
3190 && let self_implicit =
3191 matches!(self.call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
3192 && let Some(Some(arg)) =
3193 self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
3194 && arg.name != kw::SelfLower
3195 {
3196 format!("/* {} */", arg.name)
3197 } else {
3198 "/* value */".to_string()
3199 }
3200 }
3201
3202 fn first_incompatible_error(&self) -> Option<(ProvidedIdx, TypeError<'tcx>)> {
3203 self.compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
3204 if let Compatibility::Incompatible(Some(terr)) = c { Some((i, *terr)) } else { None }
3205 })
3206 }
3207}
3208
3209enum SuggestionText {
3210 None,
3211 Provide(bool),
3212 Remove(bool),
3213 Swap,
3214 Reorder,
3215 DidYouMean,
3216}