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