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