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::{CtorOf, DefKind, Res};
8use rustc_hir::def_id::DefId;
9use rustc_hir::intravisit::Visitor;
10use rustc_hir::{ExprKind, HirId, Node, QPath};
11use rustc_hir_analysis::check::potentially_plural_count;
12use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
13use rustc_index::IndexVec;
14use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
15use rustc_middle::ty::adjustment::AllowTwoPhase;
16use rustc_middle::ty::error::TypeError;
17use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
18use rustc_middle::{bug, span_bug};
19use rustc_session::Session;
20use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
21use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
22use rustc_trait_selection::infer::InferCtxtExt;
23use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
24use smallvec::SmallVec;
25use tracing::debug;
26use {rustc_ast as ast, rustc_hir as hir};
27
28use crate::Expectation::*;
29use crate::TupleArgumentsFlag::*;
30use crate::coercion::CoerceMany;
31use crate::errors::SuggestPtrNullMut;
32use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
33use crate::fn_ctxt::infer::FnCall;
34use crate::gather_locals::Declaration;
35use crate::inline_asm::InlineAsmCtxt;
36use crate::method::probe::IsSuggestion;
37use crate::method::probe::Mode::MethodCall;
38use crate::method::probe::ProbeScope::TraitsInScope;
39use crate::{
40 BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
41 TupleArgumentsFlag, errors, struct_span_code_err,
42};
43
44rustc_index::newtype_index! {
45 #[orderable]
46 #[debug_format = "GenericIdx({})"]
47 pub(crate) struct GenericIdx {}
48}
49
50#[derive(Clone, Copy, Default)]
51pub(crate) enum DivergingBlockBehavior {
52 #[default]
60 Never,
61
62 Unit,
71}
72
73impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
74 pub(in super::super) fn check_casts(&mut self) {
75 let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
78
79 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
80 for cast in deferred_cast_checks.drain(..) {
81 cast.check(self);
82 }
83
84 *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
85 }
86
87 pub(in super::super) fn check_transmutes(&self) {
88 let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
89 debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
90 for (from, to, hir_id) in deferred_transmute_checks.drain(..) {
91 self.check_transmute(from, to, hir_id);
92 }
93 }
94
95 pub(in super::super) fn check_asms(&self) {
96 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
97 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
98 for (asm, hir_id) in deferred_asm_checks.drain(..) {
99 let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
100 InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
101 }
102 }
103
104 pub(in super::super) fn check_repeat_exprs(&self) {
105 let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
106 debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
107 for (element, element_ty, count) in deferred_repeat_expr_checks.drain(..) {
108 let count =
112 self.structurally_resolve_const(element.span, self.normalize(element.span, count));
113
114 if count.references_error() {
117 continue;
118 }
119
120 if count.try_to_target_usize(self.tcx).is_none_or(|x| x > 1) {
124 self.enforce_repeat_element_needs_copy_bound(element, element_ty);
125 }
126 }
127 }
128
129 pub(in super::super) fn check_argument_types(
132 &self,
133 call_span: Span,
135 call_expr: &'tcx hir::Expr<'tcx>,
137 formal_input_tys: &[Ty<'tcx>],
139 formal_output: Ty<'tcx>,
140 expectation: Expectation<'tcx>,
142 provided_args: &'tcx [hir::Expr<'tcx>],
144 c_variadic: bool,
146 tuple_arguments: TupleArgumentsFlag,
148 fn_def_id: Option<DefId>,
150 ) {
151 let tcx = self.tcx;
152
153 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
168 self.register_wf_obligation(
169 fn_input_ty.into(),
170 arg_expr.span,
171 ObligationCauseCode::WellFormed(None),
172 );
173 }
174
175 let formal_output = self.resolve_vars_with_obligations(formal_output);
180 let expected_input_tys: Option<Vec<_>> = expectation
181 .only_has_type(self)
182 .and_then(|expected_output| {
183 self.fudge_inference_if_ok(|| {
184 let ocx = ObligationCtxt::new(self);
185
186 let origin = self.misc(call_span);
191 ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
192 if !ocx.select_where_possible().is_empty() {
193 return Err(TypeError::Mismatch);
194 }
195
196 Ok(Some(
199 formal_input_tys
200 .iter()
201 .map(|&ty| self.resolve_vars_if_possible(ty))
202 .collect(),
203 ))
204 })
205 .ok()
206 })
207 .unwrap_or_default();
208
209 let mut err_code = E0061;
210
211 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
213 let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]);
214 match tuple_type.kind() {
215 ty::Tuple(arg_types) => {
217 if arg_types.len() != provided_args.len() {
219 err_code = E0057;
220 }
221 let expected_input_tys = match expected_input_tys {
222 Some(expected_input_tys) => match expected_input_tys.get(0) {
223 Some(ty) => match ty.kind() {
224 ty::Tuple(tys) => Some(tys.iter().collect()),
225 _ => None,
226 },
227 None => None,
228 },
229 None => None,
230 };
231 (arg_types.iter().collect(), expected_input_tys)
232 }
233 _ => {
234 let guar = struct_span_code_err!(
237 self.dcx(),
238 call_span,
239 E0059,
240 "cannot use call notation; the first type parameter \
241 for the function trait is neither a tuple nor unit"
242 )
243 .emit();
244 (self.err_args(provided_args.len(), guar), None)
245 }
246 }
247 } else {
248 (formal_input_tys.to_vec(), expected_input_tys)
249 };
250
251 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
253 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
254 expected_input_tys
255 } else {
256 formal_input_tys.clone()
257 };
258
259 let minimum_input_count = expected_input_tys.len();
260 let provided_arg_count = provided_args.len();
261
262 let demand_compatible = |idx| {
266 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
267 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
268 let provided_arg = &provided_args[idx];
269
270 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
271
272 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
276
277 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
278
279 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
283
284 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
288
289 let coerce_error =
290 self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
291 if coerce_error.is_some() {
292 return Compatibility::Incompatible(coerce_error);
293 }
294
295 let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
298 DefineOpaqueTypes::Yes,
299 formal_input_ty,
300 coerced_ty,
301 );
302
303 match formal_ty_error {
305 Ok(InferOk { obligations, value: () }) => {
306 self.register_predicates(obligations);
307 Compatibility::Compatible
308 }
309 Err(err) => Compatibility::Incompatible(Some(err)),
310 }
311 };
312
313 let mut compatibility_diagonal =
316 vec![Compatibility::Incompatible(None); provided_args.len()];
317
318 let mut call_appears_satisfied = if c_variadic {
323 provided_arg_count >= minimum_input_count
324 } else {
325 provided_arg_count == minimum_input_count
326 };
327
328 for check_closures in [false, true] {
334 if check_closures {
338 self.select_obligations_where_possible(|_| {})
339 }
340
341 for (idx, arg) in provided_args.iter().enumerate() {
344 if !check_closures {
348 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
349 }
350
351 if idx >= minimum_input_count {
357 continue;
358 }
359
360 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
366 !tcx.coroutine_is_async(closure.def_id.to_def_id())
367 } else {
368 false
369 };
370 if is_closure != check_closures {
371 continue;
372 }
373
374 let compatible = demand_compatible(idx);
375 let is_compatible = matches!(compatible, Compatibility::Compatible);
376 compatibility_diagonal[idx] = compatible;
377
378 if !is_compatible {
379 call_appears_satisfied = false;
380 }
381 }
382 }
383
384 if c_variadic && provided_arg_count < minimum_input_count {
385 err_code = E0060;
386 }
387
388 for arg in provided_args.iter().skip(minimum_input_count) {
389 let arg_ty = self.check_expr(arg);
391
392 if c_variadic {
397 fn variadic_error<'tcx>(
398 sess: &'tcx Session,
399 span: Span,
400 ty: Ty<'tcx>,
401 cast_ty: &str,
402 ) {
403 sess.dcx().emit_err(errors::PassToVariadicFunction {
404 span,
405 ty,
406 cast_ty,
407 sugg_span: span.shrink_to_hi(),
408 teach: sess.teach(E0617),
409 });
410 }
411
412 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
415 match arg_ty.kind() {
416 ty::Float(ty::FloatTy::F32) => {
417 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
418 }
419 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
420 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
421 }
422 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
423 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
424 }
425 ty::FnDef(..) => {
426 let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
427 let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
428
429 let fn_item_spa = arg.span;
430 tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
431 span: fn_item_spa,
432 sugg_span: fn_item_spa.shrink_to_hi(),
433 replace: fn_ptr,
434 });
435 }
436 _ => {}
437 }
438 }
439 }
440
441 if !call_appears_satisfied {
442 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
443 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
444 minimum_input_count
445 } else {
446 provided_arg_count
447 }));
448 debug_assert_eq!(
449 formal_input_tys.len(),
450 expected_input_tys.len(),
451 "expected formal_input_tys to be the same size as expected_input_tys"
452 );
453 let formal_and_expected_inputs = IndexVec::from_iter(
454 formal_input_tys
455 .iter()
456 .copied()
457 .zip_eq(expected_input_tys.iter().copied())
458 .map(|vars| self.resolve_vars_if_possible(vars)),
459 );
460
461 self.report_arg_errors(
462 compatibility_diagonal,
463 formal_and_expected_inputs,
464 provided_args,
465 c_variadic,
466 err_code,
467 fn_def_id,
468 call_span,
469 call_expr,
470 tuple_arguments,
471 );
472 }
473 }
474
475 fn report_arg_errors(
476 &self,
477 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
478 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
479 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
480 c_variadic: bool,
481 err_code: ErrCode,
482 fn_def_id: Option<DefId>,
483 call_span: Span,
484 call_expr: &'tcx hir::Expr<'tcx>,
485 tuple_arguments: TupleArgumentsFlag,
486 ) -> ErrorGuaranteed {
487 let (error_span, call_ident, full_call_span, call_name, is_method) = match &call_expr.kind {
489 hir::ExprKind::Call(
490 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
491 _,
492 ) => {
493 if let Res::Def(DefKind::Ctor(of, _), _) =
494 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
495 {
496 let name = match of {
497 CtorOf::Struct => "struct",
498 CtorOf::Variant => "enum variant",
499 };
500 (call_span, None, *span, name, false)
501 } else {
502 (call_span, None, *span, "function", false)
503 }
504 }
505 hir::ExprKind::Call(hir::Expr { span, .. }, _) => {
506 (call_span, None, *span, "function", false)
507 }
508 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
509 let ident_span = path_segment.ident.span;
510 let ident_span = if let Some(args) = path_segment.args {
511 ident_span.with_hi(args.span_ext.hi())
512 } else {
513 ident_span
514 };
515 (*span, Some(path_segment.ident), ident_span, "method", true)
516 }
517 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
518 };
519 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
520
521 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
523 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
524 }
525
526 let tcx = self.tcx;
527
528 let normalize_span = |span: Span| -> Span {
532 let normalized_span = span.find_ancestor_inside_same_ctxt(error_span).unwrap_or(span);
533 if normalized_span.source_equal(error_span) { span } else { normalized_span }
537 };
538
539 let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
541 .iter()
542 .map(|expr| {
543 let ty = self
544 .typeck_results
545 .borrow()
546 .expr_ty_adjusted_opt(*expr)
547 .unwrap_or_else(|| Ty::new_misc_error(tcx));
548 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
549 })
550 .collect();
551 let callee_expr = match &call_expr.peel_blocks().kind {
552 hir::ExprKind::Call(callee, _) => Some(*callee),
553 hir::ExprKind::MethodCall(_, receiver, ..) => {
554 if let Some((DefKind::AssocFn, def_id)) =
555 self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
556 && let Some(assoc) = tcx.opt_associated_item(def_id)
557 && assoc.is_method()
558 {
559 Some(*receiver)
560 } else {
561 None
562 }
563 }
564 _ => None,
565 };
566 let callee_ty = callee_expr
567 .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
568
569 let similar_assoc = |call_name: Ident| -> Option<(ty::AssocItem, ty::FnSig<'_>)> {
571 if let Some(callee_ty) = callee_ty
572 && let Ok(Some(assoc)) = self.probe_op(
573 call_name.span,
574 MethodCall,
575 Some(call_name),
576 None,
577 IsSuggestion(true),
578 callee_ty.peel_refs(),
579 callee_expr.unwrap().hir_id,
580 TraitsInScope,
581 |mut ctxt| ctxt.probe_for_similar_candidate(),
582 )
583 && assoc.is_method()
584 {
585 let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
586 let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
587
588 self.instantiate_binder_with_fresh_vars(call_name.span, FnCall, fn_sig);
589 }
590 None
591 };
592
593 let suggest_confusable = |err: &mut Diag<'_>| {
594 let Some(call_name) = call_ident else {
595 return;
596 };
597 let Some(callee_ty) = callee_ty else {
598 return;
599 };
600 let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
601 if let Some(_name) = self.confusable_method_name(
609 err,
610 callee_ty.peel_refs(),
611 call_name,
612 Some(input_types.clone()),
613 ) {
614 return;
615 }
616 if let Some((assoc, fn_sig)) = similar_assoc(call_name)
618 && fn_sig.inputs()[1..]
619 .iter()
620 .zip(input_types.iter())
621 .all(|(expected, found)| self.may_coerce(*expected, *found))
622 && fn_sig.inputs()[1..].len() == input_types.len()
623 {
624 let assoc_name = assoc.name();
625 err.span_suggestion_verbose(
626 call_name.span,
627 format!("you might have meant to use `{}`", assoc_name),
628 assoc_name,
629 Applicability::MaybeIncorrect,
630 );
631 return;
632 }
633 if let Some(_name) =
635 self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
636 {
637 return;
638 }
639 if let Some((assoc, fn_sig)) = similar_assoc(call_name)
642 && fn_sig.inputs()[1..].len() == input_types.len()
643 {
644 err.span_note(
645 tcx.def_span(assoc.def_id),
646 format!(
647 "there's is a method with similar name `{}`, but the arguments don't match",
648 assoc.name(),
649 ),
650 );
651 return;
652 }
653 if let Some((assoc, _)) = similar_assoc(call_name) {
655 err.span_note(
656 tcx.def_span(assoc.def_id),
657 format!(
658 "there's is a method with similar name `{}`, but their argument count \
659 doesn't match",
660 assoc.name(),
661 ),
662 );
663 return;
664 }
665 };
666 let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
670 if provided_idx.as_usize() == expected_idx.as_usize() {
671 return compatibility_diagonal[provided_idx].clone();
672 }
673
674 let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
675 if (formal_input_ty, expected_input_ty).references_error() {
679 return Compatibility::Incompatible(None);
680 }
681
682 let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
683
684 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
685 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
686 let can_coerce = self.may_coerce(arg_ty, coerced_ty);
687 if !can_coerce {
688 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
689 ty::error::ExpectedFound::new(coerced_ty, arg_ty),
690 )));
691 }
692
693 let subtyping_error = self.probe(|_| {
695 self.at(&self.misc(arg_span), self.param_env)
696 .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
697 .err()
698 });
699
700 let references_error = (coerced_ty, arg_ty).references_error();
703 match (references_error, subtyping_error) {
704 (false, None) => Compatibility::Compatible,
705 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
706 }
707 };
708
709 let mk_trace = |span, (formal_ty, expected_ty), provided_ty| {
710 let mismatched_ty = if expected_ty == provided_ty {
711 formal_ty
715 } else {
716 expected_ty
717 };
718 TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
719 };
720
721 let (mut errors, matched_inputs) =
730 ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
731 .find_errors();
732
733 if let Some((mismatch_idx, terr)) =
735 compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
736 if let Compatibility::Incompatible(Some(terr)) = c {
737 Some((i, *terr))
738 } else {
739 None
740 }
741 })
742 {
743 if let Some(ty::Tuple(tys)) =
747 formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
748 && !tys.is_empty()
750 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
751 {
752 let provided_args_to_tuple = &provided_arg_tys[mismatch_idx..];
754 let (provided_args_to_tuple, provided_args_after_tuple) =
755 provided_args_to_tuple.split_at(tys.len());
756 let provided_as_tuple =
757 Ty::new_tup_from_iter(tcx, provided_args_to_tuple.iter().map(|&(ty, _)| ty));
758
759 let mut satisfied = true;
760 for ((_, expected_ty), provided_ty) in std::iter::zip(
762 formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
763 [provided_as_tuple]
764 .into_iter()
765 .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
766 ) {
767 if !self.may_coerce(provided_ty, *expected_ty) {
768 satisfied = false;
769 break;
770 }
771 }
772
773 if satisfied
777 && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
778 {
779 let mut err;
780 if tys.len() == 1 {
781 err = self.err_ctxt().report_and_explain_type_error(
784 mk_trace(
785 lo,
786 formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
787 provided_arg_tys[mismatch_idx].0,
788 ),
789 self.param_env,
790 terr,
791 );
792 err.span_label(
793 full_call_span,
794 format!("arguments to this {call_name} are incorrect"),
795 );
796 } else {
797 err = self.dcx().struct_span_err(
798 full_call_span,
799 format!(
800 "{call_name} takes {}{} but {} {} supplied",
801 if c_variadic { "at least " } else { "" },
802 potentially_plural_count(
803 formal_and_expected_inputs.len(),
804 "argument"
805 ),
806 potentially_plural_count(provided_args.len(), "argument"),
807 pluralize!("was", provided_args.len())
808 ),
809 );
810 err.code(err_code.to_owned());
811 err.multipart_suggestion_verbose(
812 "wrap these arguments in parentheses to construct a tuple",
813 vec![
814 (lo.shrink_to_lo(), "(".to_string()),
815 (hi.shrink_to_hi(), ")".to_string()),
816 ],
817 Applicability::MachineApplicable,
818 );
819 };
820 self.label_fn_like(
821 &mut err,
822 fn_def_id,
823 callee_ty,
824 call_expr,
825 None,
826 Some(mismatch_idx.as_usize()),
827 &matched_inputs,
828 &formal_and_expected_inputs,
829 is_method,
830 tuple_arguments,
831 );
832 suggest_confusable(&mut err);
833 return err.emit();
834 }
835 }
836 }
837
838 if errors.is_empty() {
854 if cfg!(debug_assertions) {
855 span_bug!(error_span, "expected errors from argument matrix");
856 } else {
857 let mut err =
858 self.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
859 suggest_confusable(&mut err);
860 return err.emit();
861 }
862 }
863
864 let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
865 if let ty::Adt(adt, _) = ty.kind()
866 && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
867 && let hir::ExprKind::Struct(
868 hir::QPath::LangItem(hir::LangItem::RangeFull, _),
869 [],
870 _,
871 ) = expr.kind
872 {
873 let explanation = if self.tcx.features().default_field_values() {
876 "this is only supported on non-tuple struct literals"
877 } else if self.tcx.sess.is_nightly_build() {
878 "this is only supported on non-tuple struct literals when \
879 `#![feature(default_field_values)]` is enabled"
880 } else {
881 "this is not supported"
882 };
883 let msg = format!(
884 "you might have meant to use `..` to skip providing a value for \
885 expected fields, but {explanation}; it is instead interpreted as a \
886 `std::ops::RangeFull` literal",
887 );
888 err.span_help(expr.span, msg);
889 }
890 };
891
892 let mut reported = None;
893 errors.retain(|error| {
894 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
895 error
896 else {
897 return true;
898 };
899 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
900 let trace =
901 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
902 if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
903 let mut err =
904 self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e);
905 suggest_confusable(&mut err);
906 reported = Some(err.emit());
907 return false;
908 }
909 true
910 });
911
912 if let Some(reported) = reported
914 && errors.is_empty()
915 {
916 return reported;
917 }
918 assert!(!errors.is_empty());
919
920 if let &[
926 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
927 ] = &errors[..]
928 {
929 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
930 let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
931 let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
932 let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
933 self.emit_coerce_suggestions(
934 &mut err,
935 provided_args[provided_idx],
936 provided_ty,
937 Expectation::rvalue_hint(self, expected_ty)
938 .only_has_type(self)
939 .unwrap_or(formal_ty),
940 None,
941 None,
942 );
943 err.span_label(full_call_span, format!("arguments to this {call_name} are incorrect"));
944
945 self.label_generic_mismatches(
946 &mut err,
947 fn_def_id,
948 &matched_inputs,
949 &provided_arg_tys,
950 &formal_and_expected_inputs,
951 is_method,
952 );
953
954 if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
955 && provided_idx.as_usize() == expected_idx.as_usize()
956 {
957 self.note_source_of_type_mismatch_constraint(
958 &mut err,
959 rcvr,
960 crate::demand::TypeMismatchSource::Arg {
961 call_expr,
962 incompatible_arg: provided_idx.as_usize(),
963 },
964 );
965 }
966
967 self.suggest_ptr_null_mut(
968 expected_ty,
969 provided_ty,
970 provided_args[provided_idx],
971 &mut err,
972 );
973
974 self.suggest_deref_unwrap_or(
975 &mut err,
976 callee_ty,
977 call_ident,
978 expected_ty,
979 provided_ty,
980 provided_args[provided_idx],
981 is_method,
982 );
983
984 self.label_fn_like(
986 &mut err,
987 fn_def_id,
988 callee_ty,
989 call_expr,
990 Some(expected_ty),
991 Some(expected_idx.as_usize()),
992 &matched_inputs,
993 &formal_and_expected_inputs,
994 is_method,
995 tuple_arguments,
996 );
997 suggest_confusable(&mut err);
998 detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
999 return err.emit();
1000 }
1001
1002 if let [Error::Extra(provided_idx)] = &errors[..] {
1007 let remove_idx_is_perfect = |idx: usize| -> bool {
1008 let removed_arg_tys = provided_arg_tys
1009 .iter()
1010 .enumerate()
1011 .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
1012 .collect::<IndexVec<ProvidedIdx, _>>();
1013 std::iter::zip(formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
1014 |((expected_ty, _), (provided_ty, _))| {
1015 !provided_ty.references_error()
1016 && self.may_coerce(*provided_ty, *expected_ty)
1017 },
1018 )
1019 };
1020
1021 if !remove_idx_is_perfect(provided_idx.as_usize()) {
1022 if let Some(i) = (0..provided_args.len()).find(|&i| remove_idx_is_perfect(i)) {
1023 errors = vec![Error::Extra(ProvidedIdx::from_usize(i))];
1024 }
1025 }
1026 }
1027
1028 let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
1029 struct_span_code_err!(
1030 self.dcx(),
1031 full_call_span,
1032 E0308,
1033 "arguments to this {} are incorrect",
1034 call_name,
1035 )
1036 } else {
1037 self.dcx()
1038 .struct_span_err(
1039 full_call_span,
1040 format!(
1041 "this {} takes {}{} but {} {} supplied",
1042 call_name,
1043 if c_variadic { "at least " } else { "" },
1044 potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
1045 potentially_plural_count(provided_args.len(), "argument"),
1046 pluralize!("was", provided_args.len())
1047 ),
1048 )
1049 .with_code(err_code.to_owned())
1050 };
1051
1052 suggest_confusable(&mut err);
1053 let mut labels = vec![];
1055 enum SuggestionText {
1058 None,
1059 Provide(bool),
1060 Remove(bool),
1061 Swap,
1062 Reorder,
1063 DidYouMean,
1064 }
1065 let mut suggestion_text = SuggestionText::None;
1066
1067 let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
1068 if ty.is_unit() {
1069 "()".to_string()
1070 } else if ty.is_suggestable(tcx, false) {
1071 format!("/* {ty} */")
1072 } else if let Some(fn_def_id) = fn_def_id
1073 && self.tcx.def_kind(fn_def_id).is_fn_like()
1074 && let self_implicit =
1075 matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
1076 && let Some(Some(arg)) =
1077 self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
1078 && arg.name != kw::SelfLower
1079 {
1080 format!("/* {} */", arg.name)
1081 } else {
1082 "/* value */".to_string()
1083 }
1084 };
1085
1086 let mut errors = errors.into_iter().peekable();
1087 let mut only_extras_so_far = errors
1088 .peek()
1089 .is_some_and(|first| matches!(first, Error::Extra(arg_idx) if arg_idx.index() == 0));
1090 let mut prev_extra_idx = None;
1091 let mut suggestions = vec![];
1092 while let Some(error) = errors.next() {
1093 only_extras_so_far &= matches!(error, Error::Extra(_));
1094
1095 match error {
1096 Error::Invalid(provided_idx, expected_idx, compatibility) => {
1097 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
1098 let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
1099 if let Compatibility::Incompatible(error) = compatibility {
1100 let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
1101 if let Some(e) = error {
1102 self.err_ctxt().note_type_err(
1103 &mut err,
1104 &trace.cause,
1105 None,
1106 Some(self.param_env.and(trace.values)),
1107 e,
1108 true,
1109 None,
1110 );
1111 }
1112 }
1113
1114 self.emit_coerce_suggestions(
1115 &mut err,
1116 provided_args[provided_idx],
1117 provided_ty,
1118 Expectation::rvalue_hint(self, expected_ty)
1119 .only_has_type(self)
1120 .unwrap_or(formal_ty),
1121 None,
1122 None,
1123 );
1124 detect_dotdot(&mut err, provided_ty, provided_args[provided_idx]);
1125 }
1126 Error::Extra(arg_idx) => {
1127 let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
1128 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1129 format!(" of type `{provided_ty}`")
1131 } else {
1132 "".to_string()
1133 };
1134 let idx = if provided_arg_tys.len() == 1 {
1135 "".to_string()
1136 } else {
1137 format!(" #{}", arg_idx.as_usize() + 1)
1138 };
1139 labels.push((
1140 provided_span,
1141 format!("unexpected argument{idx}{provided_ty_name}"),
1142 ));
1143 let mut span = provided_span;
1144 if span.can_be_used_for_suggestions()
1145 && error_span.can_be_used_for_suggestions()
1146 {
1147 if arg_idx.index() > 0
1148 && let Some((_, prev)) =
1149 provided_arg_tys.get(ProvidedIdx::from_usize(arg_idx.index() - 1))
1150 {
1151 span = prev.shrink_to_hi().to(span);
1153 }
1154
1155 let trim_next_comma = match errors.peek() {
1162 Some(Error::Extra(provided_idx))
1163 if only_extras_so_far
1164 && provided_idx.index() > arg_idx.index() + 1 =>
1165 {
1173 prev_extra_idx.is_none_or(|prev_extra_idx| {
1174 prev_extra_idx + 1 == arg_idx.index()
1175 })
1176 }
1177 None if only_extras_so_far => true,
1179 _ => false,
1181 };
1182
1183 if trim_next_comma {
1184 let next = provided_arg_tys
1185 .get(arg_idx + 1)
1186 .map(|&(_, sp)| sp)
1187 .unwrap_or_else(|| {
1188 self.tcx().sess.source_map().end_point(call_expr.span)
1193 });
1194
1195 span = span.until(next);
1197 }
1198
1199 suggestions.push((span, String::new()));
1200
1201 suggestion_text = match suggestion_text {
1202 SuggestionText::None => SuggestionText::Remove(false),
1203 SuggestionText::Remove(_) => SuggestionText::Remove(true),
1204 _ => SuggestionText::DidYouMean,
1205 };
1206 prev_extra_idx = Some(arg_idx.index())
1207 }
1208 detect_dotdot(&mut err, provided_ty, provided_args[arg_idx]);
1209 }
1210 Error::Missing(expected_idx) => {
1211 let mut missing_idxs = vec![expected_idx];
1215 while let Some(e) = errors.next_if(|e| {
1216 matches!(e, Error::Missing(next_expected_idx)
1217 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
1218 }) {
1219 match e {
1220 Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
1221 _ => unreachable!(
1222 "control flow ensures that we should always get an `Error::Missing`"
1223 ),
1224 }
1225 }
1226
1227 match &missing_idxs[..] {
1232 &[expected_idx] => {
1233 let (_, input_ty) = formal_and_expected_inputs[expected_idx];
1234 let span = if let Some((_, arg_span)) =
1235 provided_arg_tys.get(expected_idx.to_provided_idx())
1236 {
1237 *arg_span
1238 } else {
1239 args_span
1240 };
1241 let rendered = if !has_error_or_infer([input_ty]) {
1242 format!(" of type `{input_ty}`")
1243 } else {
1244 "".to_string()
1245 };
1246 labels.push((
1247 span,
1248 format!(
1249 "argument #{}{rendered} is missing",
1250 expected_idx.as_usize() + 1
1251 ),
1252 ));
1253
1254 suggestion_text = match suggestion_text {
1255 SuggestionText::None => SuggestionText::Provide(false),
1256 SuggestionText::Provide(_) => SuggestionText::Provide(true),
1257 _ => SuggestionText::DidYouMean,
1258 };
1259 }
1260 &[first_idx, second_idx] => {
1261 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
1262 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
1263 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
1264 provided_arg_tys.get(first_idx.to_provided_idx()),
1265 provided_arg_tys.get(second_idx.to_provided_idx()),
1266 ) {
1267 first_span.to(*second_span)
1268 } else {
1269 args_span
1270 };
1271 let rendered =
1272 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
1273 format!(
1274 " of type `{first_expected_ty}` and `{second_expected_ty}`"
1275 )
1276 } else {
1277 "".to_string()
1278 };
1279 labels.push((span, format!("two arguments{rendered} are missing")));
1280 suggestion_text = match suggestion_text {
1281 SuggestionText::None | SuggestionText::Provide(_) => {
1282 SuggestionText::Provide(true)
1283 }
1284 _ => SuggestionText::DidYouMean,
1285 };
1286 }
1287 &[first_idx, second_idx, third_idx] => {
1288 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
1289 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
1290 let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
1291 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
1292 provided_arg_tys.get(first_idx.to_provided_idx()),
1293 provided_arg_tys.get(third_idx.to_provided_idx()),
1294 ) {
1295 first_span.to(*third_span)
1296 } else {
1297 args_span
1298 };
1299 let rendered = if !has_error_or_infer([
1300 first_expected_ty,
1301 second_expected_ty,
1302 third_expected_ty,
1303 ]) {
1304 format!(
1305 " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
1306 )
1307 } else {
1308 "".to_string()
1309 };
1310 labels.push((span, format!("three arguments{rendered} are missing")));
1311 suggestion_text = match suggestion_text {
1312 SuggestionText::None | SuggestionText::Provide(_) => {
1313 SuggestionText::Provide(true)
1314 }
1315 _ => SuggestionText::DidYouMean,
1316 };
1317 }
1318 missing_idxs => {
1319 let first_idx = *missing_idxs.first().unwrap();
1320 let last_idx = *missing_idxs.last().unwrap();
1321 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
1325 provided_arg_tys.get(first_idx.to_provided_idx()),
1326 provided_arg_tys.get(last_idx.to_provided_idx()),
1327 ) {
1328 first_span.to(*last_span)
1329 } else {
1330 args_span
1331 };
1332 labels.push((span, "multiple arguments are missing".to_string()));
1333 suggestion_text = match suggestion_text {
1334 SuggestionText::None | SuggestionText::Provide(_) => {
1335 SuggestionText::Provide(true)
1336 }
1337 _ => SuggestionText::DidYouMean,
1338 };
1339 }
1340 }
1341 }
1342 Error::Swap(
1343 first_provided_idx,
1344 second_provided_idx,
1345 first_expected_idx,
1346 second_expected_idx,
1347 ) => {
1348 let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
1349 let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
1350 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
1351 format!(", found `{first_provided_ty}`")
1352 } else {
1353 String::new()
1354 };
1355 labels.push((
1356 first_span,
1357 format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
1358 ));
1359
1360 let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
1361 let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
1362 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
1363 format!(", found `{second_provided_ty}`")
1364 } else {
1365 String::new()
1366 };
1367 labels.push((
1368 second_span,
1369 format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
1370 ));
1371
1372 suggestion_text = match suggestion_text {
1373 SuggestionText::None => SuggestionText::Swap,
1374 _ => SuggestionText::DidYouMean,
1375 };
1376 }
1377 Error::Permutation(args) => {
1378 for (dst_arg, dest_input) in args {
1379 let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
1380 let (provided_ty, provided_span) = provided_arg_tys[dest_input];
1381 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1382 format!(", found `{provided_ty}`")
1383 } else {
1384 String::new()
1385 };
1386 labels.push((
1387 provided_span,
1388 format!("expected `{expected_ty}`{provided_ty_name}"),
1389 ));
1390 }
1391
1392 suggestion_text = match suggestion_text {
1393 SuggestionText::None => SuggestionText::Reorder,
1394 _ => SuggestionText::DidYouMean,
1395 };
1396 }
1397 }
1398 }
1399
1400 self.label_generic_mismatches(
1401 &mut err,
1402 fn_def_id,
1403 &matched_inputs,
1404 &provided_arg_tys,
1405 &formal_and_expected_inputs,
1406 is_method,
1407 );
1408
1409 let mut prev = -1;
1429 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1430 if let Some(provided_idx) = provided_idx {
1433 prev = provided_idx.index() as i64;
1434 continue;
1435 }
1436 let idx = ProvidedIdx::from_usize((prev + 1) as usize);
1437 if let Some((_, arg_span)) = provided_arg_tys.get(idx) {
1438 prev += 1;
1439 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1444 suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
1445 }
1446 }
1447
1448 if labels.len() <= 5 {
1450 for (span, label) in labels {
1451 err.span_label(span, label);
1452 }
1453 }
1454
1455 self.label_fn_like(
1457 &mut err,
1458 fn_def_id,
1459 callee_ty,
1460 call_expr,
1461 None,
1462 None,
1463 &matched_inputs,
1464 &formal_and_expected_inputs,
1465 is_method,
1466 tuple_arguments,
1467 );
1468
1469 let suggestion_text = match suggestion_text {
1471 SuggestionText::None => None,
1472 SuggestionText::Provide(plural) => {
1473 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
1474 }
1475 SuggestionText::Remove(plural) => {
1476 err.multipart_suggestion_verbose(
1477 format!("remove the extra argument{}", if plural { "s" } else { "" }),
1478 suggestions,
1479 Applicability::HasPlaceholders,
1480 );
1481 None
1482 }
1483 SuggestionText::Swap => Some("swap these arguments".to_string()),
1484 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
1485 SuggestionText::DidYouMean => Some("did you mean".to_string()),
1486 };
1487 if let Some(suggestion_text) = suggestion_text {
1488 let source_map = self.sess().source_map();
1489 let (mut suggestion, suggestion_span) = if let Some(call_span) =
1490 full_call_span.find_ancestor_inside_same_ctxt(error_span)
1491 {
1492 ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
1493 } else {
1494 (
1495 format!(
1496 "{}(",
1497 source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
1498 fn_def_id.map_or("".to_string(), |fn_def_id| {
1499 tcx.item_name(fn_def_id).to_string()
1500 })
1501 })
1502 ),
1503 error_span,
1504 )
1505 };
1506 let mut needs_comma = false;
1507 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1508 if needs_comma {
1509 suggestion += ", ";
1510 } else {
1511 needs_comma = true;
1512 }
1513 let suggestion_text = if let Some(provided_idx) = provided_idx
1514 && let (_, provided_span) = provided_arg_tys[*provided_idx]
1515 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
1516 {
1517 arg_text
1518 } else {
1519 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1521 ty_to_snippet(expected_ty, expected_idx)
1522 };
1523 suggestion += &suggestion_text;
1524 }
1525 suggestion += ")";
1526 err.span_suggestion_verbose(
1527 suggestion_span,
1528 suggestion_text,
1529 suggestion,
1530 Applicability::HasPlaceholders,
1531 );
1532 }
1533
1534 err.emit()
1535 }
1536
1537 fn suggest_ptr_null_mut(
1538 &self,
1539 expected_ty: Ty<'tcx>,
1540 provided_ty: Ty<'tcx>,
1541 arg: &hir::Expr<'tcx>,
1542 err: &mut Diag<'_>,
1543 ) {
1544 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
1545 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
1546 && let hir::ExprKind::Call(callee, _) = arg.kind
1547 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
1548 && let Res::Def(_, def_id) = path.res
1549 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
1550 {
1551 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
1554 }
1555 }
1556
1557 pub(in super::super) fn check_expr_lit(
1559 &self,
1560 lit: &hir::Lit,
1561 expected: Expectation<'tcx>,
1562 ) -> Ty<'tcx> {
1563 let tcx = self.tcx;
1564
1565 match lit.node {
1566 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
1567 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
1568 tcx,
1569 tcx.lifetimes.re_static,
1570 Ty::new_array(tcx, tcx.types.u8, v.len() as u64),
1571 ),
1572 ast::LitKind::Byte(_) => tcx.types.u8,
1573 ast::LitKind::Char(_) => tcx.types.char,
1574 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)),
1575 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)),
1576 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
1577 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1578 ty::Int(_) | ty::Uint(_) => Some(ty),
1579 ty::Char => Some(tcx.types.u8),
1583 ty::RawPtr(..) => Some(tcx.types.usize),
1584 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1585 &ty::Pat(base, _) if base.is_integral() => {
1586 let layout = tcx
1587 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1588 .ok()?;
1589 assert!(!layout.uninhabited);
1590
1591 match layout.backend_repr {
1592 rustc_abi::BackendRepr::Scalar(scalar) => {
1593 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1594 }
1595 _ => unreachable!(),
1596 }
1597 }
1598 _ => None,
1599 });
1600 opt_ty.unwrap_or_else(|| self.next_int_var())
1601 }
1602 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
1603 Ty::new_float(tcx, ty::float_ty(t))
1604 }
1605 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1606 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1607 ty::Float(_) => Some(ty),
1608 _ => None,
1609 });
1610 opt_ty.unwrap_or_else(|| self.next_float_var())
1611 }
1612 ast::LitKind::Bool(_) => tcx.types.bool,
1613 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1614 tcx,
1615 tcx.lifetimes.re_static,
1616 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span)))
1617 .skip_binder(),
1618 ),
1619 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1620 }
1621 }
1622
1623 pub(crate) fn check_struct_path(
1624 &self,
1625 qpath: &QPath<'tcx>,
1626 hir_id: HirId,
1627 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1628 let path_span = qpath.span();
1629 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1630 let variant = match def {
1631 Res::Err => {
1632 let guar =
1633 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1634 self.set_tainted_by_errors(guar);
1635 return Err(guar);
1636 }
1637 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1638 Some(adt) => {
1639 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1640 }
1641 _ => bug!("unexpected type: {:?}", ty.normalized),
1642 },
1643 Res::Def(
1644 DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
1645 _,
1646 )
1647 | Res::SelfTyParam { .. }
1648 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1649 Some(adt) if !adt.is_enum() => {
1650 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1651 }
1652 _ => None,
1653 },
1654 _ => bug!("unexpected definition: {:?}", def),
1655 };
1656
1657 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1658 debug!("check_struct_path: did={:?} args={:?}", did, args);
1659
1660 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1662
1663 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1665
1666 Ok((variant, ty.normalized))
1667 } else {
1668 Err(match *ty.normalized.kind() {
1669 ty::Error(guar) => {
1670 guar
1675 }
1676 _ => struct_span_code_err!(
1677 self.dcx(),
1678 path_span,
1679 E0071,
1680 "expected struct, variant or union type, found {}",
1681 ty.normalized.sort_string(self.tcx)
1682 )
1683 .with_span_label(path_span, "not a struct")
1684 .emit(),
1685 })
1686 }
1687 }
1688
1689 fn check_decl_initializer(
1690 &self,
1691 hir_id: HirId,
1692 pat: &'tcx hir::Pat<'tcx>,
1693 init: &'tcx hir::Expr<'tcx>,
1694 ) -> Ty<'tcx> {
1695 let ref_bindings = pat.contains_explicit_ref_binding();
1700
1701 let local_ty = self.local_ty(init.span, hir_id);
1702 if let Some(m) = ref_bindings {
1703 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1712 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1713 self.emit_type_mismatch_suggestions(
1714 &mut diag,
1715 init.peel_drop_temps(),
1716 init_ty,
1717 local_ty,
1718 None,
1719 None,
1720 );
1721 diag.emit();
1722 }
1723 init_ty
1724 } else {
1725 self.check_expr_coercible_to_type(init, local_ty, None)
1726 }
1727 }
1728
1729 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1730 let decl_ty = self.local_ty(decl.span, decl.hir_id);
1732
1733 if let Some(ref init) = decl.init {
1735 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1736 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1737 }
1738
1739 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1741 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
1743 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1744 } _ => (None, None), };
1747
1748 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1750 let pat_ty = self.node_ty(decl.pat.hir_id);
1751 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1752
1753 if let Some(blk) = decl.origin.try_get_else() {
1754 let previous_diverges = self.diverges.get();
1755 let else_ty = self.check_expr_block(blk, NoExpectation);
1756 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1757 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1758 {
1759 err.emit();
1760 }
1761 self.diverges.set(previous_diverges);
1762 }
1763 decl_ty
1764 }
1765
1766 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1768 GatherLocalsVisitor::gather_from_local(self, local);
1769
1770 let ty = self.check_decl(local.into());
1771 self.write_ty(local.hir_id, ty);
1772 if local.pat.is_never_pattern() {
1773 self.diverges.set(Diverges::Always {
1774 span: local.pat.span,
1775 custom_note: Some("any code following a never pattern is unreachable"),
1776 });
1777 }
1778 }
1779
1780 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1781 match stmt.kind {
1783 hir::StmtKind::Item(..) => return,
1784 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1785 }
1786
1787 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1788
1789 let old_diverges = self.diverges.replace(Diverges::Maybe);
1791
1792 match stmt.kind {
1793 hir::StmtKind::Let(l) => {
1794 self.check_decl_local(l);
1795 }
1796 hir::StmtKind::Item(_) => {}
1798 hir::StmtKind::Expr(ref expr) => {
1799 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1801 if expr.can_have_side_effects() {
1802 self.suggest_semicolon_at_end(expr.span, err);
1803 }
1804 });
1805 }
1806 hir::StmtKind::Semi(expr) => {
1807 self.check_expr(expr);
1808 }
1809 }
1810
1811 self.diverges.set(self.diverges.get() | old_diverges);
1813 }
1814
1815 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1816 let unit = self.tcx.types.unit;
1817 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1818
1819 if !ty.is_never() {
1822 self.demand_suptype(blk.span, unit, ty);
1823 }
1824 }
1825
1826 pub(in super::super) fn check_expr_block(
1827 &self,
1828 blk: &'tcx hir::Block<'tcx>,
1829 expected: Expectation<'tcx>,
1830 ) -> Ty<'tcx> {
1831 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1848 let coerce = if blk.targeted_by_break {
1849 CoerceMany::new(coerce_to_ty)
1850 } else {
1851 CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
1852 };
1853
1854 let prev_diverges = self.diverges.get();
1855 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1856
1857 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1858 for s in blk.stmts {
1859 self.check_stmt(s);
1860 }
1861
1862 let tail_expr_ty =
1865 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1866
1867 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1868 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1869 let coerce = ctxt.coerce.as_mut().unwrap();
1870 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1871 let span = self.get_expr_coercion_span(tail_expr);
1872 let cause = self.cause(
1873 span,
1874 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1875 );
1876 let ty_for_diagnostic = coerce.merged_ty();
1877 coerce.coerce_inner(
1881 self,
1882 &cause,
1883 Some(tail_expr),
1884 tail_expr_ty,
1885 |diag| {
1886 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1887 },
1888 false,
1889 );
1890 } else {
1891 if !self.diverges.get().is_always()
1902 || matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1903 {
1904 let mut sp = blk.span;
1910 let mut fn_span = None;
1911 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1912 let ret_sp = decl.output.span();
1913 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1914 if block_sp == blk.span {
1918 sp = ret_sp;
1919 fn_span = self.tcx.def_ident_span(fn_def_id);
1920 }
1921 }
1922 }
1923 coerce.coerce_forced_unit(
1924 self,
1925 &self.misc(sp),
1926 |err| {
1927 if let Some(expected_ty) = expected.only_has_type(self) {
1928 if blk.stmts.is_empty() && blk.expr.is_none() {
1929 self.suggest_boxing_when_appropriate(
1930 err,
1931 blk.span,
1932 blk.hir_id,
1933 expected_ty,
1934 self.tcx.types.unit,
1935 );
1936 }
1937 if !self.err_ctxt().consider_removing_semicolon(
1938 blk,
1939 expected_ty,
1940 err,
1941 ) {
1942 self.err_ctxt().consider_returning_binding(
1943 blk,
1944 expected_ty,
1945 err,
1946 );
1947 }
1948 if expected_ty == self.tcx.types.bool {
1949 if let hir::Block {
1954 stmts:
1955 [
1956 hir::Stmt {
1957 kind:
1958 hir::StmtKind::Let(hir::LetStmt {
1959 source:
1960 hir::LocalSource::AssignDesugar(_),
1961 ..
1962 }),
1963 ..
1964 },
1965 hir::Stmt {
1966 kind:
1967 hir::StmtKind::Expr(hir::Expr {
1968 kind: hir::ExprKind::Assign(lhs, ..),
1969 ..
1970 }),
1971 ..
1972 },
1973 ],
1974 ..
1975 } = blk
1976 {
1977 self.comes_from_while_condition(blk.hir_id, |_| {
1978 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
1982
1983 if !lhs.is_syntactic_place_expr()
1984 || res.references_error()
1985 {
1986 err.downgrade_to_delayed_bug();
1987 }
1988 })
1989 }
1990 }
1991 }
1992 if let Some(fn_span) = fn_span {
1993 err.span_label(
1994 fn_span,
1995 "implicitly returns `()` as its body has no tail or `return` \
1996 expression",
1997 );
1998 }
1999 },
2000 false,
2001 );
2002 }
2003 }
2004 });
2005
2006 if ctxt.may_break {
2007 self.diverges.set(prev_diverges);
2010 }
2011
2012 let ty = ctxt.coerce.unwrap().complete(self);
2013
2014 self.write_ty(blk.hir_id, ty);
2015
2016 ty
2017 }
2018
2019 fn parent_item_span(&self, id: HirId) -> Option<Span> {
2020 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
2021 match node {
2022 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
2023 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
2024 let body = self.tcx.hir_body(body_id);
2025 if let ExprKind::Block(block, _) = &body.value.kind {
2026 return Some(block.span);
2027 }
2028 }
2029 _ => {}
2030 }
2031 None
2032 }
2033
2034 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
2042 let check_in_progress = |elem: &hir::Expr<'_>| {
2043 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
2044 |_| match elem.kind {
2045 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
2047 _ => elem.span,
2048 },
2049 )
2050 };
2051
2052 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
2053 if let Some(rslt) = check_in_progress(el) {
2054 return rslt;
2055 }
2056 }
2057
2058 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
2059 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
2060 if let Some(span) = iter.next() {
2061 if iter.next().is_none() {
2062 return span;
2063 }
2064 }
2065 }
2066
2067 expr.span
2068 }
2069
2070 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
2071 if let Err(guar) = ty.error_reported() {
2072 struct OverwritePatternsWithError {
2073 pat_hir_ids: Vec<hir::HirId>,
2074 }
2075 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
2076 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
2077 self.pat_hir_ids.push(p.hir_id);
2078 hir::intravisit::walk_pat(self, p);
2079 }
2080 }
2081 let err = Ty::new_error(self.tcx, guar);
2083 self.write_ty(hir_id, err);
2084 self.write_ty(pat.hir_id, err);
2085 let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
2086 hir::intravisit::walk_pat(&mut visitor, pat);
2087 for hir_id in visitor.pat_hir_ids {
2090 self.write_ty(hir_id, err);
2091 }
2092 self.locals.borrow_mut().insert(hir_id, err);
2093 self.locals.borrow_mut().insert(pat.hir_id, err);
2094 }
2095 }
2096
2097 fn finish_resolving_struct_path(
2100 &self,
2101 qpath: &QPath<'tcx>,
2102 path_span: Span,
2103 hir_id: HirId,
2104 ) -> (Res, LoweredTy<'tcx>) {
2105 match *qpath {
2106 QPath::Resolved(ref maybe_qself, path) => {
2107 let self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself).raw);
2108 let ty = self.lowerer().lower_path(self_ty, path, hir_id, true);
2109 (path.res, LoweredTy::from_raw(self, path_span, ty))
2110 }
2111 QPath::TypeRelative(qself, segment) => {
2112 let ty = self.lower_ty(qself);
2113
2114 let result = self
2115 .lowerer()
2116 .lower_assoc_path_ty(hir_id, path_span, ty.raw, qself, segment, true);
2117 let ty = result
2118 .map(|(ty, _, _)| ty)
2119 .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
2120 let ty = LoweredTy::from_raw(self, path_span, ty);
2121 let result = result.map(|(_, kind, def_id)| (kind, def_id));
2122
2123 self.write_resolution(hir_id, result);
2125
2126 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
2127 }
2128 QPath::LangItem(lang_item, span) => {
2129 let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
2130 (res, LoweredTy::from_raw(self, path_span, ty))
2131 }
2132 }
2133 }
2134
2135 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
2142 &self,
2143 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
2144 ) {
2145 let mut remap_cause = FxIndexSet::default();
2151 let mut not_adjusted = vec![];
2152
2153 for error in errors {
2154 let before_span = error.obligation.cause.span;
2155 if self.adjust_fulfillment_error_for_expr_obligation(error)
2156 || before_span != error.obligation.cause.span
2157 {
2158 remap_cause.insert((
2159 before_span,
2160 error.obligation.predicate,
2161 error.obligation.cause.clone(),
2162 ));
2163 } else {
2164 not_adjusted.push(error);
2167 }
2168 }
2169
2170 for error in not_adjusted {
2178 for (span, predicate, cause) in &remap_cause {
2179 if *predicate == error.obligation.predicate
2180 && span.contains(error.obligation.cause.span)
2181 {
2182 error.obligation.cause = cause.clone();
2183 continue;
2184 }
2185 }
2186 }
2187 }
2188
2189 fn label_fn_like(
2190 &self,
2191 err: &mut Diag<'_>,
2192 callable_def_id: Option<DefId>,
2193 callee_ty: Option<Ty<'tcx>>,
2194 call_expr: &'tcx hir::Expr<'tcx>,
2195 expected_ty: Option<Ty<'tcx>>,
2196 expected_idx: Option<usize>,
2198 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2199 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2200 is_method: bool,
2201 tuple_arguments: TupleArgumentsFlag,
2202 ) {
2203 let Some(mut def_id) = callable_def_id else {
2204 return;
2205 };
2206
2207 if tuple_arguments == TupleArguments
2212 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
2213 && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
2218 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
2219 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
2221 && let Some(callee_ty) = callee_ty
2222 {
2223 let callee_ty = callee_ty.peel_refs();
2224 match *callee_ty.kind() {
2225 ty::Param(param) => {
2226 let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
2227 if param.kind.is_synthetic() {
2228 def_id = param.def_id;
2230 } else {
2231 let instantiated = self
2234 .tcx
2235 .explicit_predicates_of(self.body_id)
2236 .instantiate_identity(self.tcx);
2237 for (predicate, span) in instantiated {
2241 if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder()
2242 && pred.self_ty().peel_refs() == callee_ty
2243 && self.tcx.is_fn_trait(pred.def_id())
2244 {
2245 err.span_note(span, "callable defined here");
2246 return;
2247 }
2248 }
2249 }
2250 }
2251 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
2252 | ty::Closure(new_def_id, _)
2253 | ty::FnDef(new_def_id, _) => {
2254 def_id = new_def_id;
2255 }
2256 _ => {
2257 let new_def_id = self.probe(|_| {
2259 let trait_ref = ty::TraitRef::new(
2260 self.tcx,
2261 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
2262 [callee_ty, self.next_ty_var(DUMMY_SP)],
2263 );
2264 let obligation = traits::Obligation::new(
2265 self.tcx,
2266 traits::ObligationCause::dummy(),
2267 self.param_env,
2268 trait_ref,
2269 );
2270 match SelectionContext::new(self).select(&obligation) {
2271 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
2272 Some(impl_source.impl_def_id)
2273 }
2274 _ => None,
2275 }
2276 });
2277 if let Some(new_def_id) = new_def_id {
2278 def_id = new_def_id;
2279 } else {
2280 return;
2281 }
2282 }
2283 }
2284 }
2285
2286 if let Some(def_span) = self.tcx.def_ident_span(def_id)
2287 && !def_span.is_dummy()
2288 {
2289 let mut spans: MultiSpan = def_span.into();
2290 if let Some((params_with_generics, hir_generics)) =
2291 self.get_hir_param_info(def_id, is_method)
2292 {
2293 struct MismatchedParam<'a> {
2294 idx: ExpectedIdx,
2295 generic: GenericIdx,
2296 param: &'a FnParam<'a>,
2297 deps: SmallVec<[ExpectedIdx; 4]>,
2298 }
2299
2300 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2301 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
2303 if let Some(expected_idx) = expected_idx {
2304 let expected_idx = ExpectedIdx::from_usize(expected_idx);
2305 let &(expected_generic, ref expected_param) =
2306 ¶ms_with_generics[expected_idx];
2307 if let Some(expected_generic) = expected_generic {
2308 mismatched_params.push(MismatchedParam {
2309 idx: expected_idx,
2310 generic: expected_generic,
2311 param: expected_param,
2312 deps: SmallVec::new(),
2313 });
2314 } else {
2315 spans.push_span_label(expected_param.span(), "");
2317 }
2318 } else {
2319 mismatched_params.extend(
2320 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
2321 |((idx, &(generic, ref param)), matched_idx)| {
2322 if matched_idx.is_some() {
2323 None
2324 } else if let Some(generic) = generic {
2325 Some(MismatchedParam {
2326 idx,
2327 generic,
2328 param,
2329 deps: SmallVec::new(),
2330 })
2331 } else {
2332 spans.push_span_label(param.span(), "");
2334 None
2335 }
2336 },
2337 ),
2338 );
2339 }
2340
2341 if !mismatched_params.is_empty() {
2342 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
2345 |_| SmallVec::<[u32; 4]>::new(),
2346 params_with_generics.len(),
2347 );
2348 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
2349 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
2350 hir_generics.params.len(),
2351 );
2352 for (idx, param) in mismatched_params.iter_mut().enumerate() {
2353 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
2354 params_with_generics.iter_enumerated().zip(matched_inputs)
2355 {
2356 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
2357 generic_uses[param.generic].extend([param.idx, other_idx]);
2358 dependants[other_idx].push(idx as u32);
2359 param.deps.push(other_idx);
2360 }
2361 }
2362 }
2363
2364 for param in &mismatched_params {
2367 if let Some(deps_list) = listify(¶m.deps, |&dep| {
2368 params_with_generics[dep].1.display(dep.as_usize()).to_string()
2369 }) {
2370 spans.push_span_label(
2371 param.param.span(),
2372 format!(
2373 "this parameter needs to match the {} type of {deps_list}",
2374 self.resolve_vars_if_possible(
2375 formal_and_expected_inputs[param.deps[0]].1
2376 )
2377 .sort_string(self.tcx),
2378 ),
2379 );
2380 } else {
2381 spans.push_span_label(param.param.span(), "");
2383 }
2384 }
2385 for ((&(_, param), deps), &(_, expected_ty)) in
2387 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
2388 {
2389 if let Some(deps_list) = listify(deps, |&dep| {
2390 let param = &mismatched_params[dep as usize];
2391 param.param.display(param.idx.as_usize()).to_string()
2392 }) {
2393 spans.push_span_label(
2394 param.span(),
2395 format!(
2396 "{deps_list} need{} to match the {} type of this parameter",
2397 pluralize!((deps.len() != 1) as u32),
2398 self.resolve_vars_if_possible(expected_ty)
2399 .sort_string(self.tcx),
2400 ),
2401 );
2402 }
2403 }
2404 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
2406 uses.sort();
2407 uses.dedup();
2408 if let Some(param_list) = listify(uses, |&idx| {
2409 params_with_generics[idx].1.display(idx.as_usize()).to_string()
2410 }) {
2411 spans.push_span_label(
2412 param.span,
2413 format!(
2414 "{param_list} {} reference this parameter `{}`",
2415 if uses.len() == 2 { "both" } else { "all" },
2416 param.name.ident().name,
2417 ),
2418 );
2419 }
2420 }
2421 }
2422 }
2423 err.span_note(spans, format!("{} defined here", self.tcx.def_descr(def_id)));
2424 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
2425 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
2426 {
2427 let param = expected_idx
2428 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
2429 let (kind, span) = if let Some(param) = param {
2430 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: vec![] };
2433 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
2434 match self.tcx.hir_node_by_def_id(parent_def_id) {
2435 hir::Node::Item(item) => call_finder.visit_item(item),
2436 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
2437 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
2438 _ => {}
2439 }
2440 let typeck = self.typeck_results.borrow();
2441 for (rcvr, args) in call_finder.calls {
2442 if rcvr.hir_id.owner == typeck.hir_owner
2443 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
2444 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
2445 && def_id == *call_def_id
2446 && let Some(idx) = expected_idx
2447 && let Some(arg) = args.get(idx)
2448 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
2449 && let Some(expected_ty) = expected_ty
2450 && self.can_eq(self.param_env, arg_ty, expected_ty)
2451 {
2452 let mut sp: MultiSpan = vec![arg.span].into();
2453 sp.push_span_label(
2454 arg.span,
2455 format!("expected because this argument is of type `{arg_ty}`"),
2456 );
2457 sp.push_span_label(rcvr.span, "in this closure call");
2458 err.span_note(
2459 sp,
2460 format!(
2461 "expected because the closure was earlier called with an \
2462 argument of type `{arg_ty}`",
2463 ),
2464 );
2465 break;
2466 }
2467 }
2468
2469 ("closure parameter", param.span)
2470 } else {
2471 ("closure", self.tcx.def_span(def_id))
2472 };
2473 err.span_note(span, format!("{kind} defined here"));
2474 } else {
2475 err.span_note(
2476 self.tcx.def_span(def_id),
2477 format!("{} defined here", self.tcx.def_descr(def_id)),
2478 );
2479 }
2480 }
2481
2482 fn label_generic_mismatches(
2483 &self,
2484 err: &mut Diag<'_>,
2485 callable_def_id: Option<DefId>,
2486 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2487 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
2488 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2489 is_method: bool,
2490 ) {
2491 let Some(def_id) = callable_def_id else {
2492 return;
2493 };
2494
2495 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
2496 debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2497 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
2498 if matched_inputs[idx].is_none() {
2499 continue;
2500 }
2501
2502 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
2503 else {
2504 continue;
2505 };
2506
2507 let Some(generic_param) = generic_param else {
2508 continue;
2509 };
2510
2511 let idxs_matched = params_with_generics
2512 .iter_enumerated()
2513 .filter(|&(other_idx, (other_generic_param, _))| {
2514 if other_idx == idx {
2515 return false;
2516 }
2517 let Some(other_generic_param) = other_generic_param else {
2518 return false;
2519 };
2520 if matched_inputs[other_idx].is_some() {
2521 return false;
2522 }
2523 other_generic_param == generic_param
2524 })
2525 .count();
2526
2527 if idxs_matched == 0 {
2528 continue;
2529 }
2530
2531 let expected_display_type = self
2532 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
2533 .sort_string(self.tcx);
2534 let label = if idxs_matched == params_with_generics.len() - 1 {
2535 format!(
2536 "expected all arguments to be this {} type because they need to match the type of this parameter",
2537 expected_display_type
2538 )
2539 } else {
2540 format!(
2541 "expected some other arguments to be {} {} type to match the type of this parameter",
2542 a_or_an(&expected_display_type),
2543 expected_display_type,
2544 )
2545 };
2546
2547 err.span_label(*matched_arg_span, label);
2548 }
2549 }
2550 }
2551
2552 fn get_hir_param_info(
2557 &self,
2558 def_id: DefId,
2559 is_method: bool,
2560 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2561 {
2562 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2563 hir::Node::TraitItem(&hir::TraitItem {
2564 generics,
2565 kind: hir::TraitItemKind::Fn(sig, trait_fn),
2566 ..
2567 }) => match trait_fn {
2568 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2569 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2570 },
2571 hir::Node::ImplItem(&hir::ImplItem {
2572 generics,
2573 kind: hir::ImplItemKind::Fn(sig, body),
2574 ..
2575 })
2576 | hir::Node::Item(&hir::Item {
2577 kind: hir::ItemKind::Fn { sig, generics, body, .. },
2578 ..
2579 }) => (sig, generics, Some(body), None),
2580 hir::Node::ForeignItem(&hir::ForeignItem {
2581 kind: hir::ForeignItemKind::Fn(sig, params, generics),
2582 ..
2583 }) => (sig, generics, None, Some(params)),
2584 _ => return None,
2585 };
2586
2587 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2590 if let hir::TyKind::Path(QPath::Resolved(
2591 _,
2592 &hir::Path { res: Res::Def(_, res_def_id), .. },
2593 )) = param.kind
2594 {
2595 generics
2596 .params
2597 .iter()
2598 .position(|param| param.def_id.to_def_id() == res_def_id)
2599 .map(GenericIdx::from_usize)
2600 } else {
2601 None
2602 }
2603 });
2604 match (body_id, params) {
2605 (Some(_), Some(_)) | (None, None) => unreachable!(),
2606 (Some(body), None) => {
2607 let params = self.tcx.hir_body(body).params;
2608 let params =
2609 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2610 debug_assert_eq!(params.len(), fn_inputs.len());
2611 Some((
2612 fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect(),
2613 generics,
2614 ))
2615 }
2616 (None, Some(params)) => {
2617 let params =
2618 params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
2619 debug_assert_eq!(params.len(), fn_inputs.len());
2620 Some((
2621 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2622 generics,
2623 ))
2624 }
2625 }
2626 }
2627}
2628
2629struct FindClosureArg<'tcx> {
2630 tcx: TyCtxt<'tcx>,
2631 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2632}
2633
2634impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2635 type NestedFilter = rustc_middle::hir::nested_filter::All;
2636
2637 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2638 self.tcx
2639 }
2640
2641 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2642 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2643 self.calls.push((rcvr, args));
2644 }
2645 hir::intravisit::walk_expr(self, ex);
2646 }
2647}
2648
2649#[derive(Clone, Copy)]
2650enum FnParam<'hir> {
2651 Param(&'hir hir::Param<'hir>),
2652 Ident(Option<Ident>),
2653}
2654
2655impl FnParam<'_> {
2656 fn span(&self) -> Span {
2657 match self {
2658 Self::Param(param) => param.span,
2659 Self::Ident(ident) => {
2660 if let Some(ident) = ident {
2661 ident.span
2662 } else {
2663 DUMMY_SP
2664 }
2665 }
2666 }
2667 }
2668
2669 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2670 struct D<'a>(FnParam<'a>, usize);
2671 impl fmt::Display for D<'_> {
2672 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2673 let unique_name = match self.0 {
2676 FnParam::Param(param)
2677 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2678 {
2679 Some(ident.name)
2680 }
2681 FnParam::Ident(ident)
2682 if let Some(ident) = ident
2683 && ident.name != kw::Underscore =>
2684 {
2685 Some(ident.name)
2686 }
2687 _ => None,
2688 };
2689 if let Some(unique_name) = unique_name {
2690 write!(f, "`{unique_name}`")
2691 } else {
2692 write!(f, "parameter #{}", self.1 + 1)
2693 }
2694 }
2695 }
2696 D(*self, idx)
2697 }
2698}