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