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