1use std::ops::Deref;
2use std::{fmt, iter};
3
4use itertools::Itertools;
5use rustc_ast as ast;
6use rustc_data_structures::fx::FxIndexSet;
7use rustc_errors::codes::*;
8use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize};
9use rustc_hir as hir;
10use rustc_hir::attrs::DivergingBlockBehavior;
11use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
12use rustc_hir::def_id::DefId;
13use rustc_hir::intravisit::Visitor;
14use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal};
15use rustc_hir_analysis::check::potentially_plural_count;
16use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath};
17use rustc_index::IndexVec;
18use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace};
19use rustc_middle::ty::adjustment::AllowTwoPhase;
20use rustc_middle::ty::error::TypeError;
21use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
22use rustc_middle::{bug, span_bug};
23use rustc_session::Session;
24use rustc_session::errors::ExprParenthesesNeeded;
25use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
26use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
27use rustc_trait_selection::infer::InferCtxtExt;
28use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
29use smallvec::SmallVec;
30use tracing::debug;
31
32use crate::Expectation::*;
33use crate::TupleArgumentsFlag::*;
34use crate::coercion::CoerceMany;
35use crate::diagnostics::SuggestPtrNullMut;
36use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
37use crate::gather_locals::Declaration;
38use crate::inline_asm::InlineAsmCtxt;
39use crate::method::probe::IsSuggestion;
40use crate::method::probe::Mode::MethodCall;
41use crate::method::probe::ProbeScope::TraitsInScope;
42use crate::{
43 BreakableCtxt, Diverges, Expectation, FnCtxt, GatherLocalsVisitor, LoweredTy, Needs,
44 TupleArgumentsFlag, diagnostics, struct_span_code_err,
45};
46
47impl ::std::fmt::Debug for GenericIdx {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("GenericIdx({0})", self.as_u32()))
}
}rustc_index::newtype_index! {
48 #[orderable]
49 #[debug_format = "GenericIdx({})"]
50 pub(crate) struct GenericIdx {}
51}
52
53#[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)]
55struct TupledArgCheckOutcome<'tcx> {
56 new_err_code: Option<ErrCode>,
58
59 untupled_formal_input_tys: Vec<Ty<'tcx>>,
61
62 untupled_expected_input_tys: Option<Vec<Ty<'tcx>>>,
64}
65
66impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
67 pub(in super::super) fn check_casts(&mut self) {
68 let mut deferred_cast_checks = self.root_ctxt.deferred_cast_checks.borrow_mut();
69 {
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:69",
"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(69u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_casts: {0} deferred checks",
deferred_cast_checks.len()) as &dyn Value))])
});
} else { ; }
};debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
70 for cast in deferred_cast_checks.drain(..) {
71 let body_id = std::mem::replace(&mut self.body_id, cast.body_id);
72 cast.check(self);
73 self.body_id = body_id;
74 }
75 }
76
77 pub(in super::super) fn check_asms(&self) {
78 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
79 {
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:79",
"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(79u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_asm: {0} deferred checks",
deferred_asm_checks.len()) as &dyn Value))])
});
} else { ; }
};debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
80 for (asm, hir_id) in deferred_asm_checks.drain(..) {
81 let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
82 InlineAsmCtxt::new(self, enclosing_id).check_asm(asm);
83 }
84 }
85
86 pub(in super::super) fn check_repeat_exprs(&self) {
87 let mut deferred_repeat_expr_checks = self.deferred_repeat_expr_checks.borrow_mut();
88 {
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:88",
"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(88u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("FnCtxt::check_repeat_exprs: {0} deferred checks",
deferred_repeat_expr_checks.len()) as &dyn Value))])
});
} else { ; }
};debug!("FnCtxt::check_repeat_exprs: {} deferred checks", deferred_repeat_expr_checks.len());
89
90 let deferred_repeat_expr_checks = deferred_repeat_expr_checks
91 .drain(..)
92 .flat_map(|(element, element_ty, count)| {
93 match &element.kind {
97 hir::ExprKind::ConstBlock(..) => return None,
98 hir::ExprKind::Path(qpath) => {
99 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
100 if let Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, _) = res
101 {
102 return None;
103 }
104 }
105 _ => {}
106 }
107
108 let count = self.structurally_resolve_const(
113 element.span,
114 self.normalize(element.span, Unnormalized::new_wip(count)),
115 );
116
117 if count.references_error() {
121 return None;
122 }
123
124 Some((element, element_ty, count))
125 })
126 .collect::<Vec<_>>();
132
133 let enforce_copy_bound = |element: &hir::Expr<'_>, element_ty| {
134 let is_constable = match element.kind {
138 hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
139 ty::FnDef(def_id, _) if self.tcx.is_stable_const_fn(def_id) => {
140 traits::IsConstable::Fn
141 }
142 _ => traits::IsConstable::No,
143 },
144 hir::ExprKind::Path(qpath) => {
145 match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
146 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
147 _ => traits::IsConstable::No,
148 }
149 }
150 _ => traits::IsConstable::No,
151 };
152
153 let lang_item = self.tcx.require_lang_item(LangItem::Copy, element.span);
154 let code = traits::ObligationCauseCode::RepeatElementCopy {
155 is_constable,
156 elt_span: element.span,
157 };
158 self.require_type_meets(element_ty, element.span, code, lang_item);
159 };
160
161 for (element, element_ty, count) in deferred_repeat_expr_checks {
162 match count.kind() {
163 ty::ConstKind::Value(val) => {
164 if val.try_to_target_usize(self.tcx).is_none_or(|count| count > 1) {
165 enforce_copy_bound(element, element_ty)
166 } else {
167 }
170 }
171
172 ty::ConstKind::Param(_)
175 | ty::ConstKind::Expr(_)
176 | ty::ConstKind::Placeholder(_)
177 | ty::ConstKind::Alias(_, _) => enforce_copy_bound(element, element_ty),
178
179 ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => {
180 ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
181 }
182 }
183 }
184 }
185
186 pub(in super::super) fn check_argument_types(
189 &self,
190 call_span: Span,
192 call_expr: &'tcx hir::Expr<'tcx>,
194 formal_input_tys: &[Ty<'tcx>],
196 formal_output: Ty<'tcx>,
197 expectation: Expectation<'tcx>,
199 provided_args: &'tcx [hir::Expr<'tcx>],
201 c_variadic: bool,
203 tuple_arguments: TupleArgumentsFlag,
205 fn_def_id: Option<DefId>,
207 callee_generic_args: Option<ty::GenericArgsRef<'tcx>>,
209 ) {
210 let tcx = self.tcx;
211
212 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
227 self.register_wf_obligation(
228 fn_input_ty.into(),
229 arg_expr.span,
230 ObligationCauseCode::WellFormed(None),
231 );
232
233 self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
234 }
235
236 let formal_output = self.resolve_vars_with_obligations(formal_output);
242 let mut expected_input_tys: Option<Vec<_>> = expectation
243 .only_has_type(self)
244 .and_then(|expected_output| {
245 self.fudge_inference_if_ok(|| {
251 let ocx = ObligationCtxt::new(self);
252
253 let origin = self.misc(call_span);
258 ocx.sup(&origin, self.param_env, expected_output, formal_output)?;
259
260 for &ty in formal_input_tys {
263 ocx.register_obligation(traits::Obligation::new(
264 self.tcx,
265 self.misc(call_span),
266 self.param_env,
267 ty::ClauseKind::WellFormed(ty.into()),
268 ));
269 }
270
271 if !ocx.try_evaluate_obligations().is_empty() {
272 return Err(TypeError::Mismatch);
273 }
274
275 Ok(Some(
278 formal_input_tys
279 .iter()
280 .map(|&ty| self.resolve_vars_if_possible(ty))
281 .collect(),
282 ))
283 })
284 .ok()
285 })
286 .unwrap_or_default();
287
288 let mut err_code = E0061;
289
290 let mut formal_input_tys = formal_input_tys.to_vec();
291
292 if tuple_arguments.is_tupled() {
294 let outcome = self.check_tupled_arguments(
297 call_span,
298 call_expr,
299 formal_input_tys,
300 provided_args,
301 expected_input_tys,
302 c_variadic,
303 tuple_arguments,
304 fn_def_id,
305 callee_generic_args,
306 );
307 let TupledArgCheckOutcome {
308 new_err_code,
309 untupled_formal_input_tys,
310 untupled_expected_input_tys,
311 } = outcome;
312 if let Some(new_err_code) = new_err_code {
313 err_code = new_err_code;
314 }
315 formal_input_tys = untupled_formal_input_tys;
316 expected_input_tys = untupled_expected_input_tys;
317 }
318
319 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
321 {
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());
322 expected_input_tys
323 } else {
324 formal_input_tys.clone()
325 };
326
327 let minimum_input_count = expected_input_tys.len();
328 let provided_arg_count = provided_args.len();
329
330 let demand_compatible = |idx| {
334 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
335 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
336 let provided_arg: &hir::Expr<'tcx> = &provided_args[idx];
337
338 {
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:338",
"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(338u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("checking argument {0}: {1:?} = {2:?}",
idx, provided_arg, formal_input_ty) as &dyn Value))])
});
} else { ; }
};debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
339
340 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
344
345 let checked_ty = self
348 .tcx
349 .hir_opt_delegation_info(self.body_id)
350 .and_then(|_| self.typeck_results.borrow().node_type_opt(provided_arg.hir_id))
351 .unwrap_or_else(|| self.check_expr_with_expectation(provided_arg, expectation));
352
353 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
357
358 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
362
363 let coerce_error =
364 self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
365 if coerce_error.is_some() {
366 return Compatibility::Incompatible(coerce_error);
367 }
368
369 let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq(
372 DefineOpaqueTypes::Yes,
373 formal_input_ty,
374 coerced_ty,
375 );
376
377 match formal_ty_error {
379 Ok(InferOk { obligations, value: () }) => {
380 self.register_predicates(obligations);
381 Compatibility::Compatible
382 }
383 Err(err) => Compatibility::Incompatible(Some(err)),
384 }
385 };
386
387 let mut compatibility_diagonal =
390 ::alloc::vec::from_elem(Compatibility::Incompatible(None),
provided_args.len())vec![Compatibility::Incompatible(None); provided_args.len()];
391
392 let mut call_appears_satisfied = if c_variadic {
397 provided_arg_count >= minimum_input_count
398 } else {
399 provided_arg_count == minimum_input_count
400 };
401
402 for check_closures in [false, true] {
408 if check_closures {
412 self.select_obligations_where_possible(|_| {})
413 }
414
415 for (idx, arg) in provided_args.iter().enumerate() {
418 if !check_closures {
422 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
423 }
424
425 if idx >= minimum_input_count {
431 continue;
432 }
433
434 let is_closure = if let ExprKind::Closure(closure) = arg.kind {
440 !tcx.coroutine_is_async(closure.def_id.to_def_id())
441 } else {
442 false
443 };
444 if is_closure != check_closures {
445 continue;
446 }
447
448 let compatible = demand_compatible(idx);
449 let is_compatible = #[allow(non_exhaustive_omitted_patterns)] match compatible {
Compatibility::Compatible => true,
_ => false,
}matches!(compatible, Compatibility::Compatible);
450 compatibility_diagonal[idx] = compatible;
451
452 if !is_compatible {
453 call_appears_satisfied = false;
454 }
455 }
456 }
457
458 if c_variadic && provided_arg_count < minimum_input_count {
459 err_code = E0060;
460 }
461
462 for arg in provided_args.iter().skip(minimum_input_count) {
463 let arg_ty = self.check_expr(arg);
465
466 if c_variadic {
471 fn variadic_error<'tcx>(
472 sess: &'tcx Session,
473 span: Span,
474 ty: Ty<'tcx>,
475 cast_ty: &str,
476 ) {
477 sess.dcx().emit_err(diagnostics::PassToVariadicFunction {
478 span,
479 ty,
480 cast_ty,
481 sugg_span: span.shrink_to_hi(),
482 teach: sess.teach(E0617),
483 });
484 }
485
486 let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
495 if let Some(trait_def_id) = tcx.lang_items().va_arg_safe()
496 && self
497 .type_implements_trait(trait_def_id, [arg_ty], self.param_env)
498 .must_apply_modulo_regions()
499 {
500 continue;
501 }
502
503 match arg_ty.kind() {
504 ty::Float(ty::FloatTy::F32) => {
505 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
506 }
507 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
508 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
509 }
510 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
511 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
512 }
513 ty::FnDef(..) => {
514 let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
515 let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
516
517 let fn_item_spa = arg.span;
518 tcx.sess.dcx().emit_err(diagnostics::PassFnItemToVariadicFunction {
519 span: fn_item_spa,
520 sugg_span: fn_item_spa.shrink_to_hi(),
521 replace: fn_ptr,
522 });
523 }
524 _ => {}
525 }
526 }
527 }
528
529 if !call_appears_satisfied {
530 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
531 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
532 minimum_input_count
533 } else {
534 provided_arg_count
535 }));
536 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!(
537 formal_input_tys.len(),
538 expected_input_tys.len(),
539 "expected formal_input_tys to be the same size as expected_input_tys"
540 );
541 let formal_and_expected_inputs = IndexVec::from_iter(
542 formal_input_tys
543 .iter()
544 .copied()
545 .zip_eq(expected_input_tys.iter().copied())
546 .map(|vars| self.resolve_vars_if_possible(vars)),
547 );
548
549 self.report_arg_errors(
550 compatibility_diagonal,
551 formal_and_expected_inputs,
552 provided_args,
553 c_variadic,
554 err_code,
555 fn_def_id,
556 call_span,
557 call_expr,
558 tuple_arguments,
559 );
560 }
561 }
562
563 fn check_tupled_arguments(
565 &self,
566 call_span: Span,
568 call_expr: &'tcx hir::Expr<'tcx>,
570 mut formal_input_tys: Vec<Ty<'tcx>>,
572 provided_args: &'tcx [hir::Expr<'tcx>],
574 mut expected_input_tys: Option<Vec<Ty<'tcx>>>,
576 c_variadic: bool,
578 tuple_arguments: TupleArgumentsFlag,
581 fn_def_id: Option<DefId>,
583 callee_generic_args: Option<ty::GenericArgsRef<'tcx>>,
585 ) -> TupledArgCheckOutcome<'tcx> {
586 let (first_tupled_arg_index, is_self_splatted) = tuple_arguments.tupled_arg_index();
587 let Some(first_tupled_arg_index) = first_tupled_arg_index else {
588 return TupledArgCheckOutcome {
590 new_err_code: None,
591 untupled_formal_input_tys: formal_input_tys,
592 untupled_expected_input_tys: expected_input_tys,
593 };
594 };
595
596 let tupled_args_count = (1 + provided_args.len()).checked_sub(formal_input_tys.len());
605 {
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:605",
"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(605u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["first_tupled_arg_index",
"is_self_splatted", "tupled_args_count", "tuple_arguments",
"c_variadic", "provided_args_len", "formal_input_tys_len"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&first_tupled_arg_index)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&is_self_splatted)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&tupled_args_count)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&tuple_arguments)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&c_variadic)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&provided_args.len())
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&formal_input_tys.len())
as &dyn Value))])
});
} else { ; }
};debug!(
606 ?first_tupled_arg_index, ?is_self_splatted,
607 ?tupled_args_count, ?tuple_arguments, ?c_variadic,
608 provided_args_len = ?provided_args.len(), formal_input_tys_len = ?formal_input_tys.len()
609 );
610
611 if first_tupled_arg_index >= formal_input_tys.len() {
614 ::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:?}, c_variadic = {6:?}, provided_args: {1}",
formal_input_tys.len(), provided_args.len(), first_tupled_arg_index,
is_self_splatted, tupled_args_count, tuple_arguments, c_variadic));span_bug!(
615 call_span,
616 "splatted argument index is out of bounds: {first_tupled_arg_index:?} >= {}, \
617 is_self_splatted = {is_self_splatted:?}, \
618 tupled_args_count = {tupled_args_count:?}, {tuple_arguments:?}, \
619 c_variadic = {c_variadic:?}, provided_args: {}",
620 formal_input_tys.len(),
621 provided_args.len(),
622 );
623 }
624
625 let tuple_type = if tuple_arguments.is_splatted() {
627 let callee_tuple_type =
628 self.resolve_vars_with_obligations(formal_input_tys[first_tupled_arg_index]);
629 if callee_tuple_type.is_ty_var()
630 && let Some(tupled_args_count) = tupled_args_count
631 {
632 let ocx = ObligationCtxt::new(self);
634 let origin = self.misc(call_span);
635
636 let new_tupled_type = Ty::new_tup_from_iter(
637 self.tcx,
638 iter::repeat_with(|| self.next_ty_var(call_span)).take(tupled_args_count),
639 );
640
641 let ocx_error = ocx.eq(&origin, self.param_env, callee_tuple_type, new_tupled_type);
643 if let Err(ocx_error) = ocx_error {
644 {
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!(
646 self.dcx(),
647 call_span,
648 E0277,
650 "cannot resolve splatted arguments; splatted type parameters \
651 must be a tuple or unit type: {:?}",
652 ocx_error,
653 )
654 .emit();
655 }
656
657 let type_errors = ocx.try_evaluate_obligations();
658 if type_errors.is_empty() {
659 new_tupled_type
660 } else {
661 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!(
662 self.dcx(),
663 call_span,
664 E0277,
665 "cannot resolve splatted arguments; splatted type parameters \
666 must be a tuple or unit type: {:?}",
667 type_errors,
668 )
669 .emit();
670 Ty::new_error(self.tcx, guar)
671 }
672 } else {
673 callee_tuple_type
675 }
676 } else {
677 self.structurally_resolve_type(call_span, formal_input_tys[first_tupled_arg_index])
678 };
679
680 let mut err_code = None;
683 if let ty::Tuple(detup_formal_arg_tys) = tuple_type.kind() {
684 if Some(detup_formal_arg_tys.len()) != tupled_args_count {
687 err_code = Some(E0057);
688 }
689 if let Some(ref mut expected_input_tys) = expected_input_tys
690 && let Some(ty) = expected_input_tys.get(first_tupled_arg_index)
691 && let ty::Tuple(detup_expected_arg_tys) = ty.kind()
692 {
693 let substitute_tys = if Some(detup_expected_arg_tys.len()) == tupled_args_count {
694 detup_expected_arg_tys.iter()
695 } else {
696 detup_formal_arg_tys.iter()
698 };
699
700 expected_input_tys
701 .splice(first_tupled_arg_index..=first_tupled_arg_index, substitute_tys);
702 } else {
703 expected_input_tys = None;
704 }
705 if tuple_arguments.is_splatted() {
707 self.write_splatted_call(
709 call_expr.hir_id,
710 call_span,
711 fn_def_id,
712 callee_generic_args,
713 first_tupled_arg_index.try_into().unwrap(),
714 tupled_args_count.unwrap().try_into().unwrap(),
715 );
716 }
717
718 formal_input_tys.splice(
719 first_tupled_arg_index..=first_tupled_arg_index,
720 detup_formal_arg_tys.iter(),
721 );
722 if let Some(ref expected_input_tys) = expected_input_tys {
723 {
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:?}",
tuple_arguments)));
}
}
}
}assert_eq!(
724 formal_input_tys.len(),
725 expected_input_tys.len(),
726 "incorrectly constructed input type tuples, argument counts must match: \
727 tuple_arguments: {tuple_arguments:?}",
728 )
729 }
730 }
731
732 let guar =
736 if tuple_arguments == TupleAllCallArgs && !#[allow(non_exhaustive_omitted_patterns)] match tuple_type.kind() {
ty::Tuple(_) => true,
_ => false,
}matches!(tuple_type.kind(), ty::Tuple(_)) {
737 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!(
738 self.dcx(),
739 call_span,
740 E0059,
741 "cannot use call notation; the first type parameter \
742 for the function trait is neither a tuple nor unit"
743 )
744 .emit();
745
746 Some(guar)
747 } else if tuple_arguments.is_splatted() {
748 if !#[allow(non_exhaustive_omitted_patterns)] match tuple_type.kind() {
ty::Tuple(_) => true,
_ => false,
}matches!(tuple_type.kind(), ty::Tuple(_)) {
751 let spans = if let Some(def_id) = fn_def_id
752 && let Some(hir_node) = self.tcx.hir_get_if_local(def_id)
753 && let Some(fn_decl) = hir_node.fn_decl()
754 && let Some(arg_ty) = fn_decl.inputs.get(first_tupled_arg_index)
755 {
756 let arg_def_span = arg_ty.span;
757 ::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]
758 } else {
759 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[call_span]))vec![call_span]
760 };
761 let guar = {
self.dcx().struct_span_err(spans,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot use 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]).kind()))
})).with_code(E0277)
}struct_span_code_err!(
762 self.dcx(),
763 spans,
764 E0277,
766 "cannot use splat attribute; the splatted argument type \
767 must be a tuple or unit, not a {:?} ({:?})",
768 tuple_type.kind(),
769 self.structurally_resolve_type(
770 call_span,
771 formal_input_tys[first_tupled_arg_index]
772 )
773 .kind(),
774 )
775 .emit();
776
777 Some(guar)
778 } else if formal_input_tys.len() != provided_args.len() {
779 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!(
781 self.dcx(),
782 call_span,
783 E0057,
784 "this splatted function takes {} arguments, but {} {} provided",
785 formal_input_tys.len(),
786 provided_args.len(),
787 if provided_args.len() == 1 { "was" } else { "were" },
788 )
789 .emit();
790
791 Some(guar)
792 } else {
793 None
794 }
795 } else {
796 None
797 };
798
799 if let Some(guar) = guar {
800 TupledArgCheckOutcome {
801 new_err_code: err_code,
802 untupled_formal_input_tys: self.err_args(provided_args.len(), guar),
803 untupled_expected_input_tys: None,
804 }
805 } else {
806 TupledArgCheckOutcome {
807 new_err_code: err_code,
808 untupled_formal_input_tys: formal_input_tys,
809 untupled_expected_input_tys: expected_input_tys,
810 }
811 }
812 }
813
814 fn check_place_expr_if_unsized(&self, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
820 if self.tcx.features().unsized_fn_params() && !expr.is_syntactic_place_expr() {
821 self.require_type_is_sized(
822 ty,
823 expr.span,
824 ObligationCauseCode::UnsizedNonPlaceExpr(expr.span),
825 );
826 }
827 }
828
829 fn report_arg_errors(
830 &self,
831 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
832 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
833 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
834 c_variadic: bool,
835 err_code: ErrCode,
836 fn_def_id: Option<DefId>,
837 call_span: Span,
838 call_expr: &'tcx hir::Expr<'tcx>,
839 tuple_arguments: TupleArgumentsFlag,
841 ) -> ErrorGuaranteed {
842 let mut fn_call_diag_ctxt = FnCallDiagCtxt::new(
845 self,
846 compatibility_diagonal,
847 formal_and_expected_inputs,
848 provided_args,
849 c_variadic,
850 err_code,
851 fn_def_id,
852 call_span,
853 call_expr,
854 tuple_arguments,
855 );
856
857 if let Some(err) = fn_call_diag_ctxt.check_wrap_args_in_tuple() {
859 return err;
860 }
861
862 if let Some(fallback_error) = fn_call_diag_ctxt.ensure_has_errors() {
863 return fallback_error;
864 }
865
866 if let Some(err) = fn_call_diag_ctxt.filter_out_invalid_arguments()
881 && fn_call_diag_ctxt.errors.is_empty()
882 {
883 return err;
885 }
886
887 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());
888
889 if let Some(err) = fn_call_diag_ctxt.check_single_incompatible() {
891 return err;
892 }
893
894 fn_call_diag_ctxt.maybe_optimize_extra_arg_suggestion();
903
904 let mut err = fn_call_diag_ctxt.initial_final_diagnostic();
905 fn_call_diag_ctxt.suggest_confusable(&mut err);
906
907 let (mut suggestions, labels, suggestion_text) =
910 fn_call_diag_ctxt.labels_and_suggestion_text(&mut err);
911
912 fn_call_diag_ctxt.label_generic_mismatches(&mut err);
913 fn_call_diag_ctxt.append_arguments_changes(&mut suggestions);
914
915 if labels.len() <= 5 {
917 for (span, label) in labels {
918 err.span_label(span, label);
919 }
920 }
921
922 fn_call_diag_ctxt.label_fn_like(
924 &mut err,
925 fn_def_id,
926 fn_call_diag_ctxt.callee_ty,
927 call_expr,
928 None,
929 None,
930 &fn_call_diag_ctxt.matched_inputs,
931 &fn_call_diag_ctxt.formal_and_expected_inputs,
932 fn_call_diag_ctxt.call_metadata.is_method,
933 tuple_arguments,
934 );
935
936 if let Some(suggestion_message) =
938 FnCallDiagCtxt::format_suggestion_text(&mut err, suggestions, suggestion_text)
939 && !fn_call_diag_ctxt.call_is_in_macro()
940 {
941 let (suggestion_span, suggestion_code) = fn_call_diag_ctxt.suggestion_code();
942
943 err.span_suggestion_verbose(
944 suggestion_span,
945 suggestion_message,
946 suggestion_code,
947 Applicability::HasPlaceholders,
948 );
949 }
950
951 err.emit()
952 }
953
954 fn suggest_ptr_null_mut(
955 &self,
956 expected_ty: Ty<'tcx>,
957 provided_ty: Ty<'tcx>,
958 arg: &hir::Expr<'tcx>,
959 err: &mut Diag<'_>,
960 ) {
961 if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
962 && let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()
963 && let hir::ExprKind::Call(callee, _) = arg.kind
964 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind
965 && let Res::Def(_, def_id) = path.res
966 && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id)
967 {
968 err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
971 }
972 }
973
974 pub(in super::super) fn check_expr_lit(
976 &self,
977 lit: &hir::Lit,
978 lint_id: HirId,
979 expected: Expectation<'tcx>,
980 ) -> Ty<'tcx> {
981 let tcx = self.tcx;
982
983 match lit.node {
984 ast::LitKind::Str(..) => Ty::new_static_str(tcx),
985 ast::LitKind::ByteStr(ref v, _) => Ty::new_imm_ref(
986 tcx,
987 tcx.lifetimes.re_static,
988 Ty::new_array(tcx, tcx.types.u8, v.as_byte_str().len() as u64),
989 ),
990 ast::LitKind::Byte(_) => tcx.types.u8,
991 ast::LitKind::Char(_) => tcx.types.char,
992 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, t),
993 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, t),
994 ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
995 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
996 ty::Int(_) | ty::Uint(_) => Some(ty),
997 ty::Char => Some(tcx.types.u8),
1001 ty::RawPtr(..) => Some(tcx.types.usize),
1002 ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1003 &ty::Pat(base, _) if base.is_integral() => {
1004 let layout = tcx
1005 .layout_of(self.typing_env(self.param_env).as_query_input(ty))
1006 .ok()?;
1007 if !!layout.uninhabited {
::core::panicking::panic("assertion failed: !layout.uninhabited")
};assert!(!layout.uninhabited);
1008
1009 match layout.backend_repr {
1010 rustc_abi::BackendRepr::Scalar(scalar) => {
1011 scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
1012 }
1013 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1014 }
1015 }
1016 _ => None,
1017 });
1018 opt_ty.unwrap_or_else(|| self.next_int_var())
1019 }
1020 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => Ty::new_float(tcx, t),
1021 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1022 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1023 ty::Float(_) => Some(ty),
1024 _ => None,
1025 });
1026 opt_ty.unwrap_or_else(|| self.next_float_var(lit.span, Some(lint_id)))
1027 }
1028 ast::LitKind::Bool(_) => tcx.types.bool,
1029 ast::LitKind::CStr(_, _) => Ty::new_imm_ref(
1030 tcx,
1031 tcx.lifetimes.re_static,
1032 tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, lit.span)).skip_binder(),
1033 ),
1034 ast::LitKind::Err(guar) => Ty::new_error(tcx, guar),
1035 }
1036 }
1037
1038 pub(crate) fn check_struct_path(
1039 &self,
1040 qpath: &QPath<'tcx>,
1041 hir_id: HirId,
1042 ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
1043 let path_span = qpath.span();
1044 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1045 let variant = match def {
1046 Res::Err => {
1047 let guar =
1048 self.dcx().span_delayed_bug(path_span, "`Res::Err` but no error emitted");
1049 self.set_tainted_by_errors(guar);
1050 return Err(guar);
1051 }
1052 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1053 Some(adt) => {
1054 Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
1055 }
1056 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type: {0:?}",
ty.normalized))bug!("unexpected type: {:?}", ty.normalized),
1057 },
1058 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1059 | Res::SelfTyParam { .. }
1060 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1061 Some(adt) if !adt.is_enum() => {
1062 Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
1063 }
1064 _ => None,
1065 },
1066 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected definition: {0:?}",
def))bug!("unexpected definition: {:?}", def),
1067 };
1068
1069 if let Some((variant, did, ty::UserArgs { args, user_self_ty })) = variant {
1070 {
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:1070",
"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(1070u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::checks"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("check_struct_path: did={0:?} args={1:?}",
did, args) as &dyn Value))])
});
} else { ; }
};debug!("check_struct_path: did={:?} args={:?}", did, args);
1071
1072 self.write_user_type_annotation_from_args(hir_id, did, args, user_self_ty);
1074
1075 self.add_required_obligations_for_hir(path_span, did, args, hir_id);
1077
1078 Ok((variant, ty.normalized))
1079 } else {
1080 Err(match *ty.normalized.kind() {
1081 ty::Error(guar) => {
1082 guar
1087 }
1088 _ => {
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!(
1089 self.dcx(),
1090 path_span,
1091 E0071,
1092 "expected struct, variant or union type, found {}",
1093 ty.normalized.sort_string(self.tcx)
1094 )
1095 .with_span_label(path_span, "not a struct")
1096 .emit(),
1097 })
1098 }
1099 }
1100
1101 fn check_decl_initializer(
1102 &self,
1103 hir_id: HirId,
1104 pat: &'tcx hir::Pat<'tcx>,
1105 init: &'tcx hir::Expr<'tcx>,
1106 ) -> Ty<'tcx> {
1107 let ref_bindings = pat.contains_explicit_ref_binding();
1112
1113 let local_ty = self.local_ty(init.span, hir_id);
1114 if let Some(m) = ref_bindings {
1115 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1124 if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
1125 self.emit_type_mismatch_suggestions(
1126 &mut diag,
1127 init.peel_drop_temps(),
1128 init_ty,
1129 local_ty,
1130 None,
1131 None,
1132 );
1133 diag.emit();
1134 }
1135 init_ty
1136 } else {
1137 self.check_expr_coercible_to_type(init, local_ty, None)
1138 }
1139 }
1140
1141 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
1142 let decl_ty = self.local_ty(decl.span, decl.hir_id);
1144
1145 if let Some(init) = decl.init {
1147 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
1148 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1149 }
1150
1151 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1153 (Some(ty), _) => (None, Some(ty.span)), (_, Some(init)) => {
1155 (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1156 } _ => (None, None), };
1159
1160 self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
1162 let pat_ty = self.node_ty(decl.pat.hir_id);
1163 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1164
1165 if let Some(blk) = decl.origin.try_get_else() {
1166 let previous_diverges = self.diverges.get();
1167 let else_ty = self.check_expr_block(blk, NoExpectation);
1168 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1169 if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1170 {
1171 err.emit();
1172 }
1173 self.diverges.set(previous_diverges);
1174 }
1175 decl_ty
1176 }
1177
1178 fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
1180 GatherLocalsVisitor::gather_from_local(self, local);
1181
1182 let ty = self.check_decl(local.into());
1183 self.write_ty(local.hir_id, ty);
1184 if local.pat.is_never_pattern() {
1185 self.diverges.set(Diverges::Always {
1186 span: local.pat.span,
1187 custom_note: Some("any code following a never pattern is unreachable"),
1188 });
1189 }
1190 }
1191
1192 fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
1193 match stmt.kind {
1195 hir::StmtKind::Item(..) => return,
1196 hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1197 }
1198
1199 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1200
1201 let old_diverges = self.diverges.replace(Diverges::Maybe);
1203
1204 match stmt.kind {
1205 hir::StmtKind::Let(l) => {
1206 self.check_decl_local(l);
1207 }
1208 hir::StmtKind::Item(_) => {}
1210 hir::StmtKind::Expr(expr) => {
1211 self.check_expr_has_type_or_error(expr, self.tcx.types.unit, |err| {
1213 if self.is_next_stmt_expr_continuation(stmt.hir_id)
1214 && let hir::ExprKind::Match(..) | hir::ExprKind::If(..) = expr.kind
1215 {
1216 err.subdiagnostic(ExprParenthesesNeeded::surrounding(expr.span));
1221 } else if expr.can_have_side_effects() {
1222 self.suggest_semicolon_at_end(expr.span, err);
1223 }
1224 });
1225 }
1226 hir::StmtKind::Semi(expr) => {
1227 let ty = self.check_expr(expr);
1228 self.check_place_expr_if_unsized(ty, expr);
1229 }
1230 }
1231
1232 self.diverges.set(self.diverges.get() | old_diverges);
1234 }
1235
1236 pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1237 let unit = self.tcx.types.unit;
1238 let ty = self.check_expr_block(blk, ExpectHasType(unit));
1239
1240 if !ty.is_never() {
1243 self.demand_suptype(blk.span, unit, ty);
1244 }
1245 }
1246
1247 pub(in super::super) fn check_expr_block(
1248 &self,
1249 blk: &'tcx hir::Block<'tcx>,
1250 expected: Expectation<'tcx>,
1251 ) -> Ty<'tcx> {
1252 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1269 let coerce = CoerceMany::new(coerce_to_ty);
1270
1271 let prev_diverges = self.diverges.get();
1272 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1273
1274 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1275 for s in blk.stmts {
1276 self.check_stmt(s);
1277 }
1278
1279 let tail_expr_ty =
1282 blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
1283
1284 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1285 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1286 let coerce = ctxt.coerce.as_mut().unwrap();
1287 if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
1288 let span = self.get_expr_coercion_span(tail_expr);
1289 let cause = self.cause(
1290 span,
1291 ObligationCauseCode::BlockTailExpression(blk.hir_id, hir::MatchSource::Normal),
1292 );
1293 let ty_for_diagnostic = coerce.merged_ty();
1294 coerce.coerce_inner(
1298 self,
1299 &cause,
1300 Some(tail_expr),
1301 tail_expr_ty,
1302 |diag| {
1303 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1304 },
1305 false,
1306 );
1307 } else {
1308 if !self.diverges.get().is_always()
1319 || #[allow(non_exhaustive_omitted_patterns)] match self.diverging_block_behavior
{
DivergingBlockBehavior::Unit => true,
_ => false,
}matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
1320 {
1321 let mut sp = blk.span;
1327 let mut fn_span = None;
1328 if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) {
1329 let ret_sp = decl.output.span();
1330 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1331 if block_sp == blk.span {
1335 sp = ret_sp;
1336 fn_span = self.tcx.def_ident_span(fn_def_id);
1337 }
1338 }
1339 }
1340 coerce.coerce_forced_unit(
1341 self,
1342 &self.misc(sp),
1343 |err| {
1344 if let Some(expected_ty) = expected.only_has_type(self) {
1345 if blk.stmts.is_empty() && blk.expr.is_none() {
1346 self.suggest_boxing_when_appropriate(
1347 err,
1348 blk.span,
1349 blk.hir_id,
1350 expected_ty,
1351 self.tcx.types.unit,
1352 );
1353 }
1354 if !self.err_ctxt().consider_removing_semicolon(
1355 blk,
1356 expected_ty,
1357 err,
1358 ) {
1359 self.err_ctxt().consider_returning_binding(
1360 blk,
1361 expected_ty,
1362 err,
1363 );
1364 }
1365 if expected_ty == self.tcx.types.bool {
1366 if let hir::Block {
1371 stmts:
1372 [
1373 hir::Stmt {
1374 kind:
1375 hir::StmtKind::Let(hir::LetStmt {
1376 source: hir::LocalSource::AssignDesugar,
1377 ..
1378 }),
1379 ..
1380 },
1381 hir::Stmt {
1382 kind:
1383 hir::StmtKind::Expr(hir::Expr {
1384 kind: hir::ExprKind::Assign(lhs, ..),
1385 ..
1386 }),
1387 ..
1388 },
1389 ],
1390 ..
1391 } = blk
1392 {
1393 self.comes_from_while_condition(blk.hir_id, |_| {
1394 let res = self.typeck_results.borrow().expr_ty_opt(lhs);
1398
1399 if !lhs.is_syntactic_place_expr()
1400 || res.references_error()
1401 {
1402 err.downgrade_to_delayed_bug();
1403 }
1404 })
1405 }
1406 }
1407 }
1408 if let Some(fn_span) = fn_span {
1409 err.span_label(
1410 fn_span,
1411 "implicitly returns `()` as its body has no tail or `return` \
1412 expression",
1413 );
1414 }
1415 },
1416 false,
1417 );
1418 }
1419 }
1420 });
1421
1422 if ctxt.may_break {
1423 self.diverges.set(prev_diverges);
1426 }
1427
1428 let ty = ctxt.coerce.unwrap().complete(self);
1429
1430 self.write_ty(blk.hir_id, ty);
1431
1432 ty
1433 }
1434
1435 fn parent_item_span(&self, id: HirId) -> Option<Span> {
1436 let node = self.tcx.hir_node_by_def_id(self.tcx.hir_get_parent_item(id).def_id);
1437 match node {
1438 Node::Item(&hir::Item { kind: hir::ItemKind::Fn { body: body_id, .. }, .. })
1439 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1440 let body = self.tcx.hir_body(body_id);
1441 if let ExprKind::Block(block, _) = &body.value.kind {
1442 return Some(block.span);
1443 }
1444 }
1445 _ => {}
1446 }
1447 None
1448 }
1449
1450 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1458 let check_in_progress = |elem: &hir::Expr<'_>| {
1459 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
1460 |_| match elem.kind {
1461 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
1463 _ => elem.span,
1464 },
1465 )
1466 };
1467
1468 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind
1469 && let Some(rslt) = check_in_progress(el)
1470 {
1471 return rslt;
1472 }
1473
1474 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1475 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1476 if let Some(span) = iter.next() {
1477 if iter.next().is_none() {
1478 return span;
1479 }
1480 }
1481 }
1482
1483 expr.span
1484 }
1485
1486 fn overwrite_local_ty_if_err(&self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>) {
1487 if let Err(guar) = ty.error_reported() {
1488 struct OverwritePatternsWithError {
1489 pat_hir_ids: Vec<hir::HirId>,
1490 }
1491 impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
1492 fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
1493 self.pat_hir_ids.push(p.hir_id);
1494 hir::intravisit::walk_pat(self, p);
1495 }
1496 }
1497 let err = Ty::new_error(self.tcx, guar);
1499 self.write_ty(hir_id, err);
1500 self.write_ty(pat.hir_id, err);
1501 let mut visitor = OverwritePatternsWithError { pat_hir_ids: ::alloc::vec::Vec::new()vec![] };
1502 hir::intravisit::walk_pat(&mut visitor, pat);
1503 for hir_id in visitor.pat_hir_ids {
1506 self.write_ty(hir_id, err);
1507 }
1508 self.locals.borrow_mut().insert(hir_id, err);
1509 self.locals.borrow_mut().insert(pat.hir_id, err);
1510 }
1511 }
1512
1513 fn finish_resolving_struct_path(
1516 &self,
1517 qpath: &QPath<'tcx>,
1518 path_span: Span,
1519 hir_id: HirId,
1520 ) -> (Res, LoweredTy<'tcx>) {
1521 let ResolvedStructPath { res: result, ty } =
1522 self.lowerer().lower_path_for_struct_expr(*qpath, path_span, hir_id);
1523 match *qpath {
1524 QPath::Resolved(_, path) => (path.res, LoweredTy::from_raw(self, path_span, ty)),
1525 QPath::TypeRelative(_, _) => {
1526 let ty = LoweredTy::from_raw(self, path_span, ty);
1527 let resolution =
1528 result.map(|res: Res| (self.tcx().def_kind(res.def_id()), res.def_id()));
1529
1530 self.write_resolution(hir_id, resolution);
1532
1533 (result.unwrap_or(Res::Err), ty)
1534 }
1535 }
1536 }
1537
1538 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
1545 &self,
1546 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1547 ) {
1548 let mut remap_cause = FxIndexSet::default();
1554 let mut not_adjusted = ::alloc::vec::Vec::new()vec![];
1555
1556 for error in errors {
1557 let before_span = error.obligation.cause.span;
1558 if self.adjust_fulfillment_error_for_expr_obligation(error)
1559 || before_span != error.obligation.cause.span
1560 {
1561 remap_cause.insert((
1562 before_span,
1563 error.obligation.predicate,
1564 error.obligation.cause.clone(),
1565 ));
1566 } else {
1567 not_adjusted.push(error);
1570 }
1571 }
1572
1573 for error in not_adjusted {
1581 for (span, predicate, cause) in &remap_cause {
1582 if *predicate == error.obligation.predicate
1583 && span.contains(error.obligation.cause.span)
1584 {
1585 error.obligation.cause = cause.clone();
1586 continue;
1587 }
1588 }
1589 }
1590 }
1591
1592 fn label_fn_like(
1593 &self,
1594 err: &mut Diag<'_>,
1595 callable_def_id: Option<DefId>,
1596 callee_ty: Option<Ty<'tcx>>,
1597 call_expr: &'tcx hir::Expr<'tcx>,
1598 expected_ty: Option<Ty<'tcx>>,
1599 expected_idx: Option<usize>,
1601 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1602 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1603 is_method: bool,
1604 tuple_arguments: TupleArgumentsFlag,
1605 ) {
1606 let Some(mut def_id) = callable_def_id else {
1607 return;
1608 };
1609
1610 if tuple_arguments == TupleAllCallArgs
1616 && let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1617 && let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
1622 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1623 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
1625 && let Some(callee_ty) = callee_ty
1626 {
1627 let callee_ty = callee_ty.peel_refs();
1628 match *callee_ty.kind() {
1629 ty::Param(param) => {
1630 let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
1631 if param.kind.is_synthetic() {
1632 def_id = param.def_id;
1634 } else {
1635 let instantiated = self
1638 .tcx
1639 .explicit_predicates_of(self.body_id)
1640 .instantiate_identity(self.tcx);
1641 for (predicate, span) in instantiated {
1645 if let ty::ClauseKind::Trait(pred) =
1646 predicate.skip_norm_wip().kind().skip_binder()
1647 && pred.self_ty().peel_refs() == callee_ty
1648 && self.tcx.is_fn_trait(pred.def_id())
1649 {
1650 err.span_note(span, "callable defined here");
1651 return;
1652 }
1653 }
1654 }
1655 }
1656 ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: new_def_id }, .. })
1657 | ty::Closure(new_def_id, _)
1658 | ty::FnDef(new_def_id, _) => {
1659 def_id = new_def_id;
1660 }
1661 _ => {
1662 let new_def_id = self.probe(|_| {
1664 let trait_ref = ty::TraitRef::new(
1665 self.tcx,
1666 self.tcx.fn_trait_kind_to_def_id(call_kind)?,
1667 [callee_ty, self.next_ty_var(DUMMY_SP)],
1668 );
1669 let obligation = traits::Obligation::new(
1670 self.tcx,
1671 traits::ObligationCause::dummy(),
1672 self.param_env,
1673 trait_ref,
1674 );
1675 match SelectionContext::new(self).select(&obligation) {
1676 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1677 Some(impl_source.impl_def_id)
1678 }
1679 _ => None,
1680 }
1681 });
1682 let Some(new_def_id) = new_def_id else { return };
1683 def_id = new_def_id;
1684 }
1685 }
1686 }
1687
1688 if let Some(def_span) = self.tcx.def_ident_span(def_id)
1689 && !def_span.is_dummy()
1690 {
1691 let mut spans: MultiSpan = def_span.into();
1692 if let Some((params_with_generics, hir_generics)) =
1693 self.get_hir_param_info(def_id, is_method)
1694 {
1695 struct MismatchedParam<'a> {
1696 idx: ExpectedIdx,
1697 generic: GenericIdx,
1698 param: &'a FnParam<'a>,
1699 deps: SmallVec<[ExpectedIdx; 4]>,
1700 }
1701
1702 if !tuple_arguments.is_splatted() {
1704 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());
1705 }
1706 let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
1708 let mut use_splat_fallback = false;
1709 if let Some(expected_idx) = expected_idx {
1710 let expected_idx = ExpectedIdx::from_usize(expected_idx);
1711 match params_with_generics.get(expected_idx) {
1712 Some(&(Some(expected_generic), ref expected_param)) => mismatched_params
1713 .push(MismatchedParam {
1714 idx: expected_idx,
1715 generic: expected_generic,
1716 param: expected_param,
1717 deps: SmallVec::new(),
1718 }),
1719 Some((None, expected_param)) => {
1720 spans.push_span_label(expected_param.span(), "");
1722 }
1723 None => {
1724 if tuple_arguments.is_splatted() {
1725 use_splat_fallback = true;
1727 } else {
1728 ::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!(
1729 self.tcx.def_span(def_id),
1730 "arg index {} out of bounds for method with {} inputs",
1731 expected_idx.as_usize(),
1732 params_with_generics.len(),
1733 );
1734 }
1735 }
1736 };
1737 }
1738
1739 if expected_idx.is_none() || use_splat_fallback {
1740 mismatched_params.extend(
1741 params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
1742 |((idx, &(generic, ref param)), matched_idx)| {
1743 if matched_idx.is_some() {
1744 None
1745 } else if let Some(generic) = generic {
1746 Some(MismatchedParam {
1747 idx,
1748 generic,
1749 param,
1750 deps: SmallVec::new(),
1751 })
1752 } else {
1753 spans.push_span_label(param.span(), "");
1755 None
1756 }
1757 },
1758 ),
1759 );
1760 }
1761
1762 if !mismatched_params.is_empty() {
1763 let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
1766 |_| SmallVec::<[u32; 4]>::new(),
1767 params_with_generics.len(),
1768 );
1769 let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
1770 |_| SmallVec::<[ExpectedIdx; 4]>::new(),
1771 hir_generics.params.len(),
1772 );
1773 for (idx, param) in mismatched_params.iter_mut().enumerate() {
1774 for ((other_idx, &(other_generic, _)), &other_matched_idx) in
1775 params_with_generics.iter_enumerated().zip(matched_inputs)
1776 {
1777 if other_generic == Some(param.generic) && other_matched_idx.is_some() {
1778 generic_uses[param.generic].extend([param.idx, other_idx]);
1779 dependants[other_idx].push(idx as u32);
1780 param.deps.push(other_idx);
1781 }
1782 }
1783 }
1784
1785 for param in &mismatched_params {
1788 if let Some(deps_list) = listify(¶m.deps, |&dep| {
1789 params_with_generics[dep].1.display(dep.as_usize()).to_string()
1790 }) {
1791 spans.push_span_label(
1792 param.param.span(),
1793 ::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!(
1794 "this parameter needs to match the {} type of {deps_list}",
1795 self.resolve_vars_if_possible(
1796 formal_and_expected_inputs[param.deps[0]].1
1797 )
1798 .sort_string(self.tcx),
1799 ),
1800 );
1801 } else {
1802 spans.push_span_label(param.param.span(), "");
1804 }
1805 }
1806 for ((&(_, param), deps), &(_, expected_ty)) in
1808 params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
1809 {
1810 if let Some(deps_list) = listify(deps, |&dep| {
1811 let param = &mismatched_params[dep as usize];
1812 param.param.display(param.idx.as_usize()).to_string()
1813 }) {
1814 spans.push_span_label(
1815 param.span(),
1816 ::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!(
1817 "{deps_list} need{} to match the {} type of this parameter",
1818 pluralize!((deps.len() != 1) as u32),
1819 self.resolve_vars_if_possible(expected_ty)
1820 .sort_string(self.tcx),
1821 ),
1822 );
1823 }
1824 }
1825 for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
1827 uses.sort();
1828 uses.dedup();
1829 if let Some(param_list) = listify(uses, |&idx| {
1830 params_with_generics[idx].1.display(idx.as_usize()).to_string()
1831 }) {
1832 spans.push_span_label(
1833 param.span,
1834 ::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!(
1835 "{param_list} {} reference this parameter `{}`",
1836 if uses.len() == 2 { "both" } else { "all" },
1837 param.name.ident().name,
1838 ),
1839 );
1840 }
1841 }
1842 }
1843 }
1844 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)));
1845 if let DefKind::Fn | DefKind::AssocFn = self.tcx.def_kind(def_id)
1846 && let ty::Param(_) =
1847 self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output().kind()
1848 && let parent = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id
1849 && let Some((output, body_id)) = match self.tcx.hir_node_by_def_id(parent) {
1850 hir::Node::Item(hir::Item {
1851 kind: hir::ItemKind::Fn { sig, body, .. },
1852 ..
1853 })
1854 | hir::Node::TraitItem(hir::TraitItem {
1855 kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body)),
1856 ..
1857 })
1858 | hir::Node::ImplItem(hir::ImplItem {
1859 kind: hir::ImplItemKind::Fn(sig, body),
1860 ..
1861 }) => Some((sig.decl.output, body)),
1862 _ => None,
1863 }
1864 && let expr = self.tcx.hir_body(*body_id).value
1865 && (expr.peel_blocks().span == call_expr.span
1866 || #[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!(
1867 self.tcx.parent_hir_node(call_expr.hir_id),
1868 hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
1869 ))
1870 {
1871 err.span_label(
1872 output.span(),
1873 match output {
1874 FnRetTy::DefaultReturn(_) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this implicit `()` return type influences the call expression\'s return type"))
})format!(
1875 "this implicit `()` return type influences the call expression's return type"
1876 ),
1877 FnRetTy::Return(_) => {
1878 "this return type influences the call expression's return type"
1879 .to_string()
1880 }
1881 },
1882 );
1883 }
1884 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir_get_if_local(def_id)
1885 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
1886 {
1887 let param = expected_idx
1888 .and_then(|expected_idx| self.tcx.hir_body(*body).params.get(expected_idx));
1889 let (kind, span) = if let Some(param) = param {
1890 let mut call_finder = FindClosureArg { tcx: self.tcx, calls: ::alloc::vec::Vec::new()vec![] };
1893 let parent_def_id = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id;
1894 match self.tcx.hir_node_by_def_id(parent_def_id) {
1895 hir::Node::Item(item) => call_finder.visit_item(item),
1896 hir::Node::TraitItem(item) => call_finder.visit_trait_item(item),
1897 hir::Node::ImplItem(item) => call_finder.visit_impl_item(item),
1898 _ => {}
1899 }
1900 let typeck = self.typeck_results.borrow();
1901 for (rcvr, args) in call_finder.calls {
1902 if rcvr.hir_id.owner == typeck.hir_owner
1903 && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id)
1904 && let ty::Closure(call_def_id, _) = rcvr_ty.kind()
1905 && def_id == *call_def_id
1906 && let Some(idx) = expected_idx
1907 && let Some(arg) = args.get(idx)
1908 && let Some(arg_ty) = typeck.node_type_opt(arg.hir_id)
1909 && let Some(expected_ty) = expected_ty
1910 && self.can_eq(self.param_env, arg_ty, expected_ty)
1911 {
1912 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();
1913 sp.push_span_label(
1914 arg.span,
1915 ::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}`"),
1916 );
1917 sp.push_span_label(rcvr.span, "in this closure call");
1918 err.span_note(
1919 sp,
1920 ::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!(
1921 "expected because the closure was earlier called with an \
1922 argument of type `{arg_ty}`",
1923 ),
1924 );
1925 break;
1926 }
1927 }
1928
1929 ("closure parameter", param.span)
1930 } else {
1931 ("closure", self.tcx.def_span(def_id))
1932 };
1933 err.span_note(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} defined here", kind))
})format!("{kind} defined here"));
1934 } else {
1935 err.span_note(
1936 self.tcx.def_span(def_id),
1937 ::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)),
1938 );
1939 }
1940 }
1941
1942 fn label_generic_mismatches(
1943 &self,
1944 err: &mut Diag<'_>,
1945 callable_def_id: Option<DefId>,
1946 matched_inputs: &IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
1947 provided_arg_tys: &IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
1948 formal_and_expected_inputs: &IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
1949 is_method: bool,
1950 is_splat: bool,
1951 ) {
1952 let Some(def_id) = callable_def_id else {
1953 return;
1954 };
1955
1956 if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
1957 if !is_splat {
1959 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());
1960 }
1961 for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
1962 if matched_inputs.get(idx).flatten_ref().is_none() {
1963 continue;
1964 }
1965
1966 let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
1967 else {
1968 continue;
1969 };
1970
1971 let Some(generic_param) = generic_param else {
1972 continue;
1973 };
1974
1975 let idxs_matched = params_with_generics
1976 .iter_enumerated()
1977 .filter(|&(other_idx, (other_generic_param, _))| {
1978 if other_idx == idx {
1979 return false;
1980 }
1981 let Some(other_generic_param) = other_generic_param else {
1982 return false;
1983 };
1984 if matched_inputs.get(other_idx).flatten_ref().is_some() {
1985 return false;
1986 }
1987 other_generic_param == generic_param
1988 })
1989 .count();
1990
1991 if idxs_matched == 0 {
1992 continue;
1993 }
1994
1995 let expected_display_type = self
1996 .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
1997 .sort_string(self.tcx);
1998 let label = if idxs_matched == params_with_generics.len() - 1 {
1999 ::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!(
2000 "expected all arguments to be this {} type because they need to match the type of this parameter",
2001 expected_display_type
2002 )
2003 } else {
2004 ::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!(
2005 "expected some other arguments to be {} {} type to match the type of this parameter",
2006 a_or_an(&expected_display_type),
2007 expected_display_type,
2008 )
2009 };
2010
2011 err.span_label(*matched_arg_span, label);
2012 }
2013 }
2014 }
2015
2016 fn get_hir_param_info(
2021 &self,
2022 def_id: DefId,
2023 is_method: bool,
2024 ) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
2025 {
2026 let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? {
2027 hir::Node::TraitItem(&hir::TraitItem {
2028 generics,
2029 kind: hir::TraitItemKind::Fn(sig, trait_fn),
2030 ..
2031 }) => match trait_fn {
2032 hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
2033 hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
2034 },
2035 hir::Node::ImplItem(&hir::ImplItem {
2036 generics,
2037 kind: hir::ImplItemKind::Fn(sig, body),
2038 ..
2039 })
2040 | hir::Node::Item(&hir::Item {
2041 kind: hir::ItemKind::Fn { sig, generics, body, .. },
2042 ..
2043 }) => (sig, generics, Some(body), None),
2044 hir::Node::ForeignItem(&hir::ForeignItem {
2045 kind: hir::ForeignItemKind::Fn(sig, params, generics),
2046 ..
2047 }) => (sig, generics, None, Some(params)),
2048 _ => return None,
2049 };
2050
2051 let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
2054 if let hir::TyKind::Path(QPath::Resolved(
2055 _,
2056 &hir::Path { res: Res::Def(_, res_def_id), .. },
2057 )) = param.kind
2058 {
2059 generics
2060 .params
2061 .iter()
2062 .position(|param| param.def_id.to_def_id() == res_def_id)
2063 .map(GenericIdx::from_usize)
2064 } else {
2065 None
2066 }
2067 });
2068 match (body_id, params) {
2069 (Some(_), Some(_)) | (None, None) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2070 (Some(body), None) => {
2071 let params = self.tcx.hir_body(body).params;
2072 let params = params
2073 .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
2074 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());
2075 Some((fn_inputs.zip(params.iter().map(FnParam::Param)).collect(), generics))
2076 }
2077 (None, Some(params)) => {
2078 let params = params
2079 .get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
2080 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());
2081 Some((
2082 fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
2083 generics,
2084 ))
2085 }
2086 }
2087 }
2088}
2089
2090struct FindClosureArg<'tcx> {
2091 tcx: TyCtxt<'tcx>,
2092 calls: Vec<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
2093}
2094
2095impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
2096 type NestedFilter = rustc_middle::hir::nested_filter::All;
2097
2098 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
2099 self.tcx
2100 }
2101
2102 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
2103 if let hir::ExprKind::Call(rcvr, args) = ex.kind {
2104 self.calls.push((rcvr, args));
2105 }
2106 hir::intravisit::walk_expr(self, ex);
2107 }
2108}
2109
2110#[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)]
2111enum FnParam<'hir> {
2112 Param(&'hir hir::Param<'hir>),
2113 Ident(Option<Ident>),
2114}
2115
2116impl FnParam<'_> {
2117 fn span(&self) -> Span {
2118 match self {
2119 Self::Param(param) => param.span,
2120 Self::Ident(ident) => {
2121 if let Some(ident) = ident {
2122 ident.span
2123 } else {
2124 DUMMY_SP
2125 }
2126 }
2127 }
2128 }
2129
2130 fn display(&self, idx: usize) -> impl '_ + fmt::Display {
2131 struct D<'a>(FnParam<'a>, usize);
2132 impl fmt::Display for D<'_> {
2133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2134 let unique_name = match self.0 {
2137 FnParam::Param(param)
2138 if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind =>
2139 {
2140 Some(ident.name)
2141 }
2142 FnParam::Ident(ident)
2143 if let Some(ident) = ident
2144 && ident.name != kw::Underscore =>
2145 {
2146 Some(ident.name)
2147 }
2148 _ => None,
2149 };
2150 if let Some(unique_name) = unique_name {
2151 f.write_fmt(format_args!("`{0}`", unique_name))write!(f, "`{unique_name}`")
2152 } else {
2153 f.write_fmt(format_args!("parameter #{0}", self.1 + 1))write!(f, "parameter #{}", self.1 + 1)
2154 }
2155 }
2156 }
2157 D(*self, idx)
2158 }
2159}
2160
2161struct FnCallDiagCtxt<'a, 'tcx> {
2162 arg_matching_ctxt: ArgMatchingCtxt<'a, 'tcx>,
2163 errors: Vec<Error<'tcx>>,
2164 matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
2165}
2166
2167impl<'a, 'tcx> Deref for FnCallDiagCtxt<'a, 'tcx> {
2168 type Target = ArgMatchingCtxt<'a, 'tcx>;
2169
2170 fn deref(&self) -> &Self::Target {
2171 &self.arg_matching_ctxt
2172 }
2173}
2174
2175enum ArgumentsFormatting {
2177 SingleLine,
2178 Multiline { fallback_indent: String, brace_indent: String },
2179}
2180
2181impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> {
2182 fn new(
2183 arg: &'a FnCtxt<'a, 'tcx>,
2184 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
2185 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
2186 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
2187 c_variadic: bool,
2188 err_code: ErrCode,
2189 fn_def_id: Option<DefId>,
2190 call_span: Span,
2191 call_expr: &'tcx Expr<'tcx>,
2192 tuple_arguments: TupleArgumentsFlag,
2193 ) -> Self {
2194 let arg_matching_ctxt = ArgMatchingCtxt::new(
2195 arg,
2196 compatibility_diagonal,
2197 formal_and_expected_inputs,
2198 provided_args,
2199 c_variadic,
2200 err_code,
2201 fn_def_id,
2202 call_span,
2203 call_expr,
2204 tuple_arguments,
2205 );
2206
2207 let (errors, matched_inputs) = ArgMatrix::new(
2214 arg_matching_ctxt.provided_args.len(),
2215 arg_matching_ctxt.formal_and_expected_inputs.len(),
2216 |provided, expected| arg_matching_ctxt.check_compatible(provided, expected),
2217 )
2218 .find_errors();
2219
2220 FnCallDiagCtxt { arg_matching_ctxt, errors, matched_inputs }
2221 }
2222
2223 fn check_wrap_args_in_tuple(&self) -> Option<ErrorGuaranteed> {
2224 if let Some((mismatch_idx, terr)) = self.first_incompatible_error() {
2225 if let Some(ty::Tuple(tys)) =
2229 self.formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
2230 && !tys.is_empty()
2232 && self.provided_arg_tys.len() == self.formal_and_expected_inputs.len() - 1 + tys.len()
2233 {
2234 let provided_args_to_tuple = &self.provided_arg_tys[mismatch_idx..];
2236 let (provided_args_to_tuple, provided_args_after_tuple) =
2237 provided_args_to_tuple.split_at(tys.len());
2238 let provided_as_tuple = Ty::new_tup_from_iter(
2239 self.tcx,
2240 provided_args_to_tuple.iter().map(|&(ty, _)| ty),
2241 );
2242
2243 let mut satisfied = true;
2244 for ((_, expected_ty), provided_ty) in std::iter::zip(
2246 self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
2247 [provided_as_tuple]
2248 .into_iter()
2249 .chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
2250 ) {
2251 if !self.may_coerce(provided_ty, *expected_ty) {
2252 satisfied = false;
2253 break;
2254 }
2255 }
2256
2257 if satisfied
2261 && let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
2262 {
2263 let mut err;
2264 if tys.len() == 1 {
2265 err = self.err_ctxt().report_and_explain_type_error(
2268 self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2269 lo,
2270 self.formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
2271 self.provided_arg_tys[mismatch_idx].0,
2272 ),
2273 self.param_env,
2274 terr,
2275 );
2276 let call_name = self.call_metadata.call_name;
2277 err.span_label(
2278 self.call_metadata.full_call_span,
2279 ::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"),
2280 );
2281 } else {
2282 let call_name = self.call_metadata.call_name;
2283 err = self.dcx().struct_span_err(
2284 self.arg_matching_ctxt.args_ctxt.call_metadata.full_call_span,
2285 ::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!(
2286 "{call_name} takes {}{} but {} {} supplied",
2287 if self.arg_matching_ctxt.args_ctxt.c_variadic {
2288 "at least "
2289 } else {
2290 ""
2291 },
2292 potentially_plural_count(
2293 self.formal_and_expected_inputs.len(),
2294 "argument"
2295 ),
2296 potentially_plural_count(self.provided_args.len(), "argument"),
2297 pluralize!("was", self.provided_args.len())
2298 ),
2299 );
2300 err.code(self.err_code.to_owned());
2301 err.multipart_suggestion(
2302 "wrap these arguments in parentheses to construct a tuple",
2303 ::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![
2304 (lo.shrink_to_lo(), "(".to_string()),
2305 (hi.shrink_to_hi(), ")".to_string()),
2306 ],
2307 Applicability::MachineApplicable,
2308 );
2309 };
2310 self.arg_matching_ctxt.args_ctxt.call_ctxt.fn_ctxt.label_fn_like(
2311 &mut err,
2312 self.fn_def_id,
2313 self.callee_ty,
2314 self.call_expr,
2315 None,
2316 Some(mismatch_idx.as_usize()),
2317 &self.matched_inputs,
2318 &self.formal_and_expected_inputs,
2319 self.call_metadata.is_method,
2320 self.tuple_arguments,
2321 );
2322 self.suggest_confusable(&mut err);
2323 Some(err.emit())
2324 } else {
2325 None
2326 }
2327 } else {
2328 None
2329 }
2330 } else {
2331 None
2332 }
2333 }
2334
2335 fn ensure_has_errors(&self) -> Option<ErrorGuaranteed> {
2336 if self.errors.is_empty() {
2337 if truecfg!(debug_assertions) {
2338 ::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");
2339 } else {
2340 let mut err = self.dcx().create_err(diagnostics::ArgMismatchIndeterminate {
2341 span: self.call_metadata.error_span,
2342 });
2343 self.arg_matching_ctxt.suggest_confusable(&mut err);
2344 return Some(err.emit());
2345 }
2346 }
2347
2348 None
2349 }
2350
2351 fn detect_dotdot(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, expr: &hir::Expr<'tcx>) {
2352 if let ty::Adt(adt, _) = ty.kind()
2353 && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
2354 && is_range_literal(expr)
2355 && let hir::ExprKind::Struct(&path, [], _) = expr.kind
2356 && self.tcx().qpath_is_lang_item(path, hir::LangItem::RangeFull)
2357 {
2358 let explanation = if self.tcx.features().default_field_values() {
2361 "this is only supported on non-tuple struct literals"
2362 } else if self.tcx.sess.is_nightly_build() {
2363 "this is only supported on non-tuple struct literals when \
2364 `#![feature(default_field_values)]` is enabled"
2365 } else {
2366 "this is not supported"
2367 };
2368 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!(
2369 "you might have meant to use `..` to skip providing a value for \
2370 expected fields, but {explanation}; it is instead interpreted as a \
2371 `std::ops::RangeFull` literal",
2372 );
2373 err.span_help(expr.span, msg);
2374 }
2375 }
2376
2377 fn filter_out_invalid_arguments(&mut self) -> Option<ErrorGuaranteed> {
2378 let mut reported = None;
2379
2380 self.errors.retain(|error| {
2381 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) =
2382 error
2383 else {
2384 return true;
2385 };
2386 let (provided_ty, provided_span) =
2387 self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2388 let trace = self.arg_matching_ctxt.mk_trace(
2389 provided_span,
2390 self.arg_matching_ctxt.formal_and_expected_inputs[*expected_idx],
2391 provided_ty,
2392 );
2393 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) {
2394 let mut err = self.arg_matching_ctxt.err_ctxt().report_and_explain_type_error(
2395 trace,
2396 self.arg_matching_ctxt.param_env,
2397 *e,
2398 );
2399 self.arg_matching_ctxt.suggest_confusable(&mut err);
2400 reported = Some(err.emit());
2401 return false;
2402 }
2403 true
2404 });
2405
2406 reported
2407 }
2408
2409 fn check_single_incompatible(&self) -> Option<ErrorGuaranteed> {
2410 if let &[
2411 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
2412 ] = &self.errors[..]
2413 {
2414 let (formal_ty, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2415 let (provided_ty, provided_arg_span) = self.provided_arg_tys[provided_idx];
2416 let trace = self.mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
2417 let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
2418 self.emit_coerce_suggestions(
2419 &mut err,
2420 self.provided_args[provided_idx],
2421 provided_ty,
2422 Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2423 .only_has_type(self.fn_ctxt)
2424 .unwrap_or(formal_ty),
2425 None,
2426 None,
2427 );
2428 let call_name = self.call_metadata.call_name;
2429 err.span_label(
2430 self.call_metadata.full_call_span,
2431 ::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"),
2432 );
2433
2434 self.label_generic_mismatches(&mut err);
2435
2436 if let hir::ExprKind::MethodCall(_, rcvr, _, _) =
2437 self.arg_matching_ctxt.args_ctxt.call_ctxt.call_expr.kind
2438 && provided_idx.as_usize() == expected_idx.as_usize()
2439 {
2440 self.note_source_of_type_mismatch_constraint(
2441 &mut err,
2442 rcvr,
2443 crate::demand::TypeMismatchSource::Arg {
2444 call_expr: self.call_expr,
2445 incompatible_arg: provided_idx.as_usize(),
2446 },
2447 );
2448 }
2449
2450 self.suggest_ptr_null_mut(
2451 expected_ty,
2452 provided_ty,
2453 self.provided_args[provided_idx],
2454 &mut err,
2455 );
2456
2457 self.suggest_deref_unwrap_or(
2458 &mut err,
2459 self.callee_ty,
2460 self.call_metadata.call_ident,
2461 expected_ty,
2462 provided_ty,
2463 self.provided_args[provided_idx],
2464 self.call_metadata.is_method,
2465 );
2466
2467 self.label_fn_like(
2469 &mut err,
2470 self.fn_def_id,
2471 self.callee_ty,
2472 self.call_expr,
2473 Some(expected_ty),
2474 Some(expected_idx.as_usize()),
2475 &self.matched_inputs,
2476 &self.formal_and_expected_inputs,
2477 self.call_metadata.is_method,
2478 self.tuple_arguments,
2479 );
2480 self.arg_matching_ctxt.suggest_confusable(&mut err);
2481 self.detect_dotdot(&mut err, provided_ty, self.provided_args[provided_idx]);
2482 return Some(err.emit());
2483 }
2484
2485 None
2486 }
2487
2488 fn maybe_optimize_extra_arg_suggestion(&mut self) {
2489 if let [Error::Extra(provided_idx)] = &self.errors[..] {
2490 if !self.remove_idx_is_perfect(provided_idx.as_usize()) {
2491 if let Some(i) = (0..self.args_ctxt.call_ctxt.provided_args.len())
2492 .find(|&i| self.remove_idx_is_perfect(i))
2493 {
2494 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))];
2495 }
2496 }
2497 }
2498 }
2499
2500 fn initial_final_diagnostic(&self) -> Diag<'_> {
2501 if self.formal_and_expected_inputs.len() == self.provided_args.len() {
2502 {
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!(
2503 self.dcx(),
2504 self.call_metadata.full_call_span,
2505 E0308,
2506 "arguments to this {} are incorrect",
2507 self.call_metadata.call_name,
2508 )
2509 } else {
2510 self.arg_matching_ctxt
2511 .dcx()
2512 .struct_span_err(
2513 self.call_metadata.full_call_span,
2514 ::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!(
2515 "this {} takes {}{} but {} {} supplied",
2516 self.call_metadata.call_name,
2517 if self.arg_matching_ctxt.args_ctxt.c_variadic { "at least " } else { "" },
2518 potentially_plural_count(self.formal_and_expected_inputs.len(), "argument"),
2519 potentially_plural_count(self.provided_args.len(), "argument"),
2520 pluralize!("was", self.provided_args.len())
2521 ),
2522 )
2523 .with_code(self.err_code.to_owned())
2524 }
2525 }
2526
2527 fn labels_and_suggestion_text(
2528 &self,
2529 err: &mut Diag<'_>,
2530 ) -> (Vec<(Span, String)>, Vec<(Span, String)>, SuggestionText) {
2531 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
2533 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
2534 }
2535
2536 let mut labels = Vec::new();
2537 let mut suggestion_text = SuggestionText::None;
2538
2539 let mut errors = self.errors.iter().peekable();
2540 let mut only_extras_so_far = errors
2541 .peek()
2542 .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));
2543 let mut prev_extra_idx = None;
2544 let mut suggestions = ::alloc::vec::Vec::new()vec![];
2545 while let Some(error) = errors.next() {
2546 only_extras_so_far &= #[allow(non_exhaustive_omitted_patterns)] match error {
Error::Extra(_) => true,
_ => false,
}matches!(error, Error::Extra(_));
2547
2548 match error {
2549 Error::Invalid(provided_idx, expected_idx, compatibility) => {
2550 let (formal_ty, expected_ty) =
2551 self.arg_matching_ctxt.args_ctxt.call_ctxt.formal_and_expected_inputs
2552 [*expected_idx];
2553 let (provided_ty, provided_span) =
2554 self.arg_matching_ctxt.provided_arg_tys[*provided_idx];
2555 if let Compatibility::Incompatible(error) = compatibility {
2556 let trace = self.arg_matching_ctxt.args_ctxt.call_ctxt.mk_trace(
2557 provided_span,
2558 (formal_ty, expected_ty),
2559 provided_ty,
2560 );
2561 if let Some(e) = error {
2562 self.err_ctxt().note_type_err(
2563 err,
2564 &trace.cause,
2565 None,
2566 Some(self.param_env.and(trace.values)),
2567 *e,
2568 true,
2569 None,
2570 );
2571 }
2572 }
2573
2574 self.emit_coerce_suggestions(
2575 err,
2576 self.provided_args[*provided_idx],
2577 provided_ty,
2578 Expectation::rvalue_hint(self.fn_ctxt, expected_ty)
2579 .only_has_type(self.fn_ctxt)
2580 .unwrap_or(formal_ty),
2581 None,
2582 None,
2583 );
2584 self.detect_dotdot(err, provided_ty, self.provided_args[*provided_idx]);
2585 }
2586 Error::Extra(arg_idx) => {
2587 let (provided_ty, provided_span) = self.provided_arg_tys[*arg_idx];
2588 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2589 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" of type `{0}`", provided_ty))
})format!(" of type `{provided_ty}`")
2591 } else {
2592 "".to_string()
2593 };
2594 let idx = if self.provided_arg_tys.len() == 1 {
2595 "".to_string()
2596 } else {
2597 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" #{0}", arg_idx.as_usize() + 1))
})format!(" #{}", arg_idx.as_usize() + 1)
2598 };
2599 labels.push((
2600 provided_span,
2601 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected argument{0}{1}", idx,
provided_ty_name))
})format!("unexpected argument{idx}{provided_ty_name}"),
2602 ));
2603 if self.provided_arg_tys.len() == 1
2604 && let Some(span) = self.maybe_suggest_expect_for_unwrap(provided_ty)
2605 {
2606 err.span_suggestion_verbose(
2607 span,
2608 "did you mean to use `expect`?",
2609 "expect",
2610 Applicability::MaybeIncorrect,
2611 );
2612 continue;
2613 }
2614 let mut span = provided_span;
2615 if span.can_be_used_for_suggestions()
2616 && self.call_metadata.error_span.can_be_used_for_suggestions()
2617 {
2618 if arg_idx.index() > 0
2619 && let Some((_, prev)) = self
2620 .provided_arg_tys
2621 .get(ProvidedIdx::from_usize(arg_idx.index() - 1))
2622 {
2623 span = prev.shrink_to_hi().to(span);
2625 }
2626
2627 let trim_next_comma = match errors.peek() {
2634 Some(Error::Extra(provided_idx))
2635 if only_extras_so_far
2636 && provided_idx.index() > arg_idx.index() + 1 =>
2637 {
2645 prev_extra_idx.is_none_or(|prev_extra_idx| {
2646 prev_extra_idx + 1 == arg_idx.index()
2647 })
2648 }
2649 None if only_extras_so_far => true,
2651 _ => false,
2653 };
2654
2655 if trim_next_comma {
2656 let next = self
2657 .provided_arg_tys
2658 .get(*arg_idx + 1)
2659 .map(|&(_, sp)| sp)
2660 .unwrap_or_else(|| {
2661 self.arg_matching_ctxt
2666 .tcx()
2667 .sess
2668 .source_map()
2669 .end_point(self.call_expr.span)
2670 });
2671
2672 span = span.until(next);
2674 }
2675
2676 suggestions.push((span, String::new()));
2677
2678 suggestion_text = match suggestion_text {
2679 SuggestionText::None => SuggestionText::Remove(false),
2680 SuggestionText::Remove(_) => SuggestionText::Remove(true),
2681 _ => SuggestionText::DidYouMean,
2682 };
2683 prev_extra_idx = Some(arg_idx.index())
2684 }
2685 self.detect_dotdot(err, provided_ty, self.provided_args[*arg_idx]);
2686 }
2687 Error::Missing(expected_idx) => {
2688 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];
2692 while let Some(e) = errors.next_if(|e| {
2693 #[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)
2694 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
2695 }) {
2696 match e {
2697 Error::Missing(expected_idx) => missing_idxs.push(*expected_idx),
2698 _ => {
::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!(
2699 "control flow ensures that we should always get an `Error::Missing`"
2700 ),
2701 }
2702 }
2703
2704 match &missing_idxs[..] {
2709 &[expected_idx] => {
2710 let (_, input_ty) = self.formal_and_expected_inputs[expected_idx];
2711 let span = if let Some((_, arg_span)) =
2712 self.provided_arg_tys.get(expected_idx.to_provided_idx())
2713 {
2714 *arg_span
2715 } else {
2716 self.args_span
2717 };
2718 let rendered = if !has_error_or_infer([input_ty]) {
2719 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" of type `{0}`", input_ty))
})format!(" of type `{input_ty}`")
2720 } else {
2721 "".to_string()
2722 };
2723 labels.push((
2724 span,
2725 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("argument #{0}{1} is missing",
expected_idx.as_usize() + 1, rendered))
})format!(
2726 "argument #{}{rendered} is missing",
2727 expected_idx.as_usize() + 1
2728 ),
2729 ));
2730
2731 suggestion_text = match suggestion_text {
2732 SuggestionText::None => SuggestionText::Provide(false),
2733 SuggestionText::Provide(_) => SuggestionText::Provide(true),
2734 _ => SuggestionText::DidYouMean,
2735 };
2736 }
2737 &[first_idx, second_idx] => {
2738 let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2739 let (_, second_expected_ty) =
2740 self.formal_and_expected_inputs[second_idx];
2741 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
2742 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2743 self.provided_arg_tys.get(second_idx.to_provided_idx()),
2744 ) {
2745 first_span.to(*second_span)
2746 } else {
2747 self.args_span
2748 };
2749 let rendered =
2750 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
2751 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" of type `{0}` and `{1}`",
first_expected_ty, second_expected_ty))
})format!(
2752 " of type `{first_expected_ty}` and `{second_expected_ty}`"
2753 )
2754 } else {
2755 "".to_string()
2756 };
2757 labels.push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("two arguments{0} are missing",
rendered))
})format!("two arguments{rendered} are missing")));
2758 suggestion_text = match suggestion_text {
2759 SuggestionText::None | SuggestionText::Provide(_) => {
2760 SuggestionText::Provide(true)
2761 }
2762 _ => SuggestionText::DidYouMean,
2763 };
2764 }
2765 &[first_idx, second_idx, third_idx] => {
2766 let (_, first_expected_ty) = self.formal_and_expected_inputs[first_idx];
2767 let (_, second_expected_ty) =
2768 self.formal_and_expected_inputs[second_idx];
2769 let (_, third_expected_ty) = self.formal_and_expected_inputs[third_idx];
2770 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
2771 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2772 self.provided_arg_tys.get(third_idx.to_provided_idx()),
2773 ) {
2774 first_span.to(*third_span)
2775 } else {
2776 self.args_span
2777 };
2778 let rendered = if !has_error_or_infer([
2779 first_expected_ty,
2780 second_expected_ty,
2781 third_expected_ty,
2782 ]) {
2783 ::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!(
2784 " of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
2785 )
2786 } else {
2787 "".to_string()
2788 };
2789 labels.push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("three arguments{0} are missing",
rendered))
})format!("three arguments{rendered} are missing")));
2790 suggestion_text = match suggestion_text {
2791 SuggestionText::None | SuggestionText::Provide(_) => {
2792 SuggestionText::Provide(true)
2793 }
2794 _ => SuggestionText::DidYouMean,
2795 };
2796 }
2797 missing_idxs => {
2798 let first_idx = *missing_idxs.first().unwrap();
2799 let last_idx = *missing_idxs.last().unwrap();
2800 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
2804 self.provided_arg_tys.get(first_idx.to_provided_idx()),
2805 self.provided_arg_tys.get(last_idx.to_provided_idx()),
2806 ) {
2807 first_span.to(*last_span)
2808 } else {
2809 self.args_span
2810 };
2811 labels.push((span, "multiple arguments are missing".to_string()));
2812 suggestion_text = match suggestion_text {
2813 SuggestionText::None | SuggestionText::Provide(_) => {
2814 SuggestionText::Provide(true)
2815 }
2816 _ => SuggestionText::DidYouMean,
2817 };
2818 }
2819 }
2820 }
2821 Error::Swap(
2822 first_provided_idx,
2823 second_provided_idx,
2824 first_expected_idx,
2825 second_expected_idx,
2826 ) => {
2827 let (first_provided_ty, first_span) =
2828 self.provided_arg_tys[*first_provided_idx];
2829 let (_, first_expected_ty) =
2830 self.formal_and_expected_inputs[*first_expected_idx];
2831 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
2832 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", found `{0}`", first_provided_ty))
})format!(", found `{first_provided_ty}`")
2833 } else {
2834 String::new()
2835 };
2836 labels.push((
2837 first_span,
2838 ::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}"),
2839 ));
2840
2841 let (second_provided_ty, second_span) =
2842 self.provided_arg_tys[*second_provided_idx];
2843 let (_, second_expected_ty) =
2844 self.formal_and_expected_inputs[*second_expected_idx];
2845 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
2846 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", found `{0}`",
second_provided_ty))
})format!(", found `{second_provided_ty}`")
2847 } else {
2848 String::new()
2849 };
2850 labels.push((
2851 second_span,
2852 ::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}"),
2853 ));
2854
2855 suggestion_text = match suggestion_text {
2856 SuggestionText::None => SuggestionText::Swap,
2857 _ => SuggestionText::DidYouMean,
2858 };
2859 }
2860 Error::Permutation(args) => {
2861 for (dst_arg, dest_input) in args {
2862 let (_, expected_ty) = self.formal_and_expected_inputs[*dst_arg];
2863 let (provided_ty, provided_span) = self.provided_arg_tys[*dest_input];
2864 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
2865 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", found `{0}`", provided_ty))
})format!(", found `{provided_ty}`")
2866 } else {
2867 String::new()
2868 };
2869 labels.push((
2870 provided_span,
2871 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected `{0}`{1}", expected_ty,
provided_ty_name))
})format!("expected `{expected_ty}`{provided_ty_name}"),
2872 ));
2873 }
2874
2875 suggestion_text = match suggestion_text {
2876 SuggestionText::None => SuggestionText::Reorder,
2877 _ => SuggestionText::DidYouMean,
2878 };
2879 }
2880 }
2881 }
2882
2883 (suggestions, labels, suggestion_text)
2884 }
2885
2886 fn label_generic_mismatches(&self, err: &mut Diag<'a>) {
2887 self.fn_ctxt.label_generic_mismatches(
2888 err,
2889 self.fn_def_id,
2890 &self.matched_inputs,
2891 &self.provided_arg_tys,
2892 &self.formal_and_expected_inputs,
2893 self.call_metadata.is_method,
2894 self.arg_matching_ctxt.tuple_arguments.is_splatted(),
2895 );
2896 }
2897
2898 fn append_arguments_changes(&self, suggestions: &mut Vec<(Span, String)>) {
2907 let mut prev = -1;
2922 for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
2923 if let Some(provided_idx) = provided_idx {
2926 prev = provided_idx.index() as i64;
2927 continue;
2928 }
2929 let idx = ProvidedIdx::from_usize((prev + 1) as usize);
2930 if let Some((_, arg_span)) = self.provided_arg_tys.get(idx) {
2931 prev += 1;
2932 let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
2937 let dominated = suggestions
2941 .iter()
2942 .any(|(span, _)| span.contains(*arg_span) || arg_span.overlaps(*span));
2943 if !dominated {
2944 suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
2945 }
2946 }
2947 }
2948 }
2949
2950 fn format_suggestion_text(
2951 err: &mut Diag<'_>,
2952 suggestions: Vec<(Span, String)>,
2953 suggestion_text: SuggestionText,
2954 ) -> Option<String> {
2955 match suggestion_text {
2956 SuggestionText::None => None,
2957 SuggestionText::Provide(plural) => {
2958 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 { "" }))
2959 }
2960 SuggestionText::Remove(plural) => {
2961 err.multipart_suggestion(
2962 ::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 { "" }),
2963 suggestions,
2964 Applicability::HasPlaceholders,
2965 );
2966 None
2967 }
2968 SuggestionText::Swap => Some("swap these arguments".to_string()),
2969 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
2970 SuggestionText::DidYouMean => Some("did you mean".to_string()),
2971 }
2972 }
2973
2974 fn arguments_formatting(&self, suggestion_span: Span) -> ArgumentsFormatting {
2975 let source_map = self.sess().source_map();
2976 let mut provided_inputs = self.matched_inputs.iter().filter_map(|a| *a);
2977 if let Some(brace_indent) = source_map.indentation_before(suggestion_span)
2978 && let Some(first_idx) = provided_inputs.by_ref().next()
2979 && let Some(last_idx) = provided_inputs.by_ref().next()
2980 && let (_, first_span) = self.provided_arg_tys[first_idx]
2981 && let (_, last_span) = self.provided_arg_tys[last_idx]
2982 && source_map.is_multiline(first_span.to(last_span))
2983 && let Some(fallback_indent) = source_map.indentation_before(first_span)
2984 {
2985 ArgumentsFormatting::Multiline { fallback_indent, brace_indent }
2986 } else {
2987 ArgumentsFormatting::SingleLine
2988 }
2989 }
2990
2991 fn suggestion_code(&self) -> (Span, String) {
2992 let source_map = self.sess().source_map();
2993 let suggestion_span = if let Some(args_span) =
2994 self.call_metadata.error_span.trim_start(self.call_metadata.full_call_span)
2995 {
2996 args_span
2998 } else {
2999 self.call_metadata.full_call_span.shrink_to_hi()
3003 };
3004
3005 let arguments_formatting = self.arguments_formatting(suggestion_span);
3006
3007 let mut suggestion = "(".to_owned();
3008 let mut needs_comma = false;
3009 for (expected_idx, provided_idx) in self.matched_inputs.iter_enumerated() {
3010 if needs_comma {
3011 suggestion += ",";
3012 }
3013 match &arguments_formatting {
3014 ArgumentsFormatting::SingleLine if needs_comma => suggestion += " ",
3015 ArgumentsFormatting::SingleLine => {}
3016 ArgumentsFormatting::Multiline { .. } => suggestion += "\n",
3017 }
3018 needs_comma = true;
3019 let (suggestion_span, suggestion_text) = if let Some(provided_idx) = provided_idx
3020 && let (_, provided_span) = self.provided_arg_tys[*provided_idx]
3021 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
3022 {
3023 (Some(provided_span), arg_text)
3024 } else {
3025 let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
3027 (None, self.ty_to_snippet(expected_ty, expected_idx))
3028 };
3029 if let ArgumentsFormatting::Multiline { fallback_indent, .. } = &arguments_formatting {
3030 let indent = suggestion_span
3031 .and_then(|span| source_map.indentation_before(span))
3032 .unwrap_or_else(|| fallback_indent.clone());
3033 suggestion += &indent;
3034 }
3035 suggestion += &suggestion_text;
3036 }
3037 if let ArgumentsFormatting::Multiline { brace_indent, .. } = arguments_formatting {
3038 suggestion += ",\n";
3039 suggestion += &brace_indent;
3040 }
3041 suggestion += ")";
3042
3043 (suggestion_span, suggestion)
3044 }
3045
3046 fn maybe_suggest_expect_for_unwrap(&self, provided_ty: Ty<'tcx>) -> Option<Span> {
3047 let tcx = self.tcx();
3048 if let Some(call_ident) = self.call_metadata.call_ident
3049 && call_ident.name == sym::unwrap
3050 && let Some(callee_ty) = self.callee_ty
3051 && let ty::Adt(adt, _) = callee_ty.peel_refs().kind()
3052 && (tcx.is_diagnostic_item(sym::Option, adt.did())
3053 || tcx.is_diagnostic_item(sym::Result, adt.did()))
3054 && self.may_coerce(provided_ty, Ty::new_static_str(tcx))
3055 {
3056 Some(call_ident.span)
3057 } else {
3058 None
3059 }
3060 }
3061}
3062
3063struct ArgMatchingCtxt<'a, 'tcx> {
3064 args_ctxt: ArgsCtxt<'a, 'tcx>,
3065 provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)>,
3066}
3067
3068impl<'a, 'tcx> Deref for ArgMatchingCtxt<'a, 'tcx> {
3069 type Target = ArgsCtxt<'a, 'tcx>;
3070
3071 fn deref(&self) -> &Self::Target {
3072 &self.args_ctxt
3073 }
3074}
3075
3076impl<'a, 'tcx> ArgMatchingCtxt<'a, 'tcx> {
3077 fn new(
3078 arg: &'a FnCtxt<'a, 'tcx>,
3079 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3080 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3081 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
3082 c_variadic: bool,
3083 err_code: ErrCode,
3084 fn_def_id: Option<DefId>,
3085 call_span: Span,
3086 call_expr: &'tcx Expr<'tcx>,
3087 tuple_arguments: TupleArgumentsFlag,
3088 ) -> Self {
3089 let args_ctxt = ArgsCtxt::new(
3090 arg,
3091 compatibility_diagonal,
3092 formal_and_expected_inputs,
3093 provided_args,
3094 c_variadic,
3095 err_code,
3096 fn_def_id,
3097 call_span,
3098 call_expr,
3099 tuple_arguments,
3100 );
3101 let provided_arg_tys = args_ctxt.provided_arg_tys();
3102
3103 ArgMatchingCtxt { args_ctxt, provided_arg_tys }
3104 }
3105
3106 fn suggest_confusable(&self, err: &mut Diag<'_>) {
3107 let Some(call_name) = self.call_metadata.call_ident else {
3108 return;
3109 };
3110 let Some(callee_ty) = self.callee_ty else {
3111 return;
3112 };
3113 let input_types: Vec<Ty<'_>> = self.provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
3114
3115 if let Some(_name) = self.confusable_method_name(
3123 err,
3124 callee_ty.peel_refs(),
3125 call_name,
3126 Some(input_types.clone()),
3127 ) {
3128 return;
3129 }
3130 if let Some((assoc, fn_sig)) = self.similar_assoc(call_name)
3132 && fn_sig.inputs()[1..]
3133 .iter()
3134 .eq_by(input_types, |expected, found| self.may_coerce(*expected, found))
3135 {
3136 let assoc_name = assoc.name();
3137 err.span_suggestion_verbose(
3138 call_name.span,
3139 ::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),
3140 assoc_name,
3141 Applicability::MaybeIncorrect,
3142 );
3143 return;
3144 }
3145 }
3146
3147 fn check_compatible(
3151 &self,
3152 provided_idx: ProvidedIdx,
3153 expected_idx: ExpectedIdx,
3154 ) -> Compatibility<'tcx> {
3155 if provided_idx.as_usize() == expected_idx.as_usize() {
3156 return self.compatibility_diagonal[provided_idx].clone();
3157 }
3158
3159 let (formal_input_ty, expected_input_ty) = self.formal_and_expected_inputs[expected_idx];
3160 if (formal_input_ty, expected_input_ty).references_error() {
3164 return Compatibility::Incompatible(None);
3165 }
3166
3167 let (arg_ty, arg_span) = self.provided_arg_tys[provided_idx];
3168
3169 let expectation = Expectation::rvalue_hint(self.fn_ctxt, expected_input_ty);
3170 let coerced_ty = expectation.only_has_type(self.fn_ctxt).unwrap_or(formal_input_ty);
3171 let can_coerce = self.may_coerce(arg_ty, coerced_ty);
3172 if !can_coerce {
3173 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
3174 ty::error::ExpectedFound::new(coerced_ty, arg_ty),
3175 )));
3176 }
3177
3178 let subtyping_error = self.probe(|_| {
3180 self.at(&self.misc(arg_span), self.param_env)
3181 .sup(DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty)
3182 .err()
3183 });
3184
3185 let references_error = (coerced_ty, arg_ty).references_error();
3188 match (references_error, subtyping_error) {
3189 (false, None) => Compatibility::Compatible,
3190 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
3191 }
3192 }
3193
3194 fn remove_idx_is_perfect(&self, idx: usize) -> bool {
3195 let removed_arg_tys = self
3196 .provided_arg_tys
3197 .iter()
3198 .enumerate()
3199 .filter_map(|(j, arg)| if idx == j { None } else { Some(arg) })
3200 .collect::<IndexVec<ProvidedIdx, _>>();
3201 std::iter::zip(self.formal_and_expected_inputs.iter(), removed_arg_tys.iter()).all(
3202 |((expected_ty, _), (provided_ty, _))| {
3203 !provided_ty.references_error() && self.may_coerce(*provided_ty, *expected_ty)
3204 },
3205 )
3206 }
3207}
3208
3209struct ArgsCtxt<'a, 'tcx> {
3210 call_ctxt: CallCtxt<'a, 'tcx>,
3211 call_metadata: CallMetadata,
3212 args_span: Span,
3213}
3214
3215impl<'a, 'tcx> Deref for ArgsCtxt<'a, 'tcx> {
3216 type Target = CallCtxt<'a, 'tcx>;
3217
3218 fn deref(&self) -> &Self::Target {
3219 &self.call_ctxt
3220 }
3221}
3222
3223impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> {
3224 fn new(
3225 arg: &'a FnCtxt<'a, 'tcx>,
3226 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3227 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3228 provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
3229 c_variadic: bool,
3230 err_code: ErrCode,
3231 fn_def_id: Option<DefId>,
3232 call_span: Span,
3233 call_expr: &'tcx Expr<'tcx>,
3234 tuple_arguments: TupleArgumentsFlag,
3235 ) -> Self {
3236 let call_ctxt: CallCtxt<'_, '_> = CallCtxt::new(
3237 arg,
3238 compatibility_diagonal,
3239 formal_and_expected_inputs,
3240 provided_args,
3241 c_variadic,
3242 err_code,
3243 fn_def_id,
3244 call_span,
3245 call_expr,
3246 tuple_arguments,
3247 );
3248
3249 let call_metadata = call_ctxt.call_metadata();
3250 let args_span = call_metadata
3251 .error_span
3252 .trim_start(call_metadata.full_call_span)
3253 .unwrap_or(call_metadata.error_span);
3254
3255 ArgsCtxt { args_span, call_metadata, call_ctxt }
3256 }
3257
3258 fn normalize_span(&self, span: Span) -> Span {
3262 let normalized_span =
3263 span.find_ancestor_inside_same_ctxt(self.call_metadata.error_span).unwrap_or(span);
3264 if normalized_span.source_equal(self.call_metadata.error_span) {
3268 span
3269 } else {
3270 normalized_span
3271 }
3272 }
3273
3274 fn provided_arg_tys(&self) -> IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> {
3276 self.call_ctxt
3277 .provided_args
3278 .iter()
3279 .map(|expr| {
3280 let ty = self
3281 .call_ctxt
3282 .fn_ctxt
3283 .typeck_results
3284 .borrow()
3285 .expr_ty_adjusted_opt(expr)
3286 .unwrap_or_else(|| Ty::new_misc_error(self.call_ctxt.fn_ctxt.tcx));
3287 (
3288 self.call_ctxt.fn_ctxt.resolve_vars_if_possible(ty),
3289 self.normalize_span(expr.span),
3290 )
3291 })
3292 .collect()
3293 }
3294
3295 fn similar_assoc(&self, call_name: Ident) -> Option<(ty::AssocItem, ty::FnSig<'tcx>)> {
3297 if let Some(callee_ty) = self.call_ctxt.callee_ty
3298 && let Ok(Some(assoc)) = self.call_ctxt.fn_ctxt.probe_op(
3299 call_name.span,
3300 MethodCall,
3301 Some(call_name),
3302 None,
3303 IsSuggestion(true),
3304 callee_ty.peel_refs(),
3305 self.call_ctxt.callee_expr.unwrap().hir_id,
3306 TraitsInScope,
3307 |mut ctxt| ctxt.probe_for_similar_candidate(),
3308 )
3309 && assoc.is_method()
3310 {
3311 let args =
3312 self.call_ctxt.fn_ctxt.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
3313 let fn_sig = self
3314 .call_ctxt
3315 .fn_ctxt
3316 .tcx
3317 .fn_sig(assoc.def_id)
3318 .instantiate(self.call_ctxt.fn_ctxt.tcx, args)
3319 .skip_norm_wip();
3320
3321 self.call_ctxt.fn_ctxt.instantiate_binder_with_fresh_vars(
3322 call_name.span,
3323 BoundRegionConversionTime::FnCall,
3324 fn_sig,
3325 );
3326 }
3327 None
3328 }
3329
3330 fn call_is_in_macro(&self) -> bool {
3331 self.call_metadata.full_call_span.in_external_macro(self.sess().source_map())
3332 }
3333}
3334
3335struct CallMetadata {
3336 error_span: Span,
3337 call_ident: Option<Ident>,
3338 full_call_span: Span,
3339 call_name: &'static str,
3340 is_method: bool,
3341}
3342
3343struct CallCtxt<'a, 'tcx> {
3344 fn_ctxt: &'a FnCtxt<'a, 'tcx>,
3345 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3346 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3347 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3348 c_variadic: bool,
3349 err_code: ErrCode,
3350 fn_def_id: Option<DefId>,
3351 call_span: Span,
3352 call_expr: &'tcx hir::Expr<'tcx>,
3353 tuple_arguments: TupleArgumentsFlag,
3354 callee_expr: Option<&'tcx Expr<'tcx>>,
3355 callee_ty: Option<Ty<'tcx>>,
3356}
3357
3358impl<'a, 'tcx> Deref for CallCtxt<'a, 'tcx> {
3359 type Target = &'a FnCtxt<'a, 'tcx>;
3360
3361 fn deref(&self) -> &Self::Target {
3362 &self.fn_ctxt
3363 }
3364}
3365
3366impl<'a, 'tcx> CallCtxt<'a, 'tcx> {
3367 fn new(
3368 fn_ctxt: &'a FnCtxt<'a, 'tcx>,
3369 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
3370 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
3371 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
3372 c_variadic: bool,
3373 err_code: ErrCode,
3374 fn_def_id: Option<DefId>,
3375 call_span: Span,
3376 call_expr: &'tcx hir::Expr<'tcx>,
3377 tuple_arguments: TupleArgumentsFlag,
3378 ) -> CallCtxt<'a, 'tcx> {
3379 let callee_expr = match &call_expr.peel_blocks().kind {
3380 hir::ExprKind::Call(callee, _) => Some(*callee),
3381 hir::ExprKind::MethodCall(_, receiver, ..) => {
3382 if let Some((DefKind::AssocFn, def_id)) =
3383 fn_ctxt.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
3384 && let Some(assoc) = fn_ctxt.tcx.opt_associated_item(def_id)
3385 && assoc.is_method()
3386 {
3387 Some(*receiver)
3388 } else {
3389 None
3390 }
3391 }
3392 _ => None,
3393 };
3394
3395 let callee_ty = callee_expr.and_then(|callee_expr| {
3396 fn_ctxt.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
3397 });
3398
3399 CallCtxt {
3400 fn_ctxt,
3401 compatibility_diagonal,
3402 formal_and_expected_inputs,
3403 provided_args,
3404 c_variadic,
3405 err_code,
3406 fn_def_id,
3407 call_span,
3408 call_expr,
3409 tuple_arguments,
3410 callee_expr,
3411 callee_ty,
3412 }
3413 }
3414
3415 fn call_metadata(&self) -> CallMetadata {
3416 match &self.call_expr.kind {
3417 hir::ExprKind::Call(
3418 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
3419 _,
3420 ) => {
3421 if let Res::Def(DefKind::Ctor(of, _), _) =
3422 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
3423 {
3424 let name = match of {
3425 CtorOf::Struct => "struct",
3426 CtorOf::Variant => "enum variant",
3427 };
3428 CallMetadata {
3429 error_span: self.call_span,
3430 call_ident: None,
3431 full_call_span: *span,
3432 call_name: name,
3433 is_method: false,
3434 }
3435 } else {
3436 CallMetadata {
3437 error_span: self.call_span,
3438 call_ident: None,
3439 full_call_span: *span,
3440 call_name: "function",
3441 is_method: false,
3442 }
3443 }
3444 }
3445 hir::ExprKind::Call(hir::Expr { span, .. }, _) => CallMetadata {
3446 error_span: self.call_span,
3447 call_ident: None,
3448 full_call_span: *span,
3449 call_name: "function",
3450 is_method: false,
3451 },
3452 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
3453 let ident_span = path_segment.ident.span;
3454 let ident_span = if let Some(args) = path_segment.args {
3455 ident_span.with_hi(args.span_ext.hi())
3456 } else {
3457 ident_span
3458 };
3459 CallMetadata {
3460 error_span: *span,
3461 call_ident: Some(path_segment.ident),
3462 full_call_span: ident_span,
3463 call_name: "method",
3464 is_method: true,
3465 }
3466 }
3467 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),
3468 }
3469 }
3470
3471 fn mk_trace(
3472 &self,
3473 span: Span,
3474 (formal_ty, expected_ty): (Ty<'tcx>, Ty<'tcx>),
3475 provided_ty: Ty<'tcx>,
3476 ) -> TypeTrace<'tcx> {
3477 let mismatched_ty = if expected_ty == provided_ty {
3478 formal_ty
3482 } else {
3483 expected_ty
3484 };
3485 TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty)
3486 }
3487
3488 fn ty_to_snippet(&self, ty: Ty<'tcx>, expected_idx: ExpectedIdx) -> String {
3489 if ty.is_unit() {
3490 "()".to_string()
3491 } else if ty.is_suggestable(self.tcx, false) {
3492 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", ty))
})format!("/* {ty} */")
3493 } else if let Some(fn_def_id) = self.fn_def_id
3494 && self.tcx.def_kind(fn_def_id).is_fn_like()
3495 && let self_implicit =
3496 #[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
3497 && let Some(Some(arg)) =
3498 self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit)
3499 && arg.name != kw::SelfLower
3500 {
3501 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/* {0} */", arg.name))
})format!("/* {} */", arg.name)
3502 } else {
3503 "/* value */".to_string()
3504 }
3505 }
3506
3507 fn first_incompatible_error(&self) -> Option<(ProvidedIdx, TypeError<'tcx>)> {
3508 self.compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
3509 if let Compatibility::Incompatible(Some(terr)) = c { Some((i, *terr)) } else { None }
3510 })
3511 }
3512}
3513
3514enum SuggestionText {
3515 None,
3516 Provide(bool),
3517 Remove(bool),
3518 Swap,
3519 Reorder,
3520 DidYouMean,
3521}