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 let mut suggestion = "(".to_owned();
1593 let mut needs_comma = false;
1594 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1595 if needs_comma {
1596 suggestion += ", ";
1597 } else {
1598 needs_comma = true;
1599 }
1600 let suggestion_text = if let Some(provided_idx) = provided_idx
1601 && let (_, provided_span) = provided_arg_tys[*provided_idx]
1602 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
1603 {
1604 arg_text
1605 } else {
1606 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1608 ty_to_snippet(expected_ty, expected_idx)
1609 };
1610 suggestion += &suggestion_text;
1611 }
1612 suggestion += ")";
1613 err.span_suggestion_verbose(
1614 suggestion_span,
1615 suggestion_text,
1616 suggestion,
1617 Applicability::HasPlaceholders,
1618 );
1619 }
1620
1621 err.emit()
1622 }
1623
1624 fn suggest_ptr_null_mut(
1625 &self,
1626 expected_ty: Ty<'tcx>,
1627 provided_ty: Ty<'tcx>,
1628 arg: &hir::Expr<'tcx>,
1629 err: &mut Diag<'_>,
1630 ) {
1631 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
1632 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
1633 && let hir::ExprKind::Call(callee, _) = arg.kind
1634 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
1635 && let Res::Def(_, def_id) = path.res
1636 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
1637 {
1638 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
1641 }
1642 }
1643
1644 pub(in super::super) fn check_expr_lit(
1646 &self,
1647 lit: &hir::Lit,
1648 expected: Expectation<'tcx>,
1649 ) -> Ty<'tcx> {
1650 let tcx = self.tcx;
1651
1652 match lit.node {
1653 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
1654 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
1655 tcx,
1656 tcx.lifetimes.re_static,
1657 Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
1658 ),
1659 ast::LitKind::Byte(_) => tcx.types.u8,
1660 ast::LitKind::Char(_) => tcx.types.char,
1661 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, t),
1662 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, t),
1663 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
1664 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1665 ty::Int(_) | ty::Uint(_) => Some(ty),
1666 ty::Char => Some(tcx.types.u8),
1670 ty::RawPtr(..) => Some(tcx.types.usize),
1671 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1672 &ty::Pat(base, _) if base.is_integral() => {
1673 let layout = tcx
1674 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1675 .ok()?;
1676 assert!(!layout.uninhabited);
1677
1678 match layout.backend_repr {
1679 rustc_abi::BackendRepr::Scalar(scalar) => {
1680 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1681 }
1682 _ => unreachable!(),
1683 }
1684 }
1685 _ => None,
1686 });
1687 opt_ty.unwrap_or_else(|| self.next_int_var())
1688 }
1689 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => Ty::new_float(tcx, t),
1690 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1691 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1692 ty::Float(_) => Some(ty),
1693 _ => None,
1694 });
1695 opt_ty.unwrap_or_else(|| self.next_float_var())
1696 }
1697 ast::LitKind::Bool(_) => tcx.types.bool,
1698 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1699 tcx,
1700 tcx.lifetimes.re_static,
1701 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, lit.span)).skip_binder(),
1702 ),
1703 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1704 }
1705 }
1706
1707 pub(crate) fn check_struct_path(
1708 &self,
1709 qpath: &QPath<'tcx>,
1710 hir_id: HirId,
1711 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1712 let path_span = qpath.span();
1713 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1714 let variant = match def {
1715 Res::Err => {
1716 let guar =
1717 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1718 self.set_tainted_by_errors(guar);
1719 return Err(guar);
1720 }
1721 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1722 Some(adt) => {
1723 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1724 }
1725 _ => bug!("unexpected type: {:?}", ty.normalized),
1726 },
1727 Res::Def(
1728 DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
1729 _,
1730 )
1731 | Res::SelfTyParam { .. }
1732 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1733 Some(adt) if !adt.is_enum() => {
1734 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1735 }
1736 _ => None,
1737 },
1738 _ => bug!("unexpected definition: {:?}", def),
1739 };
1740
1741 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1742 debug!("check_struct_path: did={:?} args={:?}", did, args);
1743
1744 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1746
1747 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1749
1750 Ok((variant, ty.normalized))
1751 } else {
1752 Err(match *ty.normalized.kind() {
1753 ty::Error(guar) => {
1754 guar
1759 }
1760 _ => struct_span_code_err!(
1761 self.dcx(),
1762 path_span,
1763 E0071,
1764 "expected struct, variant or union type, found {}",
1765 ty.normalized.sort_string(self.tcx)
1766 )
1767 .with_span_label(path_span, "not a struct")
1768 .emit(),
1769 })
1770 }
1771 }
1772
1773 fn check_decl_initializer(
1774 &self,
1775 hir_id: HirId,
1776 pat: &'tcx hir::Pat<'tcx>,
1777 init: &'tcx hir::Expr<'tcx>,
1778 ) -> Ty<'tcx> {
1779 let ref_bindings = pat.contains_explicit_ref_binding();
1784
1785 let local_ty = self.local_ty(init.span, hir_id);
1786 if let Some(m) = ref_bindings {
1787 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1796 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1797 self.emit_type_mismatch_suggestions(
1798 &mut diag,
1799 init.peel_drop_temps(),
1800 init_ty,
1801 local_ty,
1802 None,
1803 None,
1804 );
1805 diag.emit();
1806 }
1807 init_ty
1808 } else {
1809 self.check_expr_coercible_to_type(init, local_ty, None)
1810 }
1811 }
1812
1813 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1814 let decl_ty = self.local_ty(decl.span, decl.hir_id);
1816
1817 if let Some(ref init) = decl.init {
1819 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1820 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1821 }
1822
1823 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1825 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
1827 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1828 } _ => (None, None), };
1831
1832 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1834 let pat_ty = self.node_ty(decl.pat.hir_id);
1835 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1836
1837 if let Some(blk) = decl.origin.try_get_else() {
1838 let previous_diverges = self.diverges.get();
1839 let else_ty = self.check_expr_block(blk, NoExpectation);
1840 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1841 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1842 {
1843 err.emit();
1844 }
1845 self.diverges.set(previous_diverges);
1846 }
1847 decl_ty
1848 }
1849
1850 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1852 GatherLocalsVisitor::gather_from_local(self, local);
1853
1854 let ty = self.check_decl(local.into());
1855 self.write_ty(local.hir_id, ty);
1856 if local.pat.is_never_pattern() {
1857 self.diverges.set(Diverges::Always {
1858 span: local.pat.span,
1859 custom_note: Some("any code following a never pattern is unreachable"),
1860 });
1861 }
1862 }
1863
1864 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1865 match stmt.kind {
1867 hir::StmtKind::Item(..) => return,
1868 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1869 }
1870
1871 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1872
1873 let old_diverges = self.diverges.replace(Diverges::Maybe);
1875
1876 match stmt.kind {
1877 hir::StmtKind::Let(l) => {
1878 self.check_decl_local(l);
1879 }
1880 hir::StmtKind::Item(_) => {}
1882 hir::StmtKind::Expr(ref expr) => {
1883 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1885 if expr.can_have_side_effects() {
1886 self.suggest_semicolon_at_end(expr.span, err);
1887 }
1888 });
1889 }
1890 hir::StmtKind::Semi(expr) => {
1891 let ty = self.check_expr(expr);
1892 self.check_place_expr_if_unsized(ty, expr);
1893 }
1894 }
1895
1896 self.diverges.set(self.diverges.get() | old_diverges);
1898 }
1899
1900 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1901 let unit = self.tcx.types.unit;
1902 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1903
1904 if !ty.is_never() {
1907 self.demand_suptype(blk.span, unit, ty);
1908 }
1909 }
1910
1911 pub(in super::super) fn check_expr_block(
1912 &self,
1913 blk: &'tcx hir::Block<'tcx>,
1914 expected: Expectation<'tcx>,
1915 ) -> Ty<'tcx> {
1916 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1933 let coerce = if blk.targeted_by_break {
1934 CoerceMany::new(coerce_to_ty)
1935 } else {
1936 CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
1937 };
1938
1939 let prev_diverges = self.diverges.get();
1940 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1941
1942 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1943 for s in blk.stmts {
1944 self.check_stmt(s);
1945 }
1946
1947 let tail_expr_ty =
1950 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1951
1952 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1953 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1954 let coerce = ctxt.coerce.as_mut().unwrap();
1955 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1956 let span = self.get_expr_coercion_span(tail_expr);
1957 let cause = self.cause(
1958 span,
1959 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1960 );
1961 let ty_for_diagnostic = coerce.merged_ty();
1962 coerce.coerce_inner(
1966 self,
1967 &cause,
1968 Some(tail_expr),
1969 tail_expr_ty,
1970 |diag| {
1971 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1972 },
1973 false,
1974 );
1975 } else {
1976 if !self.diverges.get().is_always()
1987 || matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1988 {
1989 let mut sp = blk.span;
1995 let mut fn_span = None;
1996 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1997 let ret_sp = decl.output.span();
1998 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1999 if block_sp == blk.span {
2003 sp = ret_sp;
2004 fn_span = self.tcx.def_ident_span(fn_def_id);
2005 }
2006 }
2007 }
2008 coerce.coerce_forced_unit(
2009 self,
2010 &self.misc(sp),
2011 |err| {
2012 if let Some(expected_ty) = expected.only_has_type(self) {
2013 if blk.stmts.is_empty() && blk.expr.is_none() {
2014 self.suggest_boxing_when_appropriate(
2015 err,
2016 blk.span,
2017 blk.hir_id,
2018 expected_ty,
2019 self.tcx.types.unit,
2020 );
2021 }
2022 if !self.err_ctxt().consider_removing_semicolon(
2023 blk,
2024 expected_ty,
2025 err,
2026 ) {
2027 self.err_ctxt().consider_returning_binding(
2028 blk,
2029 expected_ty,
2030 err,
2031 );
2032 }
2033 if expected_ty == self.tcx.types.bool {
2034 if let hir::Block {
2039 stmts:
2040 [
2041 hir::Stmt {
2042 kind:
2043 hir::StmtKind::Let(hir::LetStmt {
2044 source:
2045 hir::LocalSource::AssignDesugar(_),
2046 ..
2047 }),
2048 ..
2049 },
2050 hir::Stmt {
2051 kind:
2052 hir::StmtKind::Expr(hir::Expr {
2053 kind: hir::ExprKind::Assign(lhs, ..),
2054 ..
2055 }),
2056 ..
2057 },
2058 ],
2059 ..
2060 } = blk
2061 {
2062 self.comes_from_while_condition(blk.hir_id, |_| {
2063 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
2067
2068 if !lhs.is_syntactic_place_expr()
2069 || res.references_error()
2070 {
2071 err.downgrade_to_delayed_bug();
2072 }
2073 })
2074 }
2075 }
2076 }
2077 if let Some(fn_span) = fn_span {
2078 err.span_label(
2079 fn_span,
2080 "implicitly returns `()` as its body has no tail or `return` \
2081 expression",
2082 );
2083 }
2084 },
2085 false,
2086 );
2087 }
2088 }
2089 });
2090
2091 if ctxt.may_break {
2092 self.diverges.set(prev_diverges);
2095 }
2096
2097 let ty = ctxt.coerce.unwrap().complete(self);
2098
2099 self.write_ty(blk.hir_id, ty);
2100
2101 ty
2102 }
2103
2104 fn parent_item_span(&self, id: HirId) -> Option<Span> {
2105 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
2106 match node {
2107 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
2108 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
2109 let body = self.tcx.hir_body(body_id);
2110 if let ExprKind::Block(block, _) = &body.value.kind {
2111 return Some(block.span);
2112 }
2113 }
2114 _ => {}
2115 }
2116 None
2117 }
2118
2119 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
2127 let check_in_progress = |elem: &hir::Expr<'_>| {
2128 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
2129 |_| match elem.kind {
2130 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
2132 _ => elem.span,
2133 },
2134 )
2135 };
2136
2137 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
2138 && let Some(rslt) = check_in_progress(el)
2139 {
2140 return rslt;
2141 }
2142
2143 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
2144 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
2145 if let Some(span) = iter.next() {
2146 if iter.next().is_none() {
2147 return span;
2148 }
2149 }
2150 }
2151
2152 expr.span
2153 }
2154
2155 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
2156 if let Err(guar) = ty.error_reported() {
2157 struct OverwritePatternsWithError {
2158 pat_hir_ids: Vec<hir::HirId>,
2159 }
2160 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
2161 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
2162 self.pat_hir_ids.push(p.hir_id);
2163 hir::intravisit::walk_pat(self, p);
2164 }
2165 }
2166 let err = Ty::new_error(self.tcx, guar);
2168 self.write_ty(hir_id, err);
2169 self.write_ty(pat.hir_id, err);
2170 let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
2171 hir::intravisit::walk_pat(&mut visitor, pat);
2172 for hir_id in visitor.pat_hir_ids {
2175 self.write_ty(hir_id, err);
2176 }
2177 self.locals.borrow_mut().insert(hir_id, err);
2178 self.locals.borrow_mut().insert(pat.hir_id, err);
2179 }
2180 }
2181
2182 fn finish_resolving_struct_path(
2185 &self,
2186 qpath: &QPath<'tcx>,
2187 path_span: Span,
2188 hir_id: HirId,
2189 ) -> (Res, LoweredTy<'tcx>) {
2190 match *qpath {
2191 QPath::Resolved(ref maybe_qself, path) => {
2192 let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
2193 let ty = self.lowerer().lower_resolved_ty_path(
2194 self_ty,
2195 path,
2196 hir_id,
2197 PermitVariants::Yes,
2198 );
2199 (path.res, LoweredTy::from_raw(self, path_span, ty))
2200 }
2201 QPath::TypeRelative(hir_self_ty, segment) => {
2202 let self_ty = self.lower_ty(hir_self_ty);
2203
2204 let result = self.lowerer().lower_type_relative_ty_path(
2205 self_ty.raw,
2206 hir_self_ty,
2207 segment,
2208 hir_id,
2209 path_span,
2210 PermitVariants::Yes,
2211 );
2212 let ty = result
2213 .map(|(ty, _, _)| ty)
2214 .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
2215 let ty = LoweredTy::from_raw(self, path_span, ty);
2216 let result = result.map(|(_, kind, def_id)| (kind, def_id));
2217
2218 self.write_resolution(hir_id, result);
2220
2221 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
2222 }
2223 QPath::LangItem(lang_item, span) => {
2224 let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
2225 (res, LoweredTy::from_raw(self, path_span, ty))
2226 }
2227 }
2228 }
2229
2230 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
2237 &self,
2238 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
2239 ) {
2240 let mut remap_cause = FxIndexSet::default();
2246 let mut not_adjusted = vec![];
2247
2248 for error in errors {
2249 let before_span = error.obligation.cause.span;
2250 if self.adjust_fulfillment_error_for_expr_obligation(error)
2251 || before_span != error.obligation.cause.span
2252 {
2253 remap_cause.insert((
2254 before_span,
2255 error.obligation.predicate,
2256 error.obligation.cause.clone(),
2257 ));
2258 } else {
2259 not_adjusted.push(error);
2262 }
2263 }
2264
2265 for error in not_adjusted {
2273 for (span, predicate, cause) in &remap_cause {
2274 if *predicate == error.obligation.predicate
2275 && span.contains(error.obligation.cause.span)
2276 {
2277 error.obligation.cause = cause.clone();
2278 continue;
2279 }
2280 }
2281 }
2282 }
2283
2284 fn label_fn_like(
2285 &self,
2286 err: &mut Diag<'_>,
2287 callable_def_id: Option<DefId>,
2288 callee_ty: Option<Ty<'tcx>>,
2289 call_expr: &'tcx hir::Expr<'tcx>,
2290 expected_ty: Option<Ty<'tcx>>,
2291 expected_idx: Option<usize>,
2293 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2294 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2295 is_method: bool,
2296 tuple_arguments: TupleArgumentsFlag,
2297 ) {
2298 let Some(mut def_id) = callable_def_id else {
2299 return;
2300 };
2301
2302 if tuple_arguments == TupleArguments
2307 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
2308 && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
2313 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
2314 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
2316 && let Some(callee_ty) = callee_ty
2317 {
2318 let callee_ty = callee_ty.peel_refs();
2319 match *callee_ty.kind() {
2320 ty::Param(param) => {
2321 let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
2322 if param.kind.is_synthetic() {
2323 def_id = param.def_id;
2325 } else {
2326 let instantiated = self
2329 .tcx
2330 .explicit_predicates_of(self.body_id)
2331 .instantiate_identity(self.tcx);
2332 for (predicate, span) in instantiated {
2336 if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder()
2337 && pred.self_ty().peel_refs() == callee_ty
2338 && self.tcx.is_fn_trait(pred.def_id())
2339 {
2340 err.span_note(span, "callable defined here");
2341 return;
2342 }
2343 }
2344 }
2345 }
2346 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
2347 | ty::Closure(new_def_id, _)
2348 | ty::FnDef(new_def_id, _) => {
2349 def_id = new_def_id;
2350 }
2351 _ => {
2352 let new_def_id = self.probe(|_| {
2354 let trait_ref = ty::TraitRef::new(
2355 self.tcx,
2356 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
2357 [callee_ty, self.next_ty_var(DUMMY_SP)],
2358 );
2359 let obligation = traits::Obligation::new(
2360 self.tcx,
2361 traits::ObligationCause::dummy(),
2362 self.param_env,
2363 trait_ref,
2364 );
2365 match SelectionContext::new(self).select(&obligation) {
2366 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
2367 Some(impl_source.impl_def_id)
2368 }
2369 _ => None,
2370 }
2371 });
2372 if let Some(new_def_id) = new_def_id {
2373 def_id = new_def_id;
2374 } else {
2375 return;
2376 }
2377 }
2378 }
2379 }
2380
2381 if let Some(def_span) = self.tcx.def_ident_span(def_id)
2382 && !def_span.is_dummy()
2383 {
2384 let mut spans: MultiSpan = def_span.into();
2385 if let Some((params_with_generics, hir_generics)) =
2386 self.get_hir_param_info(def_id, is_method)
2387 {
2388 struct MismatchedParam<'a> {
2389 idx: ExpectedIdx,
2390 generic: GenericIdx,
2391 param: &'a FnParam<'a>,
2392 deps: SmallVec<[ExpectedIdx; 4]>,
2393 }
2394
2395 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2396 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
2398 if let Some(expected_idx) = expected_idx {
2399 let expected_idx = ExpectedIdx::from_usize(expected_idx);
2400 let &(expected_generic, ref expected_param) =
2401 ¶ms_with_generics[expected_idx];
2402 if let Some(expected_generic) = expected_generic {
2403 mismatched_params.push(MismatchedParam {
2404 idx: expected_idx,
2405 generic: expected_generic,
2406 param: expected_param,
2407 deps: SmallVec::new(),
2408 });
2409 } else {
2410 spans.push_span_label(expected_param.span(), "");
2412 }
2413 } else {
2414 mismatched_params.extend(
2415 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
2416 |((idx, &(generic, ref param)), matched_idx)| {
2417 if matched_idx.is_some() {
2418 None
2419 } else if let Some(generic) = generic {
2420 Some(MismatchedParam {
2421 idx,
2422 generic,
2423 param,
2424 deps: SmallVec::new(),
2425 })
2426 } else {
2427 spans.push_span_label(param.span(), "");
2429 None
2430 }
2431 },
2432 ),
2433 );
2434 }
2435
2436 if !mismatched_params.is_empty() {
2437 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
2440 |_| SmallVec::<[u32; 4]>::new(),
2441 params_with_generics.len(),
2442 );
2443 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
2444 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
2445 hir_generics.params.len(),
2446 );
2447 for (idx, param) in mismatched_params.iter_mut().enumerate() {
2448 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
2449 params_with_generics.iter_enumerated().zip(matched_inputs)
2450 {
2451 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
2452 generic_uses[param.generic].extend([param.idx, other_idx]);
2453 dependants[other_idx].push(idx as u32);
2454 param.deps.push(other_idx);
2455 }
2456 }
2457 }
2458
2459 for param in &mismatched_params {
2462 if let Some(deps_list) = listify(¶m.deps, |&dep| {
2463 params_with_generics[dep].1.display(dep.as_usize()).to_string()
2464 }) {
2465 spans.push_span_label(
2466 param.param.span(),
2467 format!(
2468 "this parameter needs to match the {} type of {deps_list}",
2469 self.resolve_vars_if_possible(
2470 formal_and_expected_inputs[param.deps[0]].1
2471 )
2472 .sort_string(self.tcx),
2473 ),
2474 );
2475 } else {
2476 spans.push_span_label(param.param.span(), "");
2478 }
2479 }
2480 for ((&(_, param), deps), &(_, expected_ty)) in
2482 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
2483 {
2484 if let Some(deps_list) = listify(deps, |&dep| {
2485 let param = &mismatched_params[dep as usize];
2486 param.param.display(param.idx.as_usize()).to_string()
2487 }) {
2488 spans.push_span_label(
2489 param.span(),
2490 format!(
2491 "{deps_list} need{} to match the {} type of this parameter",
2492 pluralize!((deps.len() != 1) as u32),
2493 self.resolve_vars_if_possible(expected_ty)
2494 .sort_string(self.tcx),
2495 ),
2496 );
2497 }
2498 }
2499 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
2501 uses.sort();
2502 uses.dedup();
2503 if let Some(param_list) = listify(uses, |&idx| {
2504 params_with_generics[idx].1.display(idx.as_usize()).to_string()
2505 }) {
2506 spans.push_span_label(
2507 param.span,
2508 format!(
2509 "{param_list} {} reference this parameter `{}`",
2510 if uses.len() == 2 { "both" } else { "all" },
2511 param.name.ident().name,
2512 ),
2513 );
2514 }
2515 }
2516 }
2517 }
2518 err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
2519 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
2520 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
2521 {
2522 let param = expected_idx
2523 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
2524 let (kind, span) = if let Some(param) = param {
2525 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] };
2528 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
2529 match self.tcx.hir_node_by_def_id(parent_def_id) {
2530 hir::Node::Item(item) => call_finder.visit_item(item),
2531 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
2532 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
2533 _ => {}
2534 }
2535 let typeck = self.typeck_results.borrow();
2536 for (rcvr, args) in call_finder.calls {
2537 if rcvr.hir_id.owner == typeck.hir_owner
2538 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
2539 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
2540 && def_id == *call_def_id
2541 && let Some(idx) = expected_idx
2542 && let Some(arg) = args.get(idx)
2543 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
2544 && let Some(expected_ty) = expected_ty
2545 && self.can_eq(self.param_env, arg_ty, expected_ty)
2546 {
2547 let mut sp: MultiSpan = vec![arg.span].into();
2548 sp.push_span_label(
2549 arg.span,
2550 format!("expected because this argument is of type `{arg_ty}`"),
2551 );
2552 sp.push_span_label(rcvr.span, "in this closure call");
2553 err.span_note(
2554 sp,
2555 format!(
2556 "expected because the closure was earlier called with an \
2557 argument of type `{arg_ty}`",
2558 ),
2559 );
2560 break;
2561 }
2562 }
2563
2564 ("closure parameter", param.span)
2565 } else {
2566 ("closure", self.tcx.def_span(def_id))
2567 };
2568 err.span_note(span, format!("{kind} defined here"));
2569 } else {
2570 err.span_note(
2571 self.tcx.def_span(def_id),
2572 format!("{} defined here", self.tcx.def_descr(def_id)),
2573 );
2574 }
2575 }
2576
2577 fn label_generic_mismatches(
2578 &self,
2579 err: &mut Diag<'_>,
2580 callable_def_id: Option<DefId>,
2581 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2582 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
2583 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2584 is_method: bool,
2585 ) {
2586 let Some(def_id) = callable_def_id else {
2587 return;
2588 };
2589
2590 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
2591 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2592 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
2593 if matched_inputs[idx].is_none() {
2594 continue;
2595 }
2596
2597 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
2598 else {
2599 continue;
2600 };
2601
2602 let Some(generic_param) = generic_param else {
2603 continue;
2604 };
2605
2606 let idxs_matched = params_with_generics
2607 .iter_enumerated()
2608 .filter(|&(other_idx, (other_generic_param, _))| {
2609 if other_idx == idx {
2610 return false;
2611 }
2612 let Some(other_generic_param) = other_generic_param else {
2613 return false;
2614 };
2615 if matched_inputs[other_idx].is_some() {
2616 return false;
2617 }
2618 other_generic_param == generic_param
2619 })
2620 .count();
2621
2622 if idxs_matched == 0 {
2623 continue;
2624 }
2625
2626 let expected_display_type = self
2627 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
2628 .sort_string(self.tcx);
2629 let label = if idxs_matched == params_with_generics.len() - 1 {
2630 format!(
2631 "expected all arguments to be this {} type because they need to match the type of this parameter",
2632 expected_display_type
2633 )
2634 } else {
2635 format!(
2636 "expected some other arguments to be {} {} type to match the type of this parameter",
2637 a_or_an(&expected_display_type),
2638 expected_display_type,
2639 )
2640 };
2641
2642 err.span_label(*matched_arg_span, label);
2643 }
2644 }
2645 }
2646
2647 fn get_hir_param_info(
2652 &self,
2653 def_id: DefId,
2654 is_method: bool,
2655 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2656 {
2657 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2658 hir::Node::TraitItem(&hir::TraitItem {
2659 generics,
2660 kind: hir::TraitItemKind::Fn(sig, trait_fn),
2661 ..
2662 }) => match trait_fn {
2663 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2664 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2665 },
2666 hir::Node::ImplItem(&hir::ImplItem {
2667 generics,
2668 kind: hir::ImplItemKind::Fn(sig, body),
2669 ..
2670 })
2671 | hir::Node::Item(&hir::Item {
2672 kind: hir::ItemKind::Fn { sig, generics, body, .. },
2673 ..
2674 }) => (sig, generics, Some(body), None),
2675 hir::Node::ForeignItem(&hir::ForeignItem {
2676 kind: hir::ForeignItemKind::Fn(sig, params, generics),
2677 ..
2678 }) => (sig, generics, None, Some(params)),
2679 _ => return None,
2680 };
2681
2682 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2685 if let hir::TyKind::Path(QPath::Resolved(
2686 _,
2687 &hir::Path { res: Res::Def(_, res_def_id), .. },
2688 )) = param.kind
2689 {
2690 generics
2691 .params
2692 .iter()
2693 .position(|param| param.def_id.to_def_id() == res_def_id)
2694 .map(GenericIdx::from_usize)
2695 } else {
2696 None
2697 }
2698 });
2699 match (body_id, params) {
2700 (Some(_), Some(_)) | (None, None) => unreachable!(),
2701 (Some(body), None) => {
2702 let params = self.tcx.hir_body(body).params;
2703 let params =
2704 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2705 debug_assert_eq!(params.len(), fn_inputs.len());
2706 Some((
2707 fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect(),
2708 generics,
2709 ))
2710 }
2711 (None, Some(params)) => {
2712 let params =
2713 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2714 debug_assert_eq!(params.len(), fn_inputs.len());
2715 Some((
2716 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2717 generics,
2718 ))
2719 }
2720 }
2721 }
2722}
2723
2724struct FindClosureArg<'tcx> {
2725 tcx: TyCtxt<'tcx>,
2726 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2727}
2728
2729impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2730 type NestedFilter = rustc_middle::hir::nested_filter::All;
2731
2732 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2733 self.tcx
2734 }
2735
2736 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2737 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2738 self.calls.push((rcvr, args));
2739 }
2740 hir::intravisit::walk_expr(self, ex);
2741 }
2742}
2743
2744#[derive(Clone, Copy)]
2745enum FnParam<'hir> {
2746 Param(&'hir hir::Param<'hir>),
2747 Ident(Option<Ident>),
2748}
2749
2750impl FnParam<'_> {
2751 fn span(&self) -> Span {
2752 match self {
2753 Self::Param(param) => param.span,
2754 Self::Ident(ident) => {
2755 if let Some(ident) = ident {
2756 ident.span
2757 } else {
2758 DUMMY_SP
2759 }
2760 }
2761 }
2762 }
2763
2764 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2765 struct D<'a>(FnParam<'a>, usize);
2766 impl fmt::Display for D<'_> {
2767 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2768 let unique_name = match self.0 {
2771 FnParam::Param(param)
2772 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2773 {
2774 Some(ident.name)
2775 }
2776 FnParam::Ident(ident)
2777 if let Some(ident) = ident
2778 && ident.name != kw::Underscore =>
2779 {
2780 Some(ident.name)
2781 }
2782 _ => None,
2783 };
2784 if let Some(unique_name) = unique_name {
2785 write!(f, "`{unique_name}`")
2786 } else {
2787 write!(f, "parameter #{}", self.1 + 1)
2788 }
2789 }
2790 }
2791 D(*self, idx)
2792 }
2793}