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