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_data_structures::thin_vec::ThinVec;
8use rustc_errors::codes::*;
9use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
10use rustc_hir as hir;
11use rustc_hir::attrs::DivergingBlockBehavior;
12use rustc_hir::attrs::lang_items::LangItem;
13use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
14use rustc_hir::def_id::DefId;
15use rustc_hir::intravisit::Visitor;
16use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, Node, QPath, is_range_literal};
17use rustc_hir_analysis::check::potentially_plural_count;
18use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath};
19use rustc_index::IndexVec;
20use rustc_infer::infer::{
21 BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace, relate,
22};
23use rustc_middle::ty::adjustment::AllowTwoPhase;
24use rustc_middle::ty::error::{ExpectedFound, TypeError};
25use rustc_middle::ty::print::with_forced_trimmed_paths;
26use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
27use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
28use rustc_middle::{bug, span_bug};
29use rustc_session::Session;
30use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
31use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
32use rustc_trait_selection::infer::InferCtxtExt;
33use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
34use smallvec::SmallVec;
35use tracing::debug;
36
37use crate::Expectation::*;
38use crate::TupleArgumentsFlag::*;
39use crate::callee::SplatLoweringInfo;
40use crate::coercion::CoerceMany;
41use crate::diagnostics::{ExprParenthesesNeeded, SuggestPtrNullMut};
42use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
43use crate::gather_locals::Declaration;
44use crate::inline_asm::InlineAsmCtxt;
45use crate::method::probe::IsSuggestion;
46use crate::method::probe::Mode::MethodCall;
47use crate::method::probe::ProbeScope::TraitsInScope;
48use crate::{
49 BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
50 TupleArgumentsFlag, diagnostics, struct_span_code_err,
51};
52
53impl ::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! {
54 #[orderable]
55 #[debug_format = "GenericIdx({})"]
56 pub(crate) struct GenericIdx {}
57}
58
59#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for TupledArgCheckOutcome<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"TupledArgCheckOutcome", "new_err_code", &self.new_err_code,
"untupled_formal_input_tys", &self.untupled_formal_input_tys,
"untupled_expected_input_tys", &&self.untupled_expected_input_tys)
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TupledArgCheckOutcome<'tcx> {
#[inline]
fn clone(&self) -> TupledArgCheckOutcome<'tcx> {
TupledArgCheckOutcome {
new_err_code: ::core::clone::Clone::clone(&self.new_err_code),
untupled_formal_input_tys: ::core::clone::Clone::clone(&self.untupled_formal_input_tys),
untupled_expected_input_tys: ::core::clone::Clone::clone(&self.untupled_expected_input_tys),
}
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for TupledArgCheckOutcome<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<ErrCode>>;
let _: ::core::cmp::AssertParamIsEq<Vec<Ty<'tcx>>>;
let _: ::core::cmp::AssertParamIsEq<Option<Vec<Ty<'tcx>>>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for TupledArgCheckOutcome<'tcx> {
#[inline]
fn eq(&self, other: &TupledArgCheckOutcome<'tcx>) -> bool {
self.new_err_code == other.new_err_code &&
self.untupled_formal_input_tys ==
other.untupled_formal_input_tys &&
self.untupled_expected_input_tys ==
other.untupled_expected_input_tys
}
}PartialEq)]
61struct TupledArgCheckOutcome<'tcx> {
62 new_err_code: Option<ErrCode>,
64
65 untupled_formal_input_tys: Vec<Ty<'tcx>>,
67
68 untupled_expected_input_tys: Option<Vec<Ty<'tcx>>>,
70}
71
72impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
73 pub(in super::super) fn check_casts(&mut self) {
74 let mut deferred_cast_checks = self.root_ctxt.deferred_cast_checks.borrow_mut();
75 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:75",
"rustc_hir_typeck::fn_ctxt::checks",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs"),
::tracing_core::__macro_support::Option::Some(75u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_casts: {0} deferred checks",
deferred_cast_checks.len()) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
76 for cast in deferred_cast_checks.drain(..) {
77 let body_def_id = std::mem::replace(&mut self.body_def_id, cast.body_def_id);
78 cast.check(self);
79 self.body_def_id = body_def_id;
80 }
81 }
82
83 pub(in super::super) fn check_asms(&self) {
84 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
85 {
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:85",
"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(85u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_asm: {0} deferred checks",
deferred_asm_checks.len()) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
86 for (asm, hir_id) in deferred_asm_checks.drain(..) {
87 let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
88 InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
89 }
90 }
91
92 pub(in super::super) fn check_repeat_exprs(&self) {
93 let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
94 {
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:94",
"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(94u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_repeat_exprs: {0} deferred checks",
deferred_repeat_expr_checks.len()) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
95
96 let deferred_repeat_expr_checks = deferred_repeat_expr_checks
97 .drain(..)
98 .flat_map(|(element, element_ty, count)| {
99 match &element.kind {
103 hir::ExprKind::ConstBlock(..) => return None,
104 hir::ExprKind::Path(qpath) => {
105 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
106 if let Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, _) = res
107 {
108 return None;
109 }
110 }
111 _ => {}
112 }
113
114 let count = self.structurally_resolve_const(
119 element.span,
120 self.normalize(element.span, Unnormalized::new_wip(count)),
121 );
122
123 if count.references_error() {
127 return None;
128 }
129
130 Some((element, element_ty, count))
131 })
132 .collect::<Vec<_>>();
138
139 let enforce_copy_bound = |element: &hir::Expr<'_>, element_ty| {
140 let is_constable = match element.kind {
144 hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
145 ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
146 traits::IsConstable::Fn
147 }
148 _ => traits::IsConstable::No,
149 },
150 hir::ExprKind::Path(qpath) => {
151 match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
152 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
153 _ => traits::IsConstable::No,
154 }
155 }
156 _ => traits::IsConstable::No,
157 };
158
159 let lang_item = self.tcx.require_lang_item(LangItem::Copy, element.span);
160 let code = traits::ObligationCauseCode::RepeatElementCopy {
161 is_constable,
162 elt_span: element.span,
163 };
164 self.require_type_meets(element_ty, element.span, code, lang_item);
165 };
166
167 for (element, element_ty, count) in deferred_repeat_expr_checks {
168 match count.kind() {
169 ty::ConstKind::Value(val) => {
170 if val.try_to_target_usize(self.tcx).is_none_or(|count| count > 1) {
171 enforce_copy_bound(element, element_ty)
172 } else {
173 }
176 }
177
178 ty::ConstKind::Param(_)
181 | ty::ConstKind::Expr(_)
182 | ty::ConstKind::Placeholder(_)
183 | ty::ConstKind::Alias(_, _) => enforce_copy_bound(element, element_ty),
184
185 ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => {
186 ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
187 }
188 }
189 }
190 }
191
192 pub(in super::super) fn check_argument_types(
195 &self,
196 call_span: Span,
198 call_expr: &'tcx hir::Expr<'tcx>,
200 formal_input_tys: &[Ty<'tcx>],
202 formal_output: Ty<'tcx>,
203 expectation: Expectation<'tcx>,
205 provided_args: &'tcx [hir::Expr<'tcx>],
207 c_variadic: bool,
209 tuple_arguments: TupleArgumentsFlag,
211 fn_id: SplatLoweringInfo<'tcx>,
213 callee_generic_args: Option<ty::GenericArgsRef<'tcx>>,
215 ) {
216 let tcx = self.tcx;
217
218 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
233 self.register_wf_obligation(
234 fn_input_ty.into(),
235 arg_expr.span,
236 ObligationCauseCode::WellFormed(None),
237 );
238
239 self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
240 }
241
242 let mut expected_input_tys: Option<Vec<_>> = expectation
248 .only_has_type(self)
249 .and_then(|expected_output| {
250 let formal_output = self.resolve_vars_with_obligations(formal_output);
251 let expected_input_tys = self
257 .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().no_errors() {
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::<Vec<_>>(),
289 ))
290 })
291 .ok()?;
292
293 Some(expected_input_tys.map(|expected_input_tys| {
294 expected_input_tys
295 .into_iter()
296 .zip(formal_input_tys)
297 .map(|(expected_input_ty, formal_input_ty)| {
307 if same_type_modulo_vars(tcx, expected_input_ty, *formal_input_ty) {
308 *formal_input_ty
310 } else {
311 expected_input_ty
312 }
313 })
314 .collect()
315 }))
316 })
317 .unwrap_or_default();
318
319 let mut err_code = E0061;
320
321 let mut formal_input_tys = formal_input_tys.to_vec();
322
323 if tuple_arguments.is_tupled() {
325 let outcome = self.check_tupled_arguments(
328 call_span,
329 call_expr,
330 formal_input_tys,
331 provided_args,
332 expected_input_tys,
333 tuple_arguments,
334 fn_id,
335 callee_generic_args,
336 );
337 let TupledArgCheckOutcome {
338 new_err_code,
339 untupled_formal_input_tys,
340 untupled_expected_input_tys,
341 } = outcome;
342 if let Some(new_err_code) = new_err_code {
343 err_code = new_err_code;
344 }
345 formal_input_tys = untupled_formal_input_tys;
346 expected_input_tys = untupled_expected_input_tys;
347 }
348
349 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
351 {
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());
352 expected_input_tys
353 } else {
354 formal_input_tys.clone()
355 };
356
357 let minimum_input_count = expected_input_tys.len();
358 let provided_arg_count = provided_args.len();
359
360 let demand_compatible = |idx| {
364 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
365 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
366 let provided_arg: &hir::Expr<'tcx> = &provided_args[idx];
367
368 {
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:368",
"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(368u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("checking argument {0}: {1:?} = {2:?}",
idx, provided_arg, formal_input_ty) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
369
370 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
374
375 let checked_ty = self
378 .tcx
379 .hir_opt_delegation_info(self.body_def_id)
380 .and_then(|_| self.typeck_results.borrow().node_type_opt(provided_arg.hir_id))
381 .unwrap_or_else(|| self.check_expr_with_expectation(provided_arg, expectation));
382
383 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
387
388 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
392
393 let coerce_error =
394 self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
395 if coerce_error.is_some() {
396 return Compatibility::Incompatible(coerce_error);
397 }
398
399 let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
402 DefineOpaqueTypes::Yes,
403 formal_input_ty,
404 coerced_ty,
405 );
406
407 match formal_ty_error {
409 Ok(InferOk { obligations, value: () }) => {
410 self.register_predicates(obligations);
411 Compatibility::Compatible
412 }
413 Err(err) => Compatibility::Incompatible(Some(err)),
414 }
415 };
416
417 let mut compatibility_diagonal =
420 ::alloc::vec::from_elem(Compatibility::Incompatible(None),
provided_args.len())vec![Compatibility::Incompatible(None); provided_args.len()];
421
422 let mut call_appears_satisfied = if c_variadic {
427 provided_arg_count >= minimum_input_count
428 } else {
429 provided_arg_count == minimum_input_count
430 };
431
432 for check_closures in [false, true] {
438 if check_closures {
442 self.select_obligations_where_possible(|_| {})
443 }
444
445 for (idx, arg) in provided_args.iter().enumerate() {
448 if !check_closures {
452 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
453 }
454
455 if idx >= minimum_input_count {
461 continue;
462 }
463
464 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
470 !tcx.coroutine_is_async(closure.def_id.to_def_id())
471 } else {
472 false
473 };
474 if is_closure != check_closures {
475 continue;
476 }
477
478 let compatible = demand_compatible(idx);
479 let is_compatible = #[allow(non_exhaustive_omitted_patterns)] match compatible {
Compatibility::Compatible => true,
_ => false,
}matches!(compatible, Compatibility::Compatible);
480 compatibility_diagonal[idx] = compatible;
481
482 if !is_compatible {
483 call_appears_satisfied = false;
484 }
485 }
486 }
487
488 if c_variadic && provided_arg_count < minimum_input_count {
489 err_code = E0060;
490 }
491
492 for arg in provided_args.iter().skip(minimum_input_count) {
493 let arg_ty = self.check_expr(arg);
495
496 if c_variadic {
501 fn variadic_error<'tcx>(
502 sess: &'tcx Session,
503 span: Span,
504 ty: Ty<'tcx>,
505 cast_ty: &str,
506 ) {
507 sess.dcx().emit_err(diagnostics::PassToVariadicFunction {
508 span,
509 ty,
510 cast_ty,
511 sugg_span: span.shrink_to_hi(),
512 teach: sess.teach(E0617),
513 });
514 }
515
516 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
525 if let Some(trait_def_id) = tcx.lang_items().va_arg_safe()
526 && self
527 .type_implements_trait(trait_def_id, [arg_ty], self.param_env)
528 .must_apply_modulo_regions()
529 {
530 continue;
531 }
532
533 match arg_ty.kind() {
534 ty::Float(ty::FloatTy::F32) => {
535 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
536 }
537 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
538 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
539 }
540 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
541 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
542 }
543 ty::FnDef(..) => {
544 let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
545 let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
546
547 let fn_item_spa = arg.span;
548 tcx.sess.dcx().emit_err(diagnostics::PassFnItemToVariadicFunction {
549 span: fn_item_spa,
550 sugg_span: fn_item_spa.shrink_to_hi(),
551 replace: fn_ptr,
552 });
553 }
554 _ => {}
555 }
556 }
557 }
558
559 if !call_appears_satisfied {
560 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
561 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
562 minimum_input_count
563 } else {
564 provided_arg_count
565 }));
566 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!(
567 formal_input_tys.len(),
568 expected_input_tys.len(),
569 "expected formal_input_tys to be the same size as expected_input_tys"
570 );
571 let formal_and_expected_inputs = IndexVec::from_iter(
572 formal_input_tys
573 .iter()
574 .copied()
575 .zip_eq(expected_input_tys.iter().copied())
576 .map(|vars| self.resolve_vars_if_possible(vars)),
577 );
578
579 self.report_arg_errors(
580 compatibility_diagonal,
581 formal_and_expected_inputs,
582 provided_args,
583 c_variadic,
584 err_code,
585 fn_id,
586 call_span,
587 call_expr,
588 tuple_arguments,
589 );
590 }
591 }
592
593 fn check_tupled_arguments(
595 &self,
596 call_span: Span,
598 call_expr: &'tcx hir::Expr<'tcx>,
600 mut formal_input_tys: Vec<Ty<'tcx>>,
602 provided_args: &'tcx [hir::Expr<'tcx>],
604 mut expected_input_tys: Option<Vec<Ty<'tcx>>>,
606 tuple_arguments: TupleArgumentsFlag,
608 fn_id: SplatLoweringInfo<'tcx>,
610 callee_generic_args: Option<ty::GenericArgsRef<'tcx>>,
612 ) -> TupledArgCheckOutcome<'tcx> {
613 let (first_tupled_arg_index, is_self_splatted) = tuple_arguments.tupled_arg_index();
614 let Some(first_tupled_arg_index) = first_tupled_arg_index else {
615 return TupledArgCheckOutcome {
617 new_err_code: None,
618 untupled_formal_input_tys: formal_input_tys,
619 untupled_expected_input_tys: expected_input_tys,
620 };
621 };
622 let first_tupled_arg_index_usz = usize::from(first_tupled_arg_index);
623
624 let tupled_args_count = (1 + provided_args.len()).checked_sub(formal_input_tys.len());
633 {
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:633",
"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(633u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("first_tupled_arg_index")
}> =
::tracing::__macro_support::FieldName::new("first_tupled_arg_index");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("is_self_splatted")
}> =
::tracing::__macro_support::FieldName::new("is_self_splatted");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("tupled_args_count")
}> =
::tracing::__macro_support::FieldName::new("tupled_args_count");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("tuple_arguments")
}> =
::tracing::__macro_support::FieldName::new("tuple_arguments");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("provided_args_len")
}> =
::tracing::__macro_support::FieldName::new("provided_args_len");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("formal_input_tys_len")
}> =
::tracing::__macro_support::FieldName::new("formal_input_tys_len");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&first_tupled_arg_index)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&is_self_splatted)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&tupled_args_count)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&tuple_arguments)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&provided_args.len())
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&formal_input_tys.len())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
634 ?first_tupled_arg_index, ?is_self_splatted,
635 ?tupled_args_count, ?tuple_arguments,
636 provided_args_len = ?provided_args.len(), formal_input_tys_len = ?formal_input_tys.len()
637 );
638
639 if first_tupled_arg_index_usz >= formal_input_tys.len() {
642 ::rustc_middle::util::bug::span_bug_fmt(call_span,
format_args!("splatted argument index is out of bounds: {2:?} >= {0}, is_self_splatted = {3:?}, tupled_args_count = {4:?}, {5:?}, provided_args: {1}",
formal_input_tys.len(), provided_args.len(), first_tupled_arg_index,
is_self_splatted, tupled_args_count, tuple_arguments));span_bug!(
643 call_span,
644 "splatted argument index is out of bounds: {first_tupled_arg_index:?} >= {}, \
645 is_self_splatted = {is_self_splatted:?}, \
646 tupled_args_count = {tupled_args_count:?}, {tuple_arguments:?}, \
647 provided_args: {}",
648 formal_input_tys.len(),
649 provided_args.len(),
650 );
651 }
652
653 let formal_input_tupled_ty = formal_input_tys[first_tupled_arg_index_usz];
654 let tuple_type = if tuple_arguments.is_splatted() {
656 let callee_tuple_type = self.resolve_vars_with_obligations(formal_input_tupled_ty);
657 if callee_tuple_type.is_ty_var()
658 && let Some(tupled_args_count) = tupled_args_count
659 {
660 let ocx = ObligationCtxt::new(self);
662 let origin = self.misc(call_span);
663
664 let new_tupled_type = Ty::new_tup_from_iter(
665 self.tcx,
666 iter::repeat_with(|| self.next_ty_var(call_span)).take(tupled_args_count),
667 );
668
669 let ocx_error = ocx.eq(&origin, self.param_env, callee_tuple_type, new_tupled_type);
671 if let Err(ocx_error) = ocx_error {
672 {
self.dcx().struct_span_err(call_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot resolve splatted arguments; splatted type parameters must be a tuple or unit type: {0:?}",
ocx_error))
})).with_code(E0277)
}struct_span_code_err!(
674 self.dcx(),
675 call_span,
676 E0277,
678 "cannot resolve splatted arguments; splatted type parameters \
679 must be a tuple or unit type: {:?}",
680 ocx_error,
681 )
682 .emit();
683 }
684
685 let type_errors = ocx.try_evaluate_obligations();
686 if type_errors.no_errors() {
687 new_tupled_type
688 } else {
689 let guar = {
self.dcx().struct_span_err(call_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot resolve splatted arguments; splatted type parameters must be a tuple or unit type: {0:?}",
type_errors))
})).with_code(E0277)
}struct_span_code_err!(
690 self.dcx(),
691 call_span,
692 E0277,
693 "cannot resolve splatted arguments; splatted type parameters \
694 must be a tuple or unit type: {:?}",
695 type_errors,
696 )
697 .emit();
698 Ty::new_error(self.tcx, guar)
699 }
700 } else {
701 callee_tuple_type
703 }
704 } else {
705 self.structurally_resolve_type(call_span, formal_input_tupled_ty)
706 };
707
708 let mut err_code = None;
711 if let ty::Tuple(detup_formal_arg_tys) = tuple_type.kind() {
712 if Some(detup_formal_arg_tys.len()) != tupled_args_count {
715 err_code = Some(E0057);
716 }
717 if let Some(ref mut expected_input_tys) = expected_input_tys
718 && let Some(ty) = expected_input_tys.get(first_tupled_arg_index_usz)
719 && let ty::Tuple(detup_expected_arg_tys) = ty.kind()
720 {
721 let substitute_tys = if Some(detup_expected_arg_tys.len()) == tupled_args_count {
722 detup_expected_arg_tys.iter()
723 } else {
724 detup_formal_arg_tys.iter()
726 };
727
728 expected_input_tys.splice(
729 first_tupled_arg_index_usz..=first_tupled_arg_index_usz,
730 substitute_tys,
731 );
732 } else {
733 expected_input_tys = None;
734 }
735 formal_input_tys.splice(
736 first_tupled_arg_index_usz..=first_tupled_arg_index_usz,
737 detup_formal_arg_tys.iter(),
738 );
739 if let Some(ref expected_input_tys) = expected_input_tys {
740 {
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!("incorrectly constructed input type tuples, argument counts must match: tuple_arguments: {0:?}, first_tupled_arg_index: {1}",
tuple_arguments, first_tupled_arg_index)));
}
}
}
}assert_eq!(
741 formal_input_tys.len(),
742 expected_input_tys.len(),
743 "incorrectly constructed input type tuples, argument counts must match: \
744 tuple_arguments: {tuple_arguments:?}, \
745 first_tupled_arg_index: {first_tupled_arg_index}",
746 )
747 }
748 }
749
750 let guar =
754 if tuple_arguments == TupleAllCallArgs && !#[allow(non_exhaustive_omitted_patterns)] match tuple_type.kind() {
ty::Tuple(_) => true,
_ => false,
}matches!(tuple_type.kind(), ty::Tuple(_)) {
755 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!(
756 self.dcx(),
757 call_span,
758 E0059,
759 "cannot use call notation; the first type parameter \
760 for the function trait is neither a tuple nor unit"
761 )
762 .emit();
763
764 Some(guar)
765 } else if tuple_arguments.is_splatted() {
766 if !#[allow(non_exhaustive_omitted_patterns)] match tuple_type.kind() {
ty::Tuple(_) => true,
_ => false,
}matches!(tuple_type.kind(), ty::Tuple(_)) {
769 let spans = if let SplatLoweringInfo::FnDef(def_id) = fn_id
770 && let Some(hir_node) = self.tcx.hir_get_if_local(def_id)
771 && let Some(fn_decl) = hir_node.fn_decl()
772 && let Some(arg_ty) = fn_decl.inputs.get(first_tupled_arg_index_usz)
773 {
774 let arg_def_span = arg_ty.span;
775 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[call_span, arg_def_span]))vec![call_span, arg_def_span]
776 } else {
777 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[call_span]))vec![call_span]
778 };
779 let guar = {
self.dcx().struct_span_err(spans,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot use `rustc_splat` attribute; the splatted argument type must be a tuple or unit, not a {0:?} ({1:?})",
tuple_type.kind(),
self.structurally_resolve_type(call_span,
formal_input_tys[first_tupled_arg_index_usz]).kind()))
})).with_code(E0277)
}struct_span_code_err!(
780 self.dcx(),
781 spans,
782 E0277,
784 "cannot use `rustc_splat` attribute; the splatted argument type \
785 must be a tuple or unit, not a {:?} ({:?})",
786 tuple_type.kind(),
787 self.structurally_resolve_type(
788 call_span,
789 formal_input_tys[first_tupled_arg_index_usz]
790 )
791 .kind(),
792 )
793 .emit();
794
795 Some(guar)
796 } else if formal_input_tys.len() != provided_args.len() {
797 let guar = {
self.dcx().struct_span_err(call_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this splatted function takes {0} arguments, but {1} {2} provided",
formal_input_tys.len(), provided_args.len(),
if provided_args.len() == 1 { "was" } else { "were" }))
})).with_code(E0057)
}struct_span_code_err!(
799 self.dcx(),
800 call_span,
801 E0057,
802 "this splatted function takes {} arguments, but {} {} provided",
803 formal_input_tys.len(),
804 provided_args.len(),
805 if provided_args.len() == 1 { "was" } else { "were" },
806 )
807 .emit();
808
809 Some(guar)
810 } else {
811 None
812 }
813 } else {
814 None
815 };
816
817 if let Some(guar) = guar {
818 TupledArgCheckOutcome {
819 new_err_code: err_code,
820 untupled_formal_input_tys: self.err_args(provided_args.len(), guar),
821 untupled_expected_input_tys: None,
822 }
823 } else {
824 if tuple_arguments.is_splatted() {
826 self.write_splatted_call(
828 call_expr.hir_id,
829 call_span,
830 fn_id,
831 callee_generic_args,
832 first_tupled_arg_index,
833 tupled_args_count.unwrap().try_into().unwrap(),
834 );
835 }
836
837 TupledArgCheckOutcome {
838 new_err_code: err_code,
839 untupled_formal_input_tys: formal_input_tys,
840 untupled_expected_input_tys: expected_input_tys,
841 }
842 }
843 }
844
845 fn check_place_expr_if_unsized(&self, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
851 if self.tcx.features().unsized_fn_params() && !expr.is_syntactic_place_expr() {
852 self.require_type_is_sized(
853 ty,
854 expr.span,
855 ObligationCauseCode::UnsizedNonPlaceExpr(expr.span),
856 );
857 }
858 }
859
860 fn report_arg_errors(
861 &self,
862 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
863 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
864 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
865 c_variadic: bool,
866 err_code: ErrCode,
867 fn_id: SplatLoweringInfo<'tcx>,
869 call_span: Span,
870 call_expr: &'tcx hir::Expr<'tcx>,
871 tuple_arguments: TupleArgumentsFlag,
873 ) -> ErrorGuaranteed {
874 let mut fn_call_diag_ctxt = FnCallDiagCtxt::new(
877 self,
878 compatibility_diagonal,
879 formal_and_expected_inputs,
880 provided_args,
881 c_variadic,
882 err_code,
883 fn_id,
884 call_span,
885 call_expr,
886 tuple_arguments,
887 );
888
889 if let Some(err) = fn_call_diag_ctxt.check_wrap_args_in_tuple() {
891 return err;
892 }
893
894 if let Some(fallback_error) = fn_call_diag_ctxt.ensure_has_errors() {
895 return fallback_error;
896 }
897
898 if let Some(err) = fn_call_diag_ctxt.filter_out_invalid_arguments()
913 && fn_call_diag_ctxt.errors.is_empty()
914 {
915 return err;
917 }
918
919 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());
920
921 if let Some(err) = fn_call_diag_ctxt.check_single_incompatible() {
923 return err;
924 }
925
926 fn_call_diag_ctxt.maybe_optimize_extra_arg_suggestion();
935
936 let mut err = fn_call_diag_ctxt.initial_final_diagnostic();
937 fn_call_diag_ctxt.suggest_confusable(&mut err);
938
939 let (mut suggestions, labels, suggestion_text) =
942 fn_call_diag_ctxt.labels_and_suggestion_text(&mut err);
943
944 fn_call_diag_ctxt.label_generic_mismatches(&mut err);
945 fn_call_diag_ctxt.append_arguments_changes(&mut suggestions);
946
947 if labels.len() <= 5 {
949 for (span, label) in labels {
950 err.span_label(span, label);
951 }
952 }
953
954 fn_call_diag_ctxt.label_fn_like(
956 &mut err,
957 fn_id,
958 fn_call_diag_ctxt.callee_ty,
959 call_expr,
960 None,
961 None,
962 &fn_call_diag_ctxt.matched_inputs,
963 &fn_call_diag_ctxt.formal_and_expected_inputs,
964 fn_call_diag_ctxt.call_metadata.is_method,
965 tuple_arguments,
966 );
967
968 if let Some(suggestion_message) =
970 FnCallDiagCtxt::format_suggestion_text(&mut err, suggestions, suggestion_text)
971 && !fn_call_diag_ctxt.call_is_in_macro()
972 {
973 let (suggestion_span, suggestion_code) = fn_call_diag_ctxt.suggestion_code();
974
975 err.span_suggestion_verbose(
976 suggestion_span,
977 suggestion_message,
978 suggestion_code,
979 Applicability::HasPlaceholders,
980 );
981 }
982
983 err.emit()
984 }
985
986 fn suggest_ptr_null_mut(
987 &self,
988 expected_ty: Ty<'tcx>,
989 provided_ty: Ty<'tcx>,
990 arg: &hir::Expr<'tcx>,
991 err: &mut Diag<'_>,
992 ) {
993 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
994 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
995 && let hir::ExprKind::Call(callee, _) = arg.kind
996 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
997 && let Res::Def(_, def_id) = path.res
998 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
999 {
1000 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
1003 }
1004 }
1005
1006 pub(in super::super) fn check_expr_lit(
1008 &self,
1009 lit: &hir::Lit,
1010 lint_id: HirId,
1011 expected: Expectation<'tcx>,
1012 ) -> Ty<'tcx> {
1013 let tcx = self.tcx;
1014
1015 match lit.node {
1016 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
1017 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
1018 tcx,
1019 tcx.lifetimes.re_static,
1020 Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
1021 ),
1022 ast::LitKind::Byte(_) => tcx.types.u8,
1023 ast::LitKind::Char(_) => tcx.types.char,
1024 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, t),
1025 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, t),
1026 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
1027 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1028 ty::Int(_) | ty::Uint(_) => Some(ty),
1029 ty::Char => Some(tcx.types.u8),
1033 ty::RawPtr(..) => Some(tcx.types.usize),
1034 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1035 &ty::Pat(base, _) if base.is_integral() => {
1036 let layout = tcx
1037 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1038 .ok()?;
1039 if !!layout.uninhabited {
::core::panicking::panic("assertion failed: !layout.uninhabited")
};assert!(!layout.uninhabited);
1040
1041 match layout.backend_repr {
1042 rustc_abi::BackendRepr::Scalar(scalar) => {
1043 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1044 }
1045 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1046 }
1047 }
1048 _ => None,
1049 });
1050 opt_ty.unwrap_or_else(|| self.next_int_var())
1051 }
1052 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => Ty::new_float(tcx, t),
1053 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1054 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1055 ty::Float(_) => Some(ty),
1056 _ => None,
1057 });
1058 opt_ty.unwrap_or_else(|| self.next_float_var(lit.span, Some(lint_id)))
1059 }
1060 ast::LitKind::Bool(_) => tcx.types.bool,
1061 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1062 tcx,
1063 tcx.lifetimes.re_static,
1064 tcx.type_of(tcx.require_lang_item(LangItem::CStr, lit.span)).skip_binder(),
1065 ),
1066 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1067 }
1068 }
1069
1070 pub(crate) fn check_struct_path(
1071 &self,
1072 qpath: &QPath<'tcx>,
1073 hir_id: HirId,
1074 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1075 let path_span = qpath.span();
1076 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1077 let variant = match def {
1078 Res::Err => {
1079 let guar =
1080 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1081 self.set_tainted_by_errors(guar);
1082 return Err(guar);
1083 }
1084 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1085 Some(adt) => {
1086 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1087 }
1088 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type: {0:?}",
ty.normalized))bug!("unexpected type: {:?}", ty.normalized),
1089 },
1090 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1091 | Res::SelfTyParam { .. }
1092 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1093 Some(adt) if !adt.is_enum() => {
1094 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1095 }
1096 _ => None,
1097 },
1098 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected definition: {0:?}",
def))bug!("unexpected definition: {:?}", def),
1099 };
1100
1101 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1102 {
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:1102",
"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(1102u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("check_struct_path: did={0:?} args={1:?}",
did, args) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("check_struct_path: did={:?} args={:?}", did, args);
1103
1104 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1106
1107 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1109
1110 Ok((variant, ty.normalized))
1111 } else {
1112 Err(match *ty.normalized.kind() {
1113 ty::Error(guar) => {
1114 guar
1119 }
1120 _ => {
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!(
1121 self.dcx(),
1122 path_span,
1123 E0071,
1124 "expected struct, variant or union type, found {}",
1125 ty.normalized.sort_string(self.tcx)
1126 )
1127 .with_span_label(path_span, "not a struct")
1128 .emit(),
1129 })
1130 }
1131 }
1132
1133 fn check_decl_initializer(
1134 &self,
1135 hir_id: HirId,
1136 pat: &'tcx hir::Pat<'tcx>,
1137 init: &'tcx hir::Expr<'tcx>,
1138 ) -> Ty<'tcx> {
1139 let ref_bindings = pat.contains_explicit_ref_binding();
1144
1145 let local_ty = self.local_ty(init.span, hir_id);
1146 if let Some(m) = ref_bindings {
1147 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1156 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1157 self.emit_type_mismatch_suggestions(
1158 &mut diag,
1159 init.peel_drop_temps(),
1160 init_ty,
1161 local_ty,
1162 None,
1163 None,
1164 );
1165 diag.emit();
1166 }
1167 init_ty
1168 } else {
1169 self.check_expr_coercible_to_type(init, local_ty, None)
1170 }
1171 }
1172
1173 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1174 let decl_ty = self.local_ty(decl.span, decl.hir_id);
1176
1177 if let Some(init) = decl.init {
1179 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1180 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1181 }
1182
1183 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1185 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
1187 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1188 } _ => (None, None), };
1191
1192 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1194 let pat_ty = self.node_ty(decl.pat.hir_id);
1195 if decl.ty.is_none()
1196 && decl.init.is_none()
1197 && !#[allow(non_exhaustive_omitted_patterns)] match decl.pat.kind {
hir::PatKind::Binding(.., None) | hir::PatKind::Wild => true,
_ => false,
}matches!(decl.pat.kind, hir::PatKind::Binding(.., None) | hir::PatKind::Wild)
1198 {
1199 self.register_wf_obligation(
1200 decl_ty.into(),
1201 decl.pat.span,
1202 ObligationCauseCode::WellFormed(None),
1203 );
1204 }
1205 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1206
1207 if let Some(blk) = decl.origin.try_get_else() {
1208 let previous_diverges = self.diverges.get();
1209 let else_ty = self.check_expr_block(blk, NoExpectation);
1210 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1211 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1212 {
1213 err.emit();
1214 }
1215 self.diverges.set(previous_diverges);
1216 }
1217 decl_ty
1218 }
1219
1220 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1222 GatherLocalsVisitor::gather_from_local(self, local);
1223
1224 let ty = self.check_decl(local.into());
1225 self.write_ty(local.hir_id, ty);
1226 if local.pat.is_never_pattern() {
1227 self.diverges.set(Diverges::Always {
1228 span: local.pat.span,
1229 custom_note: Some("any code following a never pattern is unreachable"),
1230 });
1231 }
1232 }
1233
1234 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1235 match stmt.kind {
1237 hir::StmtKind::Item(..) => return,
1238 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1239 }
1240
1241 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1242
1243 let old_diverges = self.diverges.replace(Diverges::Maybe);
1245
1246 match stmt.kind {
1247 hir::StmtKind::Let(l) => {
1248 self.check_decl_local(l);
1249 }
1250 hir::StmtKind::Item(_) => {}
1252 hir::StmtKind::Expr(expr) => {
1253 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1255 if self.is_next_stmt_expr_continuation(stmt.hir_id)
1256 && let hir::ExprKind::Match(..) | hir::ExprKind::If(..) = expr.kind
1257 {
1258 err.subdiagnostic(ExprParenthesesNeeded::surrounding(expr.span));
1263 } else if expr.can_have_side_effects() {
1264 self.suggest_semicolon_at_end(expr.span, err);
1265 }
1266 });
1267 }
1268 hir::StmtKind::Semi(expr) => {
1269 let ty = self.check_expr(expr);
1270 self.check_place_expr_if_unsized(ty, expr);
1271 }
1272 }
1273
1274 self.diverges.set(self.diverges.get() | old_diverges);
1276 }
1277
1278 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1279 let unit = self.tcx.types.unit;
1280 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1281
1282 if !ty.is_never() {
1285 self.demand_suptype(blk.span, unit, ty);
1286 }
1287 }
1288
1289 pub(in super::super) fn check_expr_block(
1290 &self,
1291 blk: &'tcx hir::Block<'tcx>,
1292 expected: Expectation<'tcx>,
1293 ) -> Ty<'tcx> {
1294 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1311 let coerce = CoerceMany::new(coerce_to_ty);
1312
1313 let prev_diverges = self.diverges.get();
1314 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1315
1316 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1317 for s in blk.stmts {
1318 self.check_stmt(s);
1319 }
1320
1321 let tail_expr_ty =
1324 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1325
1326 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1327 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1328 let coerce = ctxt.coerce.as_mut().unwrap();
1329 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1330 let span = self.get_expr_coercion_span(tail_expr);
1331 let cause = self.cause(
1332 span,
1333 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1334 );
1335 let ty_for_diagnostic = coerce.merged_ty();
1336 coerce.coerce_inner(
1340 self,
1341 &cause,
1342 Some(tail_expr),
1343 tail_expr_ty,
1344 |diag| {
1345 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1346 },
1347 false,
1348 );
1349 } else {
1350 if !self.diverges.get().is_always()
1361 || #[allow(non_exhaustive_omitted_patterns)] match self.diverging_block_behavior
{
DivergingBlockBehavior::Unit => true,
_ => false,
}matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1362 {
1363 let mut sp = blk.span;
1369 let mut fn_span = None;
1370 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1371 let ret_sp = decl.output.span();
1372 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1373 if block_sp == blk.span {
1377 sp = ret_sp;
1378 fn_span = self.tcx.def_ident_span(fn_def_id);
1379 }
1380 }
1381 }
1382 coerce.coerce_forced_unit(
1383 self,
1384 &self.misc(sp),
1385 |err| {
1386 if let Some(expected_ty) = expected.only_has_type(self) {
1387 if blk.stmts.is_empty() && blk.expr.is_none() {
1388 self.suggest_boxing_when_appropriate(
1389 err,
1390 blk.span,
1391 blk.hir_id,
1392 expected_ty,
1393 self.tcx.types.unit,
1394 );
1395 }
1396 if !self.err_ctxt().consider_removing_semicolon(
1397 blk,
1398 expected_ty,
1399 err,
1400 ) {
1401 self.err_ctxt().consider_returning_binding(
1402 blk,
1403 expected_ty,
1404 err,
1405 );
1406 }
1407 if expected_ty == self.tcx.types.bool {
1408 if let hir::Block {
1413 stmts:
1414 [
1415 hir::Stmt {
1416 kind:
1417 hir::StmtKind::Let(hir::LetStmt {
1418 source: hir::LocalSource::AssignDesugar,
1419 ..
1420 }),
1421 ..
1422 },
1423 hir::Stmt {
1424 kind:
1425 hir::StmtKind::Expr(hir::Expr {
1426 kind: hir::ExprKind::Assign(lhs, ..),
1427 ..
1428 }),
1429 ..
1430 },
1431 ],
1432 ..
1433 } = blk
1434 {
1435 self.comes_from_while_condition(blk.hir_id, |_| {
1436 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
1440
1441 if !lhs.is_syntactic_place_expr()
1442 || res.references_error()
1443 {
1444 err.downgrade_to_delayed_bug();
1445 }
1446 })
1447 }
1448 }
1449 }
1450 if let Some(fn_span) = fn_span {
1451 err.span_label(
1452 fn_span,
1453 "implicitly returns `()` as its body has no tail or `return` \
1454 expression",
1455 );
1456 }
1457 },
1458 false,
1459 );
1460 }
1461 }
1462 });
1463
1464 if ctxt.may_break {
1465 self.diverges.set(prev_diverges);
1468 }
1469
1470 let ty = ctxt.coerce.unwrap().complete(self);
1471
1472 self.write_ty(blk.hir_id, ty);
1473
1474 ty
1475 }
1476
1477 fn parent_item_span(&self, id: HirId) -> Option<Span> {
1478 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
1479 match node {
1480 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
1481 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1482 let body = self.tcx.hir_body(body_id);
1483 if let ExprKind::Block(block, _) = &body.value.kind {
1484 return Some(block.span);
1485 }
1486 }
1487 _ => {}
1488 }
1489 None
1490 }
1491
1492 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1500 let check_in_progress = |elem: &hir::Expr<'_>| {
1501 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
1502 |_| match elem.kind {
1503 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
1505 _ => elem.span,
1506 },
1507 )
1508 };
1509
1510 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
1511 && let Some(rslt) = check_in_progress(el)
1512 {
1513 return rslt;
1514 }
1515
1516 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1517 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1518 if let Some(span) = iter.next() {
1519 if iter.next().is_none() {
1520 return span;
1521 }
1522 }
1523 }
1524
1525 expr.span
1526 }
1527
1528 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
1529 if let Err(guar) = ty.error_reported() {
1530 struct OverwritePatternsWithError {
1531 pat_hir_ids: Vec<hir::HirId>,
1532 }
1533 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
1534 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
1535 self.pat_hir_ids.push(p.hir_id);
1536 hir::intravisit::walk_pat(self, p);
1537 }
1538 }
1539 let err = Ty::new_error(self.tcx, guar);
1541 self.write_ty(hir_id, err);
1542 self.write_ty(pat.hir_id, err);
1543 let mut visitor = OverwritePatternsWithError { pat_hir_ids: ::alloc::vec::Vec::new()vec![] };
1544 hir::intravisit::walk_pat(&mut visitor, pat);
1545 for hir_id in visitor.pat_hir_ids {
1548 self.write_ty(hir_id, err);
1549 }
1550 self.locals.borrow_mut().insert(hir_id, err);
1551 self.locals.borrow_mut().insert(pat.hir_id, err);
1552 }
1553 }
1554
1555 fn finish_resolving_struct_path(
1558 &self,
1559 qpath: &QPath<'tcx>,
1560 path_span: Span,
1561 hir_id: HirId,
1562 ) -> (Res, LoweredTy<'tcx>) {
1563 let ResolvedStructPath { res: result, ty } =
1564 self.lowerer().lower_path_for_struct_expr(*qpath, path_span, hir_id);
1565 match *qpath {
1566 QPath::Resolved(_, path) => (path.res, LoweredTy::from_raw(self, path_span, ty)),
1567 QPath::TypeRelative(_, _) => {
1568 let ty = LoweredTy::from_raw(self, path_span, ty);
1569 let resolution =
1570 result.map(|res: Res| (self.tcx().def_kind(res.def_id()), res.def_id()));
1571
1572 self.write_resolution(hir_id, resolution);
1574
1575 (result.unwrap_or(Res::Err), ty)
1576 }
1577 }
1578 }
1579
1580 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
1587 &self,
1588 errors: &mut ThinVec<traits::FulfillmentError<'tcx>>,
1589 ) {
1590 let mut remap_cause = FxIndexSet::default();
1596 let mut not_adjusted = ::alloc::vec::Vec::new()vec![];
1597
1598 for error in errors {
1599 let before_span = error.obligation.cause.span;
1600 if self.adjust_fulfillment_error_for_expr_obligation(error)
1601 || before_span != error.obligation.cause.span
1602 {
1603 remap_cause.insert((
1604 before_span,
1605 error.obligation.predicate,
1606 error.obligation.cause.clone(),
1607 ));
1608 } else {
1609 not_adjusted.push(error);
1612 }
1613 }
1614
1615 for error in not_adjusted {
1623 for (span, predicate, cause) in &remap_cause {
1624 if *predicate == error.obligation.predicate
1625 && span.contains(error.obligation.cause.span)
1626 {
1627 error.obligation.cause = cause.clone();
1628 continue;
1629 }
1630 }
1631 }
1632 }
1633
1634 fn label_fn_like(
1635 &self,
1636 err: &mut Diag<'_>,
1637 callable_id: SplatLoweringInfo<'tcx>,
1639 callee_ty: Option<Ty<'tcx>>,
1640 call_expr: &'tcx hir::Expr<'tcx>,
1641 expected_ty: Option<Ty<'tcx>>,
1642 expected_idx: Option<usize>,
1644 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1645 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1646 is_method: bool,
1647 tuple_arguments: TupleArgumentsFlag,
1648 ) {
1649 let SplatLoweringInfo::FnDef(mut def_id) = callable_id else {
1650 return;
1652 };
1653
1654 if tuple_arguments == TupleAllCallArgs
1660 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1661 && let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
1666 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1667 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
1669 && let Some(callee_ty) = callee_ty
1670 {
1671 let callee_ty = callee_ty.peel_refs();
1672 match *callee_ty.kind() {
1673 ty::Param(param) => {
1674 let param = self.tcx.generics_of(self.body_def_id).type_param(param, self.tcx);
1675 if param.kind.is_synthetic() {
1676 def_id = param.def_id;
1678 } else {
1679 let instantiated = self
1682 .tcx
1683 .explicit_clauses_of(self.body_def_id)
1684 .instantiate_identity(self.tcx);
1685 for (clause, span) in instantiated {
1689 if let ty::ClauseKind::Trait(pred) =
1690 clause.skip_norm_wip().kind().skip_binder()
1691 && pred.self_ty().peel_refs() == callee_ty
1692 && self.tcx.is_fn_trait(pred.def_id())
1693 {
1694 err.span_note(span, "callable defined here");
1695 return;
1696 }
1697 }
1698 }
1699 }
1700 ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: new_def_id }, .. })
1701 | ty::Closure(new_def_id, _)
1702 | ty::FnDef(new_def_id, _) => {
1703 def_id = new_def_id;
1704 }
1705 _ => {
1706 let new_def_id = self.probe(|_| {
1708 let trait_ref = ty::TraitRef::new(
1709 self.tcx,
1710 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
1711 [callee_ty, self.next_ty_var(DUMMY_SP)],
1712 );
1713 let obligation = traits::Obligation::new(
1714 self.tcx,
1715 traits::ObligationCause::dummy(),
1716 self.param_env,
1717 trait_ref,
1718 );
1719 match SelectionContext::new(self).select(&obligation) {
1720 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1721 Some(impl_source.impl_def_id)
1722 }
1723 _ => None,
1724 }
1725 });
1726 let Some(new_def_id) = new_def_id else { return };
1727 def_id = new_def_id;
1728 }
1729 }
1730 }
1731
1732 if let Some(def_span) = self.tcx.def_ident_span(def_id)
1733 && !def_span.is_dummy()
1734 {
1735 let mut spans: MultiSpan = def_span.into();
1736 if let Some((params_with_generics, hir_generics)) =
1737 self.get_hir_param_info(def_id, is_method)
1738 {
1739 struct MismatchedParam<'a> {
1740 idx: ExpectedIdx,
1741 generic: GenericIdx,
1742 param: &'a FnParam<'a>,
1743 deps: SmallVec<[ExpectedIdx; 4]>,
1744 }
1745
1746 if !tuple_arguments.is_splatted() {
1748 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());
1749 }
1750 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
1752 let mut use_splat_fallback = false;
1753 if let Some(expected_idx) = expected_idx {
1754 let expected_idx = ExpectedIdx::from_usize(expected_idx);
1755 match params_with_generics.get(expected_idx) {
1756 Some(&(Some(expected_generic), ref expected_param)) => mismatched_params
1757 .push(MismatchedParam {
1758 idx: expected_idx,
1759 generic: expected_generic,
1760 param: expected_param,
1761 deps: SmallVec::new(),
1762 }),
1763 Some((None, expected_param)) => {
1764 spans.push_span_label(expected_param.span(), "");
1766 }
1767 None => {
1768 if tuple_arguments.is_splatted() {
1769 use_splat_fallback = true;
1771 } else {
1772 ::rustc_middle::util::bug::span_bug_fmt(self.tcx.def_span(def_id),
format_args!("arg index {0} out of bounds for method with {1} inputs",
expected_idx.as_usize(), params_with_generics.len()));span_bug!(
1773 self.tcx.def_span(def_id),
1774 "arg index {} out of bounds for method with {} inputs",
1775 expected_idx.as_usize(),
1776 params_with_generics.len(),
1777 );
1778 }
1779 }
1780 };
1781 }
1782
1783 if expected_idx.is_none() || use_splat_fallback {
1784 mismatched_params.extend(
1785 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
1786 |((idx, &(generic, ref param)), matched_idx)| {
1787 if matched_idx.is_some() {
1788 None
1789 } else if let Some(generic) = generic {
1790 Some(MismatchedParam {
1791 idx,
1792 generic,
1793 param,
1794 deps: SmallVec::new(),
1795 })
1796 } else {
1797 spans.push_span_label(param.span(), "");
1799 None
1800 }
1801 },
1802 ),
1803 );
1804 }
1805
1806 if !mismatched_params.is_empty() {
1807 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
1810 |_| SmallVec::<[u32; 4]>::new(),
1811 params_with_generics.len(),
1812 );
1813 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
1814 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
1815 hir_generics.params.len(),
1816 );
1817 for (idx, param) in mismatched_params.iter_mut().enumerate() {
1818 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
1819 params_with_generics.iter_enumerated().zip(matched_inputs)
1820 {
1821 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
1822 generic_uses[param.generic].extend([param.idx, other_idx]);
1823 dependants[other_idx].push(idx as u32);
1824 param.deps.push(other_idx);
1825 }
1826 }
1827 }
1828
1829 for param in &mismatched_params {
1832 if let Some(deps_list) = listify(¶m.deps, |&dep| {
1833 params_with_generics[dep].1.display(dep.as_usize()).to_string()
1834 }) {
1835 spans.push_span_label(
1836 param.param.span(),
1837 ::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!(
1838 "this parameter needs to match the {} type of {deps_list}",
1839 self.resolve_vars_if_possible(
1840 formal_and_expected_inputs[param.deps[0]].1
1841 )
1842 .sort_string(self.tcx),
1843 ),
1844 );
1845 } else {
1846 spans.push_span_label(param.param.span(), "");
1848 }
1849 }
1850 for ((&(_, param), deps), &(_, expected_ty)) in
1852 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
1853 {
1854 if let Some(deps_list) = listify(deps, |&dep| {
1855 let param = &mismatched_params[dep as usize];
1856 param.param.display(param.idx.as_usize()).to_string()
1857 }) {
1858 spans.push_span_label(
1859 param.span(),
1860 ::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!(
1861 "{deps_list} need{} to match the {} type of this parameter",
1862 pluralize!((deps.len() != 1) as u32),
1863 self.resolve_vars_if_possible(expected_ty)
1864 .sort_string(self.tcx),
1865 ),
1866 );
1867 }
1868 }
1869 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
1871 uses.sort();
1872 uses.dedup();
1873 if let Some(param_list) = listify(uses, |&idx| {
1874 params_with_generics[idx].1.display(idx.as_usize()).to_string()
1875 }) {
1876 spans.push_span_label(
1877 param.span,
1878 ::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!(
1879 "{param_list} {} reference this parameter `{}`",
1880 if uses.len() == 2 { "both" } else { "all" },
1881 param.name.ident().name,
1882 ),
1883 );
1884 }
1885 }
1886 }
1887 }
1888 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)));
1889 if let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(def_id)
1890 && let ty::Param(_) =
1891 self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output().kind()
1892 && let parent = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id
1893 && let Some((output, body_id)) = match self.tcx.hir_node_by_def_id(parent) {
1894 hir::Node::Item(hir::Item {
1895 kind: hir::ItemKind::Fn { sig, body, .. },
1896 ..
1897 })
1898 | hir::Node::TraitItem(hir::TraitItem {
1899 kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)),
1900 ..
1901 })
1902 | hir::Node::ImplItem(hir::ImplItem {
1903 kind: hir::ImplItemKind::Fn(sig, body),
1904 ..
1905 }) => Some((sig.decl.output, body)),
1906 _ => None,
1907 }
1908 && let expr = self.tcx.hir_body(*body_id).value
1909 && (expr.peel_blocks().span == call_expr.span
1910 || #[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!(
1911 self.tcx.parent_hir_node(call_expr.hir_id),
1912 hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
1913 ))
1914 {
1915 err.span_label(
1916 output.span(),
1917 match output {
1918 FnRetTy::DefaultReturn(_) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this implicit `()` return type influences the call expression\'s return type"))
})format!(
1919 "this implicit `()` return type influences the call expression's return type"
1920 ),
1921 FnRetTy::Return(_) => {
1922 "this return type influences the call expression's return type"
1923 .to_string()
1924 }
1925 },
1926 );
1927 }
1928 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
1929 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
1930 {
1931 let param = expected_idx
1932 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
1933 let (kind, span) = if let Some(param) = param {
1934 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: ::alloc::vec::Vec::new()vec![] };
1937 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
1938 match self.tcx.hir_node_by_def_id(parent_def_id) {
1939 hir::Node::Item(item) => call_finder.visit_item(item),
1940 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
1941 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
1942 _ => {}
1943 }
1944 let typeck = self.typeck_results.borrow();
1945 for (rcvr, args) in call_finder.calls {
1946 if rcvr.hir_id.owner == typeck.hir_owner
1947 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
1948 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
1949 && def_id == *call_def_id
1950 && let Some(idx) = expected_idx
1951 && let Some(arg) = args.get(idx)
1952 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
1953 && let Some(expected_ty) = expected_ty
1954 && self.can_eq(self.param_env, arg_ty, expected_ty)
1955 {
1956 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();
1957 sp.push_span_label(
1958 arg.span,
1959 ::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}`"),
1960 );
1961 sp.push_span_label(rcvr.span, "in this closure call");
1962 err.span_note(
1963 sp,
1964 ::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!(
1965 "expected because the closure was earlier called with an \
1966 argument of type `{arg_ty}`",
1967 ),
1968 );
1969 break;
1970 }
1971 }
1972
1973 ("closure parameter", param.span)
1974 } else {
1975 ("closure", self.tcx.def_span(def_id))
1976 };
1977 err.span_note(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} defined here", kind))
})format!("{kind} defined here"));
1978 } else {
1979 err.span_note(
1980 self.tcx.def_span(def_id),
1981 ::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)),
1982 );
1983 }
1984 }
1985
1986 fn label_generic_mismatches(
1987 &self,
1988 err: &mut Diag<'_>,
1989 callable_id: SplatLoweringInfo<'tcx>,
1991 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1992 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
1993 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1994 is_method: bool,
1995 is_splat: bool,
1996 ) {
1997 let SplatLoweringInfo::FnDef(def_id) = callable_id else {
1998 return;
2000 };
2001
2002 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
2003 if !is_splat {
2005 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());
2006 }
2007 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
2008 if matched_inputs.get(idx).flatten_ref().is_none() {
2009 continue;
2010 }
2011
2012 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
2013 else {
2014 continue;
2015 };
2016
2017 let Some(generic_param) = generic_param else {
2018 continue;
2019 };
2020
2021 let idxs_matched = params_with_generics
2022 .iter_enumerated()
2023 .filter(|&(other_idx, (other_generic_param, _))| {
2024 if other_idx == idx {
2025 return false;
2026 }
2027 let Some(other_generic_param) = other_generic_param else {
2028 return false;
2029 };
2030 if matched_inputs.get(other_idx).flatten_ref().is_some() {
2031 return false;
2032 }
2033 other_generic_param == generic_param
2034 })
2035 .count();
2036
2037 if idxs_matched == 0 {
2038 continue;
2039 }
2040
2041 let expected_display_type = self
2042 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
2043 .sort_string(self.tcx);
2044 let label = if idxs_matched == params_with_generics.len() - 1 {
2045 ::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!(
2046 "expected all arguments to be this {} type because they need to match the type of this parameter",
2047 expected_display_type
2048 )
2049 } else {
2050 ::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!(
2051 "expected some other arguments to be {} {} type to match the type of this parameter",
2052 a_or_an(&expected_display_type),
2053 expected_display_type,
2054 )
2055 };
2056
2057 err.span_label(*matched_arg_span, label);
2058 }
2059 }
2060 }
2061
2062 fn get_hir_param_info(
2067 &self,
2068 def_id: DefId,
2069 is_method: bool,
2070 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2071 {
2072 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2073 hir::Node::TraitItem(&hir::TraitItem {
2074 generics,
2075 kind: hir::TraitItemKind::Fn(sig, trait_fn),
2076 ..
2077 }) => match trait_fn {
2078 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2079 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2080 },
2081 hir::Node::ImplItem(&hir::ImplItem {
2082 generics,
2083 kind: hir::ImplItemKind::Fn(sig, body),
2084 ..
2085 })
2086 | hir::Node::Item(&hir::Item {
2087 kind: hir::ItemKind::Fn { sig, generics, body, .. },
2088 ..
2089 }) => (sig, generics, Some(body), None),
2090 hir::Node::ForeignItem(&hir::ForeignItem {
2091 kind: hir::ForeignItemKind::Fn(sig, params, generics),
2092 ..
2093 }) => (sig, generics, None, Some(params)),
2094 _ => return None,
2095 };
2096
2097 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2100 if let hir::TyKind::Path(QPath::Resolved(
2101 _,
2102 &hir::Path { res: Res::Def(_, res_def_id), .. },
2103 )) = param.kind
2104 {
2105 generics
2106 .params
2107 .iter()
2108 .position(|param| param.def_id.to_def_id() == res_def_id)
2109 .map(GenericIdx::from_usize)
2110 } else {
2111 None
2112 }
2113 });
2114 match (body_id, params) {
2115 (Some(_), Some(_)) | (None, None) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2116 (Some(body), None) => {
2117 let params = self.tcx.hir_body(body).params;
2118 let params = params
2119 .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
2120 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());
2121 Some((fn_inputs.zip(params.iter().map(FnParam::Param)).collect(), generics))
2122 }
2123 (None, Some(params)) => {
2124 let params = params
2125 .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
2126 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());
2127 Some((
2128 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2129 generics,
2130 ))
2131 }
2132 }
2133 }
2134}
2135
2136struct FindClosureArg<'tcx> {
2137 tcx: TyCtxt<'tcx>,
2138 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2139}
2140
2141impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2142 type NestedFilter = rustc_middle::hir::nested_filter::All;
2143
2144 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2145 self.tcx
2146 }
2147
2148 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2149 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2150 self.calls.push((rcvr, args));
2151 }
2152 hir::intravisit::walk_expr(self, ex);
2153 }
2154}
2155
2156#[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)]
2157enum FnParam<'hir> {
2158 Param(&'hir hir::Param<'hir>),
2159 Ident(Option<Ident>),
2160}
2161
2162impl FnParam<'_> {
2163 fn span(&self) -> Span {
2164 match self {
2165 Self::Param(param) => param.span,
2166 Self::Ident(ident) => {
2167 if let Some(ident) = ident {
2168 ident.span
2169 } else {
2170 DUMMY_SP
2171 }
2172 }
2173 }
2174 }
2175
2176 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2177 struct D<'a>(FnParam<'a>, usize);
2178 impl fmt::Display for D<'_> {
2179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2180 let unique_name = match self.0 {
2183 FnParam::Param(param)
2184 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2185 {
2186 Some(ident.name)
2187 }
2188 FnParam::Ident(ident)
2189 if let Some(ident) = ident
2190 && ident.name != kw::Underscore =>
2191 {
2192 Some(ident.name)
2193 }
2194 _ => None,
2195 };
2196 if let Some(unique_name) = unique_name {
2197 f.write_fmt(format_args!("`{0}`", unique_name))write!(f, "`{unique_name}`")
2198 } else {
2199 f.write_fmt(format_args!("parameter #{0}", self.1 + 1))write!(f, "parameter #{}", self.1 + 1)
2200 }
2201 }
2202 }
2203 D(*self, idx)
2204 }
2205}
2206
2207struct FnCallDiagCtxt<'a, 'tcx> {
2208 arg_matching_ctxt: ArgMatchingCtxt<'a, 'tcx>,
2209 errors: Vec<Error<'tcx>>,
2210 matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2211}
2212
2213impl<'a, 'tcx> Deref for FnCallDiagCtxt<'a, 'tcx> {
2214 type Target = ArgMatchingCtxt<'a, 'tcx>;
2215
2216 fn deref(&self) -> &Self::Target {
2217 &self.arg_matching_ctxt
2218 }
2219}
2220
2221enum ArgumentsFormatting {
2223 SingleLine,
2224 Multiline { fallback_indent: String, brace_indent: String },
2225}
2226
2227impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> {
2228 fn new(
2229 arg: &'a FnCtxt<'a, 'tcx>,
2230 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
2231 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2232 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
2233 c_variadic: bool,
2234 err_code: ErrCode,
2235 fn_id: SplatLoweringInfo<'tcx>,
2237 call_span: Span,
2238 call_expr: &'tcx Expr<'tcx>,
2239 tuple_arguments: TupleArgumentsFlag,
2240 ) -> Self {
2241 let arg_matching_ctxt = ArgMatchingCtxt::new(
2242 arg,
2243 compatibility_diagonal,
2244 formal_and_expected_inputs,
2245 provided_args,
2246 c_variadic,
2247 err_code,
2248 fn_id,
2249 call_span,
2250 call_expr,
2251 tuple_arguments,
2252 );
2253
2254 let (errors, matched_inputs) = ArgMatrix::new(
2261 arg_matching_ctxt.provided_args.len(),
2262 arg_matching_ctxt.formal_and_expected_inputs.len(),
2263 |provided, expected| arg_matching_ctxt.check_compatible(provided, expected),
2264 )
2265 .find_errors();
2266
2267 FnCallDiagCtxt { arg_matching_ctxt, errors, matched_inputs }
2268 }
2269
2270 fn check_wrap_args_in_tuple(&self) -> Option<ErrorGuaranteed> {
2271 if let Some((mismatch_idx, terr)) = self.first_incompatible_error() {
2272 if let Some(ty::Tuple(tys)) =
2276 self.formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
2277 && !tys.is_empty()
2279 && self.provided_arg_tys.len() == self.formal_and_expected_inputs.len() - 1 + tys.len()
2280 {
2281 let provided_args_to_tuple = &self.provided_arg_tys[mismatch_idx..];
2283 let (provided_args_to_tuple, provided_args_after_tuple) =
2284 provided_args_to_tuple.split_at(tys.len());
2285 let provided_as_tuple = Ty::new_tup_from_iter(
2286 self.tcx,
2287 provided_args_to_tuple.iter().map(|&(ty, _)| ty),
2288 );
2289
2290 let mut satisfied = true;
2291 for ((_, expected_ty), provided_ty) in std::iter::zip(
2293 self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
2294 [provided_as_tuple]
2295 .into_iter()
2296 .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
2297 ) {
2298 if !self.may_coerce(provided_ty, *expected_ty) {
2299 satisfied = false;
2300 break;
2301 }
2302 }
2303
2304 if satisfied
2308 && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
2309 {
2310 let mut err;
2311 if tys.len() == 1 {
2312 err = self.err_ctxt().report_and_explain_type_error(
2315 self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2316 lo,
2317 self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
2318 self.provided_arg_tys[mismatch_idx].0,
2319 ),
2320 self.param_env,
2321 terr,
2322 );
2323 let call_name = self.call_metadata.call_name;
2324 err.span_label(
2325 self.call_metadata.full_call_span,
2326 ::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"),
2327 );
2328 } else {
2329 let call_name = self.call_metadata.call_name;
2330 err = self.dcx().struct_span_err(
2331 self.arg_matching_ctxt.args_ctxt.call_metadata.full_call_span,
2332 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{4} takes {0}{1} but {2} {3} supplied",
if self.arg_matching_ctxt.args_ctxt.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!(
2333 "{call_name} takes {}{} but {} {} supplied",
2334 if self.arg_matching_ctxt.args_ctxt.c_variadic {
2335 "at least "
2336 } else {
2337 ""
2338 },
2339 potentially_plural_count(
2340 self.formal_and_expected_inputs.len(),
2341 "argument"
2342 ),
2343 potentially_plural_count(self.provided_args.len(), "argument"),
2344 pluralize!("was", self.provided_args.len())
2345 ),
2346 );
2347 err.code(self.err_code.to_owned());
2348 err.multipart_suggestion(
2349 "wrap these arguments in parentheses to construct a tuple",
2350 ::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![
2351 (lo.shrink_to_lo(), "(".to_string()),
2352 (hi.shrink_to_hi(), ")".to_string()),
2353 ],
2354 Applicability::MachineApplicable,
2355 );
2356 };
2357 self.arg_matching_ctxt.args_ctxt.call_ctxt.fn_ctxt.label_fn_like(
2358 &mut err,
2359 self.fn_id,
2360 self.callee_ty,
2361 self.call_expr,
2362 None,
2363 Some(mismatch_idx.as_usize()),
2364 &self.matched_inputs,
2365 &self.formal_and_expected_inputs,
2366 self.call_metadata.is_method,
2367 self.tuple_arguments,
2368 );
2369 self.suggest_confusable(&mut err);
2370 Some(err.emit())
2371 } else {
2372 None
2373 }
2374 } else {
2375 None
2376 }
2377 } else {
2378 None
2379 }
2380 }
2381
2382 fn ensure_has_errors(&self) -> Option<ErrorGuaranteed> {
2383 if self.errors.is_empty() {
2384 if truecfg!(debug_assertions) {
2385 ::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");
2386 } else {
2387 let mut err = self.dcx().create_err(diagnostics::ArgMismatchIndeterminate {
2388 span: self.call_metadata.error_span,
2389 });
2390 self.arg_matching_ctxt.suggest_confusable(&mut err);
2391 return Some(err.emit());
2392 }
2393 }
2394
2395 None
2396 }
2397
2398 fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) {
2399 if let ty::Adt(adt, _) = ty.kind()
2400 && self.tcx().is_lang_item(adt.did(), LangItem::RangeFull)
2401 && is_range_literal(expr)
2402 && let hir::ExprKind::Struct(&path, [], _) = expr.kind
2403 && self.tcx().qpath_is_lang_item(path, LangItem::RangeFull)
2404 {
2405 let explanation = if self.tcx.features().default_field_values() {
2408 "this is only supported on non-tuple struct literals"
2409 } else if self.tcx.sess.is_nightly_build() {
2410 "this is only supported on non-tuple struct literals when \
2411 `#![feature(default_field_values)]` is enabled"
2412 } else {
2413 "this is not supported"
2414 };
2415 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!(
2416 "you might have meant to use `..` to skip providing a value for \
2417 expected fields, but {explanation}; it is instead interpreted as a \
2418 `std::ops::RangeFull` literal",
2419 );
2420 err.span_help(expr.span, msg);
2421 }
2422 }
2423
2424 fn filter_out_invalid_arguments(&mut self) -> Option<ErrorGuaranteed> {
2425 let mut reported = None;
2426
2427 self.errors.retain(|error| {
2428 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
2429 error
2430 else {
2431 return true;
2432 };
2433 let (provided_ty, provided_span) =
2434 self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2435 let trace = self.arg_matching_ctxt.mk_trace(
2436 provided_span,
2437 self.arg_matching_ctxt.formal_and_expected_inputs[*expected_idx],
2438 provided_ty,
2439 );
2440 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) {
2441 let mut err = self.arg_matching_ctxt.err_ctxt().report_and_explain_type_error(
2442 trace,
2443 self.arg_matching_ctxt.param_env,
2444 *e,
2445 );
2446 self.arg_matching_ctxt.suggest_confusable(&mut err);
2447 reported = Some(err.emit());
2448 return false;
2449 }
2450 true
2451 });
2452
2453 reported
2454 }
2455
2456 fn check_single_incompatible(&self) -> Option<ErrorGuaranteed> {
2457 if let &[
2458 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
2459 ] = &self.errors[..]
2460 {
2461 let (formal_ty, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2462 let (provided_ty, provided_arg_span) = self.provided_arg_tys[provided_idx];
2463 let trace = self.mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
2464 let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
2465 self.emit_coerce_suggestions(
2466 &mut err,
2467 self.provided_args[provided_idx],
2468 provided_ty,
2469 Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2470 .only_has_type(self.fn_ctxt)
2471 .unwrap_or(formal_ty),
2472 None,
2473 None,
2474 );
2475 let call_name = self.call_metadata.call_name;
2476 err.span_label(
2477 self.call_metadata.full_call_span,
2478 ::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"),
2479 );
2480
2481 self.label_generic_mismatches(&mut err);
2482
2483 if let hir::ExprKind::MethodCall(_, rcvr, _, _) =
2484 self.arg_matching_ctxt.args_ctxt.call_ctxt.call_expr.kind
2485 && provided_idx.as_usize() == expected_idx.as_usize()
2486 {
2487 self.note_source_of_type_mismatch_constraint(
2488 &mut err,
2489 rcvr,
2490 crate::demand::TypeMismatchSource::Arg {
2491 call_expr: self.call_expr,
2492 incompatible_arg: provided_idx.as_usize(),
2493 },
2494 );
2495 }
2496
2497 self.suggest_ptr_null_mut(
2498 expected_ty,
2499 provided_ty,
2500 self.provided_args[provided_idx],
2501 &mut err,
2502 );
2503
2504 self.suggest_deref_unwrap_or(
2505 &mut err,
2506 self.callee_ty,
2507 self.call_metadata.call_ident,
2508 expected_ty,
2509 provided_ty,
2510 self.provided_args[provided_idx],
2511 self.call_metadata.is_method,
2512 );
2513
2514 self.label_fn_like(
2516 &mut err,
2517 self.fn_id,
2518 self.callee_ty,
2519 self.call_expr,
2520 Some(expected_ty),
2521 Some(expected_idx.as_usize()),
2522 &self.matched_inputs,
2523 &self.formal_and_expected_inputs,
2524 self.call_metadata.is_method,
2525 self.tuple_arguments,
2526 );
2527 self.arg_matching_ctxt.suggest_confusable(&mut err);
2528 self.detect_dotdot(&mut err, provided_ty, self.provided_args[provided_idx]);
2529 return Some(err.emit());
2530 }
2531
2532 None
2533 }
2534
2535 fn maybe_optimize_extra_arg_suggestion(&mut self) {
2536 if let [Error::Extra(provided_idx)] = &self.errors[..] {
2537 if !self.remove_idx_is_perfect(provided_idx.as_usize()) {
2538 if let Some(i) = (0..self.args_ctxt.call_ctxt.provided_args.len())
2539 .find(|&i| self.remove_idx_is_perfect(i))
2540 {
2541 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))];
2542 }
2543 }
2544 }
2545 }
2546
2547 fn initial_final_diagnostic(&self) -> Diag<'_> {
2548 if self.formal_and_expected_inputs.len() == self.provided_args.len() {
2549 {
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!(
2550 self.dcx(),
2551 self.call_metadata.full_call_span,
2552 E0308,
2553 "arguments to this {} are incorrect",
2554 self.call_metadata.call_name,
2555 )
2556 } else {
2557 self.arg_matching_ctxt
2558 .dcx()
2559 .struct_span_err(
2560 self.call_metadata.full_call_span,
2561 ::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.arg_matching_ctxt.args_ctxt.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!(
2562 "this {} takes {}{} but {} {} supplied",
2563 self.call_metadata.call_name,
2564 if self.arg_matching_ctxt.args_ctxt.c_variadic { "at least " } else { "" },
2565 potentially_plural_count(self.formal_and_expected_inputs.len(), "argument"),
2566 potentially_plural_count(self.provided_args.len(), "argument"),
2567 pluralize!("was", self.provided_args.len())
2568 ),
2569 )
2570 .with_code(self.err_code.to_owned())
2571 }
2572 }
2573
2574 fn labels_and_suggestion_text(
2575 &self,
2576 err: &mut Diag<'_>,
2577 ) -> (Vec<(Span, String)>, Vec<(Span, String)>, SuggestionText) {
2578 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
2580 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
2581 }
2582
2583 let mut labels = Vec::new();
2584 let mut suggestion_text = SuggestionText::None;
2585
2586 let mut errors = self.errors.iter().peekable();
2587 let mut only_extras_so_far = errors
2588 .peek()
2589 .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));
2590 let mut prev_extra_idx = None;
2591 let mut suggestions = ::alloc::vec::Vec::new()vec![];
2592 while let Some(error) = errors.next() {
2593 only_extras_so_far &= #[allow(non_exhaustive_omitted_patterns)] match error {
Error::Extra(_) => true,
_ => false,
}matches!(error, Error::Extra(_));
2594
2595 match error {
2596 Error::Invalid(provided_idx, expected_idx, compatibility) => {
2597 let (formal_ty, expected_ty) =
2598 self.arg_matching_ctxt.args_ctxt.call_ctxt.formal_and_expected_inputs
2599 [*expected_idx];
2600 let (provided_ty, provided_span) =
2601 self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2602 if let Compatibility::Incompatible(error) = compatibility {
2603 let trace = self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2604 provided_span,
2605 (formal_ty, expected_ty),
2606 provided_ty,
2607 );
2608 if let Some(e) = error {
2609 self.err_ctxt().note_type_err(
2610 err,
2611 &trace.cause,
2612 None,
2613 Some(self.param_env.and(trace.values)),
2614 *e,
2615 true,
2616 None,
2617 );
2618 }
2619 }
2620
2621 self.emit_coerce_suggestions(
2622 err,
2623 self.provided_args[*provided_idx],
2624 provided_ty,
2625 Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2626 .only_has_type(self.fn_ctxt)
2627 .unwrap_or(formal_ty),
2628 None,
2629 None,
2630 );
2631 self.detect_dotdot(err, provided_ty, self.provided_args[*provided_idx]);
2632 }
2633 Error::Extra(arg_idx) => {
2634 let (provided_ty, provided_span) = self.provided_arg_tys[*arg_idx];
2635 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2636 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" of type `{0}`", provided_ty))
})format!(" of type `{provided_ty}`")
2638 } else {
2639 "".to_string()
2640 };
2641 let idx = if self.provided_arg_tys.len() == 1 {
2642 "".to_string()
2643 } else {
2644 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" #{0}", arg_idx.as_usize() + 1))
})format!(" #{}", arg_idx.as_usize() + 1)
2645 };
2646 labels.push((
2647 provided_span,
2648 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected argument{0}{1}", idx,
provided_ty_name))
})format!("unexpected argument{idx}{provided_ty_name}"),
2649 ));
2650 if self.provided_arg_tys.len() == 1
2651 && let Some(span) = self.maybe_suggest_expect_for_unwrap(provided_ty)
2652 {
2653 err.span_suggestion_verbose(
2654 span,
2655 "did you mean to use `expect`?",
2656 "expect",
2657 Applicability::MaybeIncorrect,
2658 );
2659 continue;
2660 }
2661 let mut span = provided_span;
2662 if span.can_be_used_for_suggestions()
2663 && self.call_metadata.error_span.can_be_used_for_suggestions()
2664 {
2665 if arg_idx.index() > 0
2666 && let Some((_, prev)) = self
2667 .provided_arg_tys
2668 .get(ProvidedIdx::from_usize(arg_idx.index() - 1))
2669 {
2670 span = prev.shrink_to_hi().to(span);
2672 }
2673
2674 let trim_next_comma = match errors.peek() {
2681 Some(Error::Extra(provided_idx))
2682 if only_extras_so_far
2683 && provided_idx.index() > arg_idx.index() + 1 =>
2684 {
2692 prev_extra_idx.is_none_or(|prev_extra_idx| {
2693 prev_extra_idx + 1 == arg_idx.index()
2694 })
2695 }
2696 None if only_extras_so_far => true,
2698 _ => false,
2700 };
2701
2702 if trim_next_comma {
2703 let next = self
2704 .provided_arg_tys
2705 .get(*arg_idx + 1)
2706 .map(|&(_, sp)| sp)
2707 .unwrap_or_else(|| {
2708 self.arg_matching_ctxt
2713 .tcx()
2714 .sess
2715 .source_map()
2716 .end_point(self.call_expr.span)
2717 });
2718
2719 span = span.until(next);
2721 }
2722
2723 suggestions.push((span, String::new()));
2724
2725 suggestion_text = match suggestion_text {
2726 SuggestionText::None => SuggestionText::Remove(false),
2727 SuggestionText::Remove(_) => SuggestionText::Remove(true),
2728 _ => SuggestionText::DidYouMean,
2729 };
2730 prev_extra_idx = Some(arg_idx.index())
2731 }
2732 self.detect_dotdot(err, provided_ty, self.provided_args[*arg_idx]);
2733 }
2734 Error::Missing(expected_idx) => {
2735 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];
2739 while let Some(e) = errors.next_if(|e| {
2740 #[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)
2741 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
2742 }) {
2743 match e {
2744 Error::Missing(expected_idx) => missing_idxs.push(*expected_idx),
2745 _ => {
::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!(
2746 "control flow ensures that we should always get an `Error::Missing`"
2747 ),
2748 }
2749 }
2750
2751 match &missing_idxs[..] {
2756 &[expected_idx] => {
2757 let (_, input_ty) = self.formal_and_expected_inputs[expected_idx];
2758 let span = if let Some((_, arg_span)) =
2759 self.provided_arg_tys.get(expected_idx.to_provided_idx())
2760 {
2761 *arg_span
2762 } else {
2763 self.args_span
2764 };
2765 let rendered = if !has_error_or_infer([input_ty]) {
2766 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" of type `{0}`", input_ty))
})format!(" of type `{input_ty}`")
2767 } else {
2768 "".to_string()
2769 };
2770 labels.push((
2771 span,
2772 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("argument #{0}{1} is missing",
expected_idx.as_usize() + 1, rendered))
})format!(
2773 "argument #{}{rendered} is missing",
2774 expected_idx.as_usize() + 1
2775 ),
2776 ));
2777
2778 suggestion_text = match suggestion_text {
2779 SuggestionText::None => SuggestionText::Provide(false),
2780 SuggestionText::Provide(_) => SuggestionText::Provide(true),
2781 _ => SuggestionText::DidYouMean,
2782 };
2783 }
2784 &[first_idx, second_idx] => {
2785 let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2786 let (_, second_expected_ty) =
2787 self.formal_and_expected_inputs[second_idx];
2788 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
2789 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2790 self.provided_arg_tys.get(second_idx.to_provided_idx()),
2791 ) {
2792 first_span.to(*second_span)
2793 } else {
2794 self.args_span
2795 };
2796 let rendered =
2797 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
2798 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" of type `{0}` and `{1}`",
first_expected_ty, second_expected_ty))
})format!(
2799 " of type `{first_expected_ty}` and `{second_expected_ty}`"
2800 )
2801 } else {
2802 "".to_string()
2803 };
2804 labels.push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("two arguments{0} are missing",
rendered))
})format!("two arguments{rendered} are missing")));
2805 suggestion_text = match suggestion_text {
2806 SuggestionText::None | SuggestionText::Provide(_) => {
2807 SuggestionText::Provide(true)
2808 }
2809 _ => SuggestionText::DidYouMean,
2810 };
2811 }
2812 &[first_idx, second_idx, third_idx] => {
2813 let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2814 let (_, second_expected_ty) =
2815 self.formal_and_expected_inputs[second_idx];
2816 let (_, third_expected_ty) = self.formal_and_expected_inputs[third_idx];
2817 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
2818 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2819 self.provided_arg_tys.get(third_idx.to_provided_idx()),
2820 ) {
2821 first_span.to(*third_span)
2822 } else {
2823 self.args_span
2824 };
2825 let rendered = if !has_error_or_infer([
2826 first_expected_ty,
2827 second_expected_ty,
2828 third_expected_ty,
2829 ]) {
2830 ::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!(
2831 " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
2832 )
2833 } else {
2834 "".to_string()
2835 };
2836 labels.push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("three arguments{0} are missing",
rendered))
})format!("three arguments{rendered} are missing")));
2837 suggestion_text = match suggestion_text {
2838 SuggestionText::None | SuggestionText::Provide(_) => {
2839 SuggestionText::Provide(true)
2840 }
2841 _ => SuggestionText::DidYouMean,
2842 };
2843 }
2844 missing_idxs => {
2845 let first_idx = *missing_idxs.first().unwrap();
2846 let last_idx = *missing_idxs.last().unwrap();
2847 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
2851 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2852 self.provided_arg_tys.get(last_idx.to_provided_idx()),
2853 ) {
2854 first_span.to(*last_span)
2855 } else {
2856 self.args_span
2857 };
2858 labels.push((span, "multiple arguments are missing".to_string()));
2859 suggestion_text = match suggestion_text {
2860 SuggestionText::None | SuggestionText::Provide(_) => {
2861 SuggestionText::Provide(true)
2862 }
2863 _ => SuggestionText::DidYouMean,
2864 };
2865 }
2866 }
2867 }
2868 Error::Swap(
2869 first_provided_idx,
2870 second_provided_idx,
2871 first_expected_idx,
2872 second_expected_idx,
2873 ) => {
2874 let (first_provided_ty, first_span) =
2875 self.provided_arg_tys[*first_provided_idx];
2876 let (_, first_expected_ty) =
2877 self.formal_and_expected_inputs[*first_expected_idx];
2878 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
2879 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", found `{0}`", first_provided_ty))
})format!(", found `{first_provided_ty}`")
2880 } else {
2881 String::new()
2882 };
2883 labels.push((
2884 first_span,
2885 ::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}"),
2886 ));
2887
2888 let (second_provided_ty, second_span) =
2889 self.provided_arg_tys[*second_provided_idx];
2890 let (_, second_expected_ty) =
2891 self.formal_and_expected_inputs[*second_expected_idx];
2892 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
2893 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", found `{0}`",
second_provided_ty))
})format!(", found `{second_provided_ty}`")
2894 } else {
2895 String::new()
2896 };
2897 labels.push((
2898 second_span,
2899 ::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}"),
2900 ));
2901
2902 suggestion_text = match suggestion_text {
2903 SuggestionText::None => SuggestionText::Swap,
2904 _ => SuggestionText::DidYouMean,
2905 };
2906 }
2907 Error::Permutation(args) => {
2908 for (dst_arg, dest_input) in args {
2909 let (_, expected_ty) = self.formal_and_expected_inputs[*dst_arg];
2910 let (provided_ty, provided_span) = self.provided_arg_tys[*dest_input];
2911 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2912 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", found `{0}`", provided_ty))
})format!(", found `{provided_ty}`")
2913 } else {
2914 String::new()
2915 };
2916 labels.push((
2917 provided_span,
2918 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected `{0}`{1}", expected_ty,
provided_ty_name))
})format!("expected `{expected_ty}`{provided_ty_name}"),
2919 ));
2920 }
2921
2922 suggestion_text = match suggestion_text {
2923 SuggestionText::None => SuggestionText::Reorder,
2924 _ => SuggestionText::DidYouMean,
2925 };
2926 }
2927 }
2928 }
2929
2930 (suggestions, labels, suggestion_text)
2931 }
2932
2933 fn label_generic_mismatches(&self, err: &mut Diag<'a>) {
2934 self.fn_ctxt.label_generic_mismatches(
2935 err,
2936 self.fn_id,
2937 &self.matched_inputs,
2938 &self.provided_arg_tys,
2939 &self.formal_and_expected_inputs,
2940 self.call_metadata.is_method,
2941 self.arg_matching_ctxt.tuple_arguments.is_splatted(),
2942 );
2943 }
2944
2945 fn append_arguments_changes(&self, suggestions: &mut Vec<(Span, String)>) {
2954 let mut prev = -1;
2969 for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
2970 if let Some(provided_idx) = provided_idx {
2973 prev = provided_idx.index() as i64;
2974 continue;
2975 }
2976 let idx = ProvidedIdx::from_usize((prev + 1) as usize);
2977 if let Some((_, arg_span)) = self.provided_arg_tys.get(idx) {
2978 prev += 1;
2979 let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2984 let dominated = suggestions
2988 .iter()
2989 .any(|(span, _)| span.contains(*arg_span) || arg_span.overlaps(*span));
2990 if !dominated {
2991 suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
2992 }
2993 }
2994 }
2995 }
2996
2997 fn format_suggestion_text(
2998 err: &mut Diag<'_>,
2999 suggestions: Vec<(Span, String)>,
3000 suggestion_text: SuggestionText,
3001 ) -> Option<String> {
3002 match suggestion_text {
3003 SuggestionText::None => None,
3004 SuggestionText::Provide(plural) => {
3005 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 { "" }))
3006 }
3007 SuggestionText::Remove(plural) => {
3008 err.multipart_suggestion(
3009 ::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 { "" }),
3010 suggestions,
3011 Applicability::HasPlaceholders,
3012 );
3013 None
3014 }
3015 SuggestionText::Swap => Some("swap these arguments".to_string()),
3016 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
3017 SuggestionText::DidYouMean => Some("did you mean".to_string()),
3018 }
3019 }
3020
3021 fn arguments_formatting(&self, suggestion_span: Span) -> ArgumentsFormatting {
3022 let source_map = self.sess().source_map();
3023 let mut provided_inputs = self.matched_inputs.iter().filter_map(|a| *a);
3024 if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
3025 && let Some(first_idx) = provided_inputs.by_ref().next()
3026 && let Some(last_idx) = provided_inputs.by_ref().next()
3027 && let (_, first_span) = self.provided_arg_tys[first_idx]
3028 && let (_, last_span) = self.provided_arg_tys[last_idx]
3029 && source_map.is_multiline(first_span.to(last_span))
3030 && let Some(fallback_indent) = source_map.indentation_before(first_span)
3031 {
3032 ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
3033 } else {
3034 ArgumentsFormatting::SingleLine
3035 }
3036 }
3037
3038 fn suggestion_code(&self) -> (Span, String) {
3039 let source_map = self.sess().source_map();
3040 let suggestion_span = if let Some(args_span) =
3041 self.call_metadata.error_span.trim_start(self.call_metadata.full_call_span)
3042 {
3043 args_span
3045 } else {
3046 self.call_metadata.full_call_span.shrink_to_hi()
3050 };
3051
3052 let arguments_formatting = self.arguments_formatting(suggestion_span);
3053
3054 let mut suggestion = "(".to_owned();
3055 let mut needs_comma = false;
3056 for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
3057 if needs_comma {
3058 suggestion += ",";
3059 }
3060 match &arguments_formatting {
3061 ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
3062 ArgumentsFormatting::SingleLine => {}
3063 ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
3064 }
3065 needs_comma = true;
3066 let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
3067 && let (_, provided_span) = self.provided_arg_tys[*provided_idx]
3068 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
3069 {
3070 (Some(provided_span), arg_text)
3071 } else {
3072 let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
3074 (None, self.ty_to_snippet(expected_ty, expected_idx))
3075 };
3076 if let ArgumentsFormatting::Multiline { fallback_indent, .. } = &arguments_formatting {
3077 let indent = suggestion_span
3078 .and_then(|span| source_map.indentation_before(span))
3079 .unwrap_or_else(|| fallback_indent.clone());
3080 suggestion += &indent;
3081 }
3082 suggestion += &suggestion_text;
3083 }
3084 if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
3085 suggestion += ",\n";
3086 suggestion += &brace_indent;
3087 }
3088 suggestion += ")";
3089
3090 (suggestion_span, suggestion)
3091 }
3092
3093 fn maybe_suggest_expect_for_unwrap(&self, provided_ty: Ty<'tcx>) -> Option<Span> {
3094 let tcx = self.tcx();
3095 if let Some(call_ident) = self.call_metadata.call_ident
3096 && call_ident.name == sym::unwrap
3097 && let Some(callee_ty) = self.callee_ty
3098 && let ty::Adt(adt, _) = callee_ty.peel_refs().kind()
3099 && (tcx.is_diagnostic_item(sym::Option, adt.did())
3100 || tcx.is_diagnostic_item(sym::Result, adt.did()))
3101 && self.may_coerce(provided_ty, Ty::new_static_str(tcx))
3102 {
3103 Some(call_ident.span)
3104 } else {
3105 None
3106 }
3107 }
3108}
3109
3110struct ArgMatchingCtxt<'a, 'tcx> {
3111 args_ctxt: ArgsCtxt<'a, 'tcx>,
3112 provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
3113}
3114
3115impl<'a, 'tcx> Deref for ArgMatchingCtxt<'a, 'tcx> {
3116 type Target = ArgsCtxt<'a, 'tcx>;
3117
3118 fn deref(&self) -> &Self::Target {
3119 &self.args_ctxt
3120 }
3121}
3122
3123impl<'a, 'tcx> ArgMatchingCtxt<'a, 'tcx> {
3124 fn new(
3125 arg: &'a FnCtxt<'a, 'tcx>,
3126 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3127 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3128 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
3129 c_variadic: bool,
3130 err_code: ErrCode,
3131 fn_id: SplatLoweringInfo<'tcx>,
3133 call_span: Span,
3134 call_expr: &'tcx Expr<'tcx>,
3135 tuple_arguments: TupleArgumentsFlag,
3136 ) -> Self {
3137 let args_ctxt = ArgsCtxt::new(
3138 arg,
3139 compatibility_diagonal,
3140 formal_and_expected_inputs,
3141 provided_args,
3142 c_variadic,
3143 err_code,
3144 fn_id,
3145 call_span,
3146 call_expr,
3147 tuple_arguments,
3148 );
3149 let provided_arg_tys = args_ctxt.provided_arg_tys();
3150
3151 ArgMatchingCtxt { args_ctxt, provided_arg_tys }
3152 }
3153
3154 fn suggest_confusable(&self, err: &mut Diag<'_>) {
3155 let Some(call_name) = self.call_metadata.call_ident else {
3156 return;
3157 };
3158 let Some(callee_ty) = self.callee_ty else {
3159 return;
3160 };
3161 let input_types: Vec<Ty<'_>> = self.provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
3162
3163 if let Some(_name) = self.confusable_method_name(
3171 err,
3172 callee_ty.peel_refs(),
3173 call_name,
3174 Some(input_types.clone()),
3175 ) {
3176 return;
3177 }
3178 if let Some((assoc, fn_sig)) = self.similar_assoc(call_name)
3180 && fn_sig.inputs()[1..]
3181 .iter()
3182 .eq_by(input_types, |expected, found| self.may_coerce(*expected, found))
3183 {
3184 let assoc_name = assoc.name();
3185 err.span_suggestion_verbose(
3186 call_name.span,
3187 ::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),
3188 assoc_name,
3189 Applicability::MaybeIncorrect,
3190 );
3191 return;
3192 }
3193 }
3194
3195 fn check_compatible(
3199 &self,
3200 provided_idx: ProvidedIdx,
3201 expected_idx: ExpectedIdx,
3202 ) -> Compatibility<'tcx> {
3203 if provided_idx.as_usize() == expected_idx.as_usize() {
3204 return self.compatibility_diagonal[provided_idx].clone();
3205 }
3206
3207 let (formal_input_ty, expected_input_ty) = self.formal_and_expected_inputs[expected_idx];
3208 if (formal_input_ty, expected_input_ty).references_error() {
3212 return Compatibility::Incompatible(None);
3213 }
3214
3215 let (arg_ty, arg_span) = self.provided_arg_tys[provided_idx];
3216
3217 let expectation = Expectation::rvalue_hint(self.fn_ctxt, expected_input_ty);
3218 let coerced_ty = expectation.only_has_type(self.fn_ctxt).unwrap_or(formal_input_ty);
3219 let can_coerce = self.may_coerce(arg_ty, coerced_ty);
3220 if !can_coerce {
3221 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
3222 ty::error::ExpectedFound::new(coerced_ty, arg_ty),
3223 )));
3224 }
3225
3226 let subtyping_error = self.probe(|_| {
3228 self.at(&self.misc(arg_span), self.param_env)
3229 .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
3230 .err()
3231 });
3232
3233 let references_error = (coerced_ty, arg_ty).references_error();
3236 match (references_error, subtyping_error) {
3237 (false, None) => Compatibility::Compatible,
3238 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
3239 }
3240 }
3241
3242 fn remove_idx_is_perfect(&self, idx: usize) -> bool {
3243 let removed_arg_tys = self
3244 .provided_arg_tys
3245 .iter()
3246 .enumerate()
3247 .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
3248 .collect::<IndexVec<ProvidedIdx, _>>();
3249 std::iter::zip(self.formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
3250 |((expected_ty, _), (provided_ty, _))| {
3251 !provided_ty.references_error() && self.may_coerce(*provided_ty, *expected_ty)
3252 },
3253 )
3254 }
3255}
3256
3257struct ArgsCtxt<'a, 'tcx> {
3258 call_ctxt: CallCtxt<'a, 'tcx>,
3259 call_metadata: CallMetadata,
3260 args_span: Span,
3261}
3262
3263impl<'a, 'tcx> Deref for ArgsCtxt<'a, 'tcx> {
3264 type Target = CallCtxt<'a, 'tcx>;
3265
3266 fn deref(&self) -> &Self::Target {
3267 &self.call_ctxt
3268 }
3269}
3270
3271impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> {
3272 fn new(
3273 arg: &'a FnCtxt<'a, 'tcx>,
3274 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3275 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3276 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
3277 c_variadic: bool,
3278 err_code: ErrCode,
3279 fn_id: SplatLoweringInfo<'tcx>,
3281 call_span: Span,
3282 call_expr: &'tcx Expr<'tcx>,
3283 tuple_arguments: TupleArgumentsFlag,
3284 ) -> Self {
3285 let call_ctxt: CallCtxt<'_, '_> = CallCtxt::new(
3286 arg,
3287 compatibility_diagonal,
3288 formal_and_expected_inputs,
3289 provided_args,
3290 c_variadic,
3291 err_code,
3292 fn_id,
3293 call_span,
3294 call_expr,
3295 tuple_arguments,
3296 );
3297
3298 let call_metadata = call_ctxt.call_metadata();
3299 let args_span = call_metadata
3300 .error_span
3301 .trim_start(call_metadata.full_call_span)
3302 .unwrap_or(call_metadata.error_span);
3303
3304 ArgsCtxt { args_span, call_metadata, call_ctxt }
3305 }
3306
3307 fn normalize_span(&self, span: Span) -> Span {
3311 let normalized_span =
3312 span.find_ancestor_inside_same_ctxt(self.call_metadata.error_span).unwrap_or(span);
3313 if normalized_span.source_equal(self.call_metadata.error_span) {
3317 span
3318 } else {
3319 normalized_span
3320 }
3321 }
3322
3323 fn provided_arg_tys(&self) -> IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> {
3325 self.call_ctxt
3326 .provided_args
3327 .iter()
3328 .map(|expr| {
3329 let ty = self
3330 .call_ctxt
3331 .fn_ctxt
3332 .typeck_results
3333 .borrow()
3334 .expr_ty_adjusted_opt(expr)
3335 .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx));
3336 (
3337 self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty),
3338 self.normalize_span(expr.span),
3339 )
3340 })
3341 .collect()
3342 }
3343
3344 fn similar_assoc(&self, call_name: Ident) -> Option<(ty::AssocItem, ty::FnSig<'tcx>)> {
3346 if let Some(callee_ty) = self.call_ctxt.callee_ty
3347 && let Ok(Some(assoc)) = self.call_ctxt.fn_ctxt.probe_op(
3348 call_name.span,
3349 MethodCall,
3350 Some(call_name),
3351 None,
3352 IsSuggestion(true),
3353 callee_ty.peel_refs(),
3354 self.call_ctxt.callee_expr.unwrap().hir_id,
3355 TraitsInScope,
3356 |mut ctxt| ctxt.probe_for_similar_candidate(),
3357 )
3358 && assoc.is_method()
3359 {
3360 let args =
3361 self.call_ctxt.fn_ctxt.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
3362 let fn_sig = self
3363 .call_ctxt
3364 .fn_ctxt
3365 .tcx
3366 .fn_sig(assoc.def_id)
3367 .instantiate(self.call_ctxt.fn_ctxt.tcx, args)
3368 .skip_norm_wip();
3369
3370 self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars(
3371 call_name.span,
3372 BoundRegionConversionTime::FnCall,
3373 fn_sig,
3374 );
3375 }
3376 None
3377 }
3378
3379 fn call_is_in_macro(&self) -> bool {
3380 self.call_metadata.full_call_span.in_external_macro(self.sess().source_map())
3381 }
3382}
3383
3384struct CallMetadata {
3385 error_span: Span,
3386 call_ident: Option<Ident>,
3387 full_call_span: Span,
3388 call_name: &'static str,
3389 is_method: bool,
3390}
3391
3392struct CallCtxt<'a, 'tcx> {
3393 fn_ctxt: &'a FnCtxt<'a, 'tcx>,
3394 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3395 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3396 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3397 c_variadic: bool,
3398 err_code: ErrCode,
3399 fn_id: SplatLoweringInfo<'tcx>,
3401 call_span: Span,
3402 call_expr: &'tcx hir::Expr<'tcx>,
3403 tuple_arguments: TupleArgumentsFlag,
3404 callee_expr: Option<&'tcx Expr<'tcx>>,
3405 callee_ty: Option<Ty<'tcx>>,
3406}
3407
3408impl<'a, 'tcx> Deref for CallCtxt<'a, 'tcx> {
3409 type Target = &'a FnCtxt<'a, 'tcx>;
3410
3411 fn deref(&self) -> &Self::Target {
3412 &self.fn_ctxt
3413 }
3414}
3415
3416impl<'a, 'tcx> CallCtxt<'a, 'tcx> {
3417 fn new(
3418 fn_ctxt: &'a FnCtxt<'a, 'tcx>,
3419 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3420 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3421 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3422 c_variadic: bool,
3423 err_code: ErrCode,
3424 fn_id: SplatLoweringInfo<'tcx>,
3426 call_span: Span,
3427 call_expr: &'tcx hir::Expr<'tcx>,
3428 tuple_arguments: TupleArgumentsFlag,
3429 ) -> CallCtxt<'a, 'tcx> {
3430 let callee_expr = match &call_expr.peel_blocks().kind {
3431 hir::ExprKind::Call(callee, _) => Some(*callee),
3432 hir::ExprKind::MethodCall(_, receiver, ..) => {
3433 if let Some((DefKind::AssocFn, def_id)) =
3434 fn_ctxt.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
3435 && let Some(assoc) = fn_ctxt.tcx.opt_associated_item(def_id)
3436 && assoc.is_method()
3437 {
3438 Some(*receiver)
3439 } else {
3440 None
3441 }
3442 }
3443 _ => None,
3444 };
3445
3446 let callee_ty = callee_expr.and_then(|callee_expr| {
3447 fn_ctxt.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
3448 });
3449
3450 CallCtxt {
3451 fn_ctxt,
3452 compatibility_diagonal,
3453 formal_and_expected_inputs,
3454 provided_args,
3455 c_variadic,
3456 err_code,
3457 fn_id,
3458 call_span,
3459 call_expr,
3460 tuple_arguments,
3461 callee_expr,
3462 callee_ty,
3463 }
3464 }
3465
3466 fn call_metadata(&self) -> CallMetadata {
3467 match &self.call_expr.kind {
3468 hir::ExprKind::Call(
3469 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
3470 _,
3471 ) => {
3472 if let Res::Def(DefKind::Ctor(of, _), _) =
3473 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
3474 {
3475 let name = match of {
3476 CtorOf::Struct => "struct",
3477 CtorOf::Variant => "enum variant",
3478 };
3479 CallMetadata {
3480 error_span: self.call_span,
3481 call_ident: None,
3482 full_call_span: *span,
3483 call_name: name,
3484 is_method: false,
3485 }
3486 } else {
3487 CallMetadata {
3488 error_span: self.call_span,
3489 call_ident: None,
3490 full_call_span: *span,
3491 call_name: "function",
3492 is_method: false,
3493 }
3494 }
3495 }
3496 hir::ExprKind::Call(hir::Expr { span, .. }, _) => CallMetadata {
3497 error_span: self.call_span,
3498 call_ident: None,
3499 full_call_span: *span,
3500 call_name: "function",
3501 is_method: false,
3502 },
3503 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
3504 let ident_span = path_segment.ident.span;
3505 let ident_span = if let Some(args) = path_segment.args {
3506 ident_span.with_hi(args.span_ext.hi())
3507 } else {
3508 ident_span
3509 };
3510 CallMetadata {
3511 error_span: *span,
3512 call_ident: Some(path_segment.ident),
3513 full_call_span: ident_span,
3514 call_name: "method",
3515 is_method: true,
3516 }
3517 }
3518 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),
3519 }
3520 }
3521
3522 fn mk_trace(
3523 &self,
3524 span: Span,
3525 (formal_ty, expected_ty): (Ty<'tcx>, Ty<'tcx>),
3526 provided_ty: Ty<'tcx>,
3527 ) -> TypeTrace<'tcx> {
3528 let mismatched_ty = if expected_ty == provided_ty {
3529 formal_ty
3533 } else {
3534 expected_ty
3535 };
3536 TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
3537 }
3538
3539 fn ty_to_snippet(&self, ty: Ty<'tcx>, expected_idx: ExpectedIdx) -> String {
3540 if ty.is_unit() {
3541 "()".to_string()
3542 } else if ty.is_suggestable(self.tcx, false) {
3543 {
let _guard = ForceTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", ty))
})
}with_forced_trimmed_paths!(format!("/* {ty} */"))
3544 } else if let SplatLoweringInfo::FnDef(fn_def_id) = self.fn_id
3545 && self.tcx.def_kind(fn_def_id).is_fn_like()
3546 && let self_implicit =
3547 #[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
3548 && let Some(Some(arg)) =
3549 self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
3550 && arg.name != kw::SelfLower
3551 {
3552 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", arg.name))
})format!("/* {} */", arg.name)
3553 } else {
3554 "/* value */".to_string()
3558 }
3559 }
3560
3561 fn first_incompatible_error(&self) -> Option<(ProvidedIdx, TypeError<'tcx>)> {
3562 self.compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
3563 if let Compatibility::Incompatible(Some(terr)) = c { Some((i, *terr)) } else { None }
3564 })
3565 }
3566}
3567
3568enum SuggestionText {
3569 None,
3570 Provide(bool),
3571 Remove(bool),
3572 Swap,
3573 Reorder,
3574 DidYouMean,
3575}
3576
3577fn same_type_modulo_vars<'tcx>(tcx: TyCtxt<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
3578 struct SameModuloVars<'tcx> {
3579 tcx: TyCtxt<'tcx>,
3580 }
3581 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameModuloVars<'tcx> {
3582 fn cx(&self) -> TyCtxt<'tcx> {
3583 self.tcx
3584 }
3585
3586 fn relate_ty_args(
3587 &mut self,
3588 a_ty: Ty<'tcx>,
3589 _b_ty: Ty<'tcx>,
3590 _ty_def_id: DefId,
3591 a_args: ty::GenericArgsRef<'tcx>,
3592 b_args: ty::GenericArgsRef<'tcx>,
3593 _mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
3594 ) -> RelateResult<'tcx, Ty<'tcx>> {
3595 relate::relate_args_invariantly(self, a_args, b_args)?;
3596 Ok(a_ty)
3597 }
3598
3599 fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
3600 &mut self,
3601 _variance: ty::Variance,
3602 _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
3603 a: T,
3604 b: T,
3605 ) -> RelateResult<'tcx, T> {
3606 self.relate(a, b)
3607 }
3608
3609 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
3610 if a == b {
3611 return Ok(a);
3612 }
3613
3614 match (a.kind(), b.kind()) {
3615 (&ty::Infer(ty::InferTy::TyVar(_)), &ty::Infer(ty::InferTy::TyVar(_)))
3616 | (&ty::Infer(ty::InferTy::FloatVar(_)), &ty::Infer(ty::InferTy::FloatVar(_)))
3617 | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Infer(ty::InferTy::IntVar(_))) => Ok(a),
3618 (&ty::Infer(_), _) | (_, &ty::Infer(_)) => Err(TypeError::Mismatch),
3619 (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)),
3620 _ => relate::structurally_relate_tys(self, a, b),
3621 }
3622 }
3623
3624 fn regions(
3625 &mut self,
3626 a: ty::Region<'tcx>,
3627 _b: ty::Region<'tcx>,
3628 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
3629 Ok(a)
3630 }
3631
3632 fn consts(
3633 &mut self,
3634 mut a: ty::Const<'tcx>,
3635 mut b: ty::Const<'tcx>,
3636 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
3637 if a == b {
3638 return Ok(a);
3639 }
3640
3641 if self.tcx.features().generic_const_exprs() {
3644 a = self.tcx.expand_abstract_consts(a);
3645 b = self.tcx.expand_abstract_consts(b);
3646 }
3647
3648 match (a.kind(), b.kind()) {
3649 (ty::ConstKind::Infer(_), ty::ConstKind::Infer(_)) => return Ok(a),
3650 (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
3651 return Err(TypeError::ConstMismatch(ExpectedFound::new(a, b)));
3652 }
3653 _ => {}
3654 }
3655
3656 relate::structurally_relate_consts(self, a, b)
3657 }
3658
3659 fn binders<T>(
3660 &mut self,
3661 a: ty::Binder<'tcx, T>,
3662 b: ty::Binder<'tcx, T>,
3663 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
3664 where
3665 T: Relate<TyCtxt<'tcx>>,
3666 {
3667 Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
3668 }
3669 }
3670
3671 SameModuloVars { tcx }.relate(a, b).is_ok()
3672}