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