1 use crate::astconv::AstConv;
2 use crate::check::coercion::CoerceMany;
3 use crate::check::fn_ctxt::arg_matrix::{
4 ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx,
6 use crate::check::gather_locals::Declaration;
7 use crate::check::intrinsicck::InlineAsmCtxt;
8 use crate::check::method::MethodCallee;
9 use crate::check::Expectation::*;
10 use crate::check::TupleArgumentsFlag::*;
12 potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
13 LocalTy, Needs, TupleArgumentsFlag,
15 use crate::structured_errors::StructuredDiagnostic;
18 use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
20 use rustc_hir::def::{CtorOf, DefKind, Res};
21 use rustc_hir::def_id::DefId;
22 use rustc_hir::{ExprKind, Node, QPath};
23 use rustc_index::vec::IndexVec;
24 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
25 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
26 use rustc_infer::infer::InferOk;
27 use rustc_infer::infer::TypeTrace;
28 use rustc_middle::ty::adjustment::AllowTwoPhase;
29 use rustc_middle::ty::visit::TypeVisitable;
30 use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
31 use rustc_session::Session;
32 use rustc_span::symbol::Ident;
33 use rustc_span::{self, Span};
34 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
39 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
40 pub(in super::super) fn check_casts(&self) {
41 let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
42 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
43 for cast in deferred_cast_checks.drain(..) {
48 pub(in super::super) fn check_transmutes(&self) {
49 let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
50 debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
51 for (from, to, span) in deferred_transmute_checks.drain(..) {
52 self.check_transmute(span, from, to);
56 pub(in super::super) fn check_asms(&self) {
57 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
58 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
59 for (asm, hir_id) in deferred_asm_checks.drain(..) {
60 let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
61 InlineAsmCtxt::new_in_fn(self)
62 .check_asm(asm, self.tcx.hir().local_def_id_to_hir_id(enclosing_id));
66 pub(in super::super) fn check_method_argument_types(
69 expr: &'tcx hir::Expr<'tcx>,
70 method: Result<MethodCallee<'tcx>, ()>,
71 args_no_rcvr: &'tcx [hir::Expr<'tcx>],
72 tuple_arguments: TupleArgumentsFlag,
73 expected: Expectation<'tcx>,
75 let has_error = match method {
76 Ok(method) => method.substs.references_error() || method.sig.references_error(),
80 let err_inputs = self.err_args(args_no_rcvr.len());
82 let err_inputs = match tuple_arguments {
83 DontTupleArguments => err_inputs,
84 TupleArguments => vec![self.tcx.intern_tup(&err_inputs)],
87 self.check_argument_types(
95 method.ok().map(|method| method.def_id),
97 return self.tcx.ty_error();
100 let method = method.unwrap();
101 // HACK(eddyb) ignore self in the definition (see above).
102 let expected_input_tys = self.expected_inputs_for_expected_output(
106 &method.sig.inputs()[1..],
108 self.check_argument_types(
111 &method.sig.inputs()[1..],
114 method.sig.c_variadic,
121 /// Generic function that factors out common logic from function calls,
122 /// method calls and overloaded operators.
123 pub(in super::super) fn check_argument_types(
125 // Span enclosing the call site
127 // Expression of the call site
128 call_expr: &'tcx hir::Expr<'tcx>,
129 // Types (as defined in the *signature* of the target function)
130 formal_input_tys: &[Ty<'tcx>],
131 // More specific expected types, after unifying with caller output types
132 expected_input_tys: Option<Vec<Ty<'tcx>>>,
133 // The expressions for each provided argument
134 provided_args: &'tcx [hir::Expr<'tcx>],
135 // Whether the function is variadic, for example when imported from C
137 // Whether the arguments have been bundled in a tuple (ex: closures)
138 tuple_arguments: TupleArgumentsFlag,
139 // The DefId for the function being called, for better error messages
140 fn_def_id: Option<DefId>,
144 // Conceptually, we've got some number of expected inputs, and some number of provided aguments
145 // and we can form a grid of whether each argument could satisfy a given input:
146 // in1 | in2 | in3 | ...
151 // Initially, we just check the diagonal, because in the case of correct code
152 // these are the only checks that matter
153 // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
154 // better error messages about invalid method calls.
156 // All the input types from the fn signature must outlive the call
157 // so as to validate implied bounds.
158 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
159 self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
162 let mut err_code = "E0061";
164 // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
165 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
166 let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
167 match tuple_type.kind() {
168 // We expected a tuple and got a tuple
169 ty::Tuple(arg_types) => {
170 // Argument length differs
171 if arg_types.len() != provided_args.len() {
174 let expected_input_tys = match expected_input_tys {
175 Some(expected_input_tys) => match expected_input_tys.get(0) {
176 Some(ty) => match ty.kind() {
177 ty::Tuple(tys) => Some(tys.iter().collect()),
184 (arg_types.iter().collect(), expected_input_tys)
187 // Otherwise, there's a mismatch, so clear out what we're expecting, and set
188 // our input types to err_args so we don't blow up the error messages
193 "cannot use call notation; the first type parameter \
194 for the function trait is neither a tuple nor unit"
197 (self.err_args(provided_args.len()), None)
201 (formal_input_tys.to_vec(), expected_input_tys)
204 // If there are no external expectations at the call site, just use the types from the function defn
205 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
206 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
209 formal_input_tys.clone()
212 let minimum_input_count = expected_input_tys.len();
213 let provided_arg_count = provided_args.len();
215 // We introduce a helper function to demand that a given argument satisfy a given input
216 // This is more complicated than just checking type equality, as arguments could be coerced
217 // This version writes those types back so further type checking uses the narrowed types
218 let demand_compatible = |idx| {
219 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
220 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
221 let provided_arg = &provided_args[idx];
223 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
225 // We're on the happy path here, so we'll do a more involved check and write back types
226 // To check compatibility, we'll do 3 things:
227 // 1. Unify the provided argument with the expected type
228 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
230 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
232 // 2. Coerce to the most detailed type that could be coerced
233 // to, which is `expected_ty` if `rvalue_hint` returns an
234 // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
235 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
237 // Cause selection errors caused by resolving a single argument to point at the
238 // argument and not the call. This lets us customize the span pointed to in the
239 // fulfillment error to be more accurate.
241 self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
242 self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
243 self.point_at_arg_instead_of_call_if_possible(
252 let coerce_error = self
253 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
256 if coerce_error.is_some() {
257 return Compatibility::Incompatible(coerce_error);
260 // 3. Check if the formal type is a supertype of the checked one
261 // and register any such obligations for future type checks
262 let supertype_error = self
263 .at(&self.misc(provided_arg.span), self.param_env)
264 .sup(formal_input_ty, coerced_ty);
265 let subtyping_error = match supertype_error {
266 Ok(InferOk { obligations, value: () }) => {
267 self.register_predicates(obligations);
270 Err(err) => Some(err),
273 // If neither check failed, the types are compatible
274 match subtyping_error {
275 None => Compatibility::Compatible,
276 Some(_) => Compatibility::Incompatible(subtyping_error),
280 // To start, we only care "along the diagonal", where we expect every
281 // provided arg to be in the right spot
282 let mut compatibility_diagonal =
283 vec![Compatibility::Incompatible(None); provided_args.len()];
285 // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
286 // if the wrong number of arguments were supplied, we CAN'T be satisfied,
287 // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
288 // otherwise, they need to be identical, because rust doesn't currently support variadic functions
289 let mut call_appears_satisfied = if c_variadic {
290 provided_arg_count >= minimum_input_count
292 provided_arg_count == minimum_input_count
295 // Check the arguments.
296 // We do this in a pretty awful way: first we type-check any arguments
297 // that are not closures, then we type-check the closures. This is so
298 // that we have more information about the types of arguments when we
299 // type-check the functions. This isn't really the right way to do this.
300 for check_closures in [false, true] {
301 // More awful hacks: before we check argument types, try to do
302 // an "opportunistic" trait resolution of any trait bounds on
303 // the call. This helps coercions.
305 self.select_obligations_where_possible(false, |errors| {
306 self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
307 self.point_at_arg_instead_of_call_if_possible(
317 // Check each argument, to satisfy the input it was provided for
318 // Visually, we're traveling down the diagonal of the compatibility matrix
319 for (idx, arg) in provided_args.iter().enumerate() {
320 // Warn only for the first loop (the "no closures" one).
321 // Closure arguments themselves can't be diverging, but
322 // a previous argument can, e.g., `foo(panic!(), || {})`.
324 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
327 // For C-variadic functions, we don't have a declared type for all of
328 // the arguments hence we only do our usual type checking with
329 // the arguments who's types we do know. However, we *can* check
330 // for unreachable expressions (see above).
331 // FIXME: unreachable warning current isn't emitted
332 if idx >= minimum_input_count {
336 let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
337 if is_closure != check_closures {
341 let compatible = demand_compatible(idx);
342 let is_compatible = matches!(compatible, Compatibility::Compatible);
343 compatibility_diagonal[idx] = compatible;
346 call_appears_satisfied = false;
351 if c_variadic && provided_arg_count < minimum_input_count {
355 for arg in provided_args.iter().skip(minimum_input_count) {
356 // Make sure we've checked this expr at least once.
357 let arg_ty = self.check_expr(&arg);
359 // If the function is c-style variadic, we skipped a bunch of arguments
360 // so we need to check those, and write out the types
361 // Ideally this would be folded into the above, for uniform style
362 // but c-variadic is already a corner case
364 fn variadic_error<'tcx>(
370 use crate::structured_errors::MissingCastForVariadicArg;
372 MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
375 // There are a few types which get autopromoted when passed via varargs
376 // in C but we just error out instead and require explicit casts.
377 let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
378 match arg_ty.kind() {
379 ty::Float(ty::FloatTy::F32) => {
380 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
382 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
383 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
385 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
386 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
389 let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
390 let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
391 variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
398 if !call_appears_satisfied {
399 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
400 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
406 formal_input_tys.len(),
407 expected_input_tys.len(),
408 "expected formal_input_tys to be the same size as expected_input_tys"
410 let formal_and_expected_inputs = IndexVec::from_iter(
414 .zip(expected_input_tys.iter().copied())
415 .map(|vars| self.resolve_vars_if_possible(vars)),
418 self.report_arg_errors(
419 compatibility_diagonal,
420 formal_and_expected_inputs,
431 fn report_arg_errors(
433 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
434 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
435 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
438 fn_def_id: Option<DefId>,
440 call_expr: &hir::Expr<'tcx>,
442 // Next, let's construct the error
443 let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
445 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
448 if let Res::Def(DefKind::Ctor(of, _), _) =
449 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
451 (call_span, *span, Some(of))
453 (call_span, *span, None)
456 hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
457 hir::ExprKind::MethodCall(path_segment, _, span) => {
458 let ident_span = path_segment.ident.span;
459 let ident_span = if let Some(args) = path_segment.args {
460 ident_span.with_hi(args.span_ext.hi())
465 *span, ident_span, None, // methods are never ctors
468 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
470 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
471 let call_name = match ctor_of {
472 Some(CtorOf::Struct) => "struct",
473 Some(CtorOf::Variant) => "enum variant",
477 // Don't print if it has error types or is just plain `_`
478 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
479 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
482 self.set_tainted_by_errors();
485 // Get the argument span in the context of the call span so that
486 // suggestions and labels are (more) correct when an arg is a
488 let normalize_span = |span: Span| -> Span {
489 let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span);
490 // Sometimes macros mess up the spans, so do not normalize the
491 // arg span to equal the error span, because that's less useful
492 // than pointing out the arg expr in the wrong context.
493 if normalized_span.source_equal(error_span) { span } else { normalized_span }
496 // Precompute the provided types and spans, since that's all we typically need for below
497 let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
503 .expr_ty_adjusted_opt(*expr)
504 .unwrap_or_else(|| tcx.ty_error());
505 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
508 let callee_expr = match &call_expr.peel_blocks().kind {
509 hir::ExprKind::Call(callee, _) => Some(*callee),
510 hir::ExprKind::MethodCall(_, callee, _) => {
511 if let Some((DefKind::AssocFn, def_id)) =
512 self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
513 && let Some(assoc) = tcx.opt_associated_item(def_id)
514 && assoc.fn_has_self_parameter
523 let callee_ty = callee_expr
524 .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
526 // A "softer" version of the `demand_compatible`, which checks types without persisting them,
527 // and treats error types differently
528 // This will allow us to "probe" for other argument orders that would likely have been correct
529 let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
530 if provided_idx.as_usize() == expected_idx.as_usize() {
531 return compatibility_diagonal[provided_idx].clone();
534 let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
535 // If either is an error type, we defy the usual convention and consider them to *not* be
536 // coercible. This prevents our error message heuristic from trying to pass errors into
538 if (formal_input_ty, expected_input_ty).references_error() {
539 return Compatibility::Incompatible(None);
542 let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
544 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
545 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
546 let can_coerce = self.can_coerce(arg_ty, coerced_ty);
548 return Compatibility::Incompatible(None);
551 // Using probe here, since we don't want this subtyping to affect inference.
552 let subtyping_error = self.probe(|_| {
553 self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err()
556 // Same as above: if either the coerce type or the checked type is an error type,
557 // consider them *not* compatible.
558 let references_error = (coerced_ty, arg_ty).references_error();
559 match (references_error, subtyping_error) {
560 (false, None) => Compatibility::Compatible,
561 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
565 // The algorithm here is inspired by levenshtein distance and longest common subsequence.
566 // We'll try to detect 4 different types of mistakes:
567 // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
568 // - An input is missing, which isn't satisfied by *any* of the other arguments
569 // - Some number of arguments have been provided in the wrong order
570 // - A type is straight up invalid
572 // First, let's find the errors
573 let (mut errors, matched_inputs) =
574 ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
577 // First, check if we just need to wrap some arguments in a tuple.
578 if let Some((mismatch_idx, terr)) =
579 compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {
580 if let Compatibility::Incompatible(Some(terr)) = c { Some((i, terr)) } else { None }
583 // Is the first bad expected argument a tuple?
584 // Do we have as many extra provided arguments as the tuple's length?
585 // If so, we might have just forgotten to wrap some args in a tuple.
586 if let Some(ty::Tuple(tys)) =
587 formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
588 // If the tuple is unit, we're not actually wrapping any arguments.
590 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
592 // Wrap up the N provided arguments starting at this position in a tuple.
593 let provided_as_tuple = tcx.mk_tup(
594 provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
597 let mut satisfied = true;
598 // Check if the newly wrapped tuple + rest of the arguments are compatible.
599 for ((_, expected_ty), provided_ty) in std::iter::zip(
600 formal_and_expected_inputs.iter().skip(mismatch_idx),
601 [provided_as_tuple].into_iter().chain(
602 provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
605 if !self.can_coerce(provided_ty, *expected_ty) {
611 // If they're compatible, suggest wrapping in an arg, and we're done!
612 // Take some care with spans, so we don't suggest wrapping a macro's
613 // innards in parenthesis, for example.
615 && let Some((_, lo)) =
616 provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx))
617 && let Some((_, hi)) =
618 provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1))
622 // A tuple wrap suggestion actually occurs within,
623 // so don't do anything special here.
624 err = self.report_and_explain_type_error(
628 formal_and_expected_inputs[mismatch_idx.into()].1,
629 provided_arg_tys[mismatch_idx.into()].0,
635 format!("arguments to this {} are incorrect", call_name),
638 err = tcx.sess.struct_span_err_with_code(
641 "this {} takes {}{} but {} {} supplied",
643 if c_variadic { "at least " } else { "" },
644 potentially_plural_count(
645 formal_and_expected_inputs.len(),
648 potentially_plural_count(provided_args.len(), "argument"),
649 pluralize!("was", provided_args.len())
651 DiagnosticId::Error(err_code.to_owned()),
653 err.multipart_suggestion_verbose(
654 "wrap these arguments in parentheses to construct a tuple",
656 (lo.shrink_to_lo(), "(".to_string()),
657 (hi.shrink_to_hi(), ")".to_string()),
659 Applicability::MachineApplicable,
662 self.label_fn_like(&mut err, fn_def_id, callee_ty);
669 // Okay, so here's where it gets complicated in regards to what errors
671 // There are 3 different "types" of errors we might encounter.
672 // 1) Missing/extra/swapped arguments
673 // 2) Valid but incorrect arguments
674 // 3) Invalid arguments
675 // - Currently I think this only comes up with `CyclicTy`
677 // We first need to go through, remove those from (3) and emit those
678 // as their own error, particularly since they're error code and
679 // message is special. From what I can tell, we *must* emit these
680 // here (vs somewhere prior to this function) since the arguments
681 // become invalid *because* of how they get used in the function.
684 if errors.is_empty() {
685 if cfg!(debug_assertions) {
686 span_bug!(error_span, "expected errors from argument matrix");
691 "argument type mismatch was detected, \
692 but rustc had trouble determining where",
695 "we would appreciate a bug report: \
696 https://github.com/rust-lang/rust/issues/new",
703 errors.drain_filter(|error| {
704 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(error)) = error else { return false };
705 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
706 let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
707 let cause = &self.misc(provided_span);
708 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
709 if let Some(e) = error {
710 if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
711 self.report_and_explain_type_error(trace, e).emit();
718 // We're done if we found errors, but we already emitted them.
719 if errors.is_empty() {
723 // Okay, now that we've emitted the special errors separately, we
724 // are only left missing/extra/swapped and mismatched arguments, both
725 // can be collated pretty easily if needed.
727 // Next special case: if there is only one "Incompatible" error, just emit that
729 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
732 let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
733 let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
734 let cause = &self.misc(provided_arg_span);
735 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
736 let mut err = self.report_and_explain_type_error(trace, err);
737 self.emit_coerce_suggestions(
739 &provided_args[*provided_idx],
741 Expectation::rvalue_hint(self, expected_ty)
743 .unwrap_or(formal_ty),
749 format!("arguments to this {} are incorrect", call_name),
751 // Call out where the function is defined
752 self.label_fn_like(&mut err, fn_def_id, callee_ty);
757 let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
762 "arguments to this {} are incorrect",
766 tcx.sess.struct_span_err_with_code(
769 "this {} takes {}{} but {} {} supplied",
771 if c_variadic { "at least " } else { "" },
772 potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
773 potentially_plural_count(provided_args.len(), "argument"),
774 pluralize!("was", provided_args.len())
776 DiagnosticId::Error(err_code.to_owned()),
780 // As we encounter issues, keep track of what we want to provide for the suggestion
781 let mut labels = vec![];
782 // If there is a single error, we give a specific suggestion; otherwise, we change to
783 // "did you mean" with the suggested function call
784 enum SuggestionText {
792 let mut suggestion_text = SuggestionText::None;
794 let mut errors = errors.into_iter().peekable();
795 while let Some(error) = errors.next() {
797 Error::Invalid(provided_idx, expected_idx, compatibility) => {
798 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
799 let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
800 if let Compatibility::Incompatible(error) = &compatibility {
801 let cause = &self.misc(provided_span);
802 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
803 if let Some(e) = error {
816 self.emit_coerce_suggestions(
818 &provided_args[provided_idx],
820 Expectation::rvalue_hint(self, expected_ty)
822 .unwrap_or(formal_ty),
827 Error::Extra(arg_idx) => {
828 let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
829 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
830 // FIXME: not suggestable, use something else
831 format!(" of type `{}`", provided_ty)
836 .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
837 suggestion_text = match suggestion_text {
838 SuggestionText::None => SuggestionText::Remove(false),
839 SuggestionText::Remove(_) => SuggestionText::Remove(true),
840 _ => SuggestionText::DidYouMean,
843 Error::Missing(expected_idx) => {
844 // If there are multiple missing arguments adjacent to each other,
845 // then we can provide a single error.
847 let mut missing_idxs = vec![expected_idx];
848 while let Some(e) = errors.next_if(|e| {
849 matches!(e, Error::Missing(next_expected_idx)
850 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
853 Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
858 // NOTE: Because we might be re-arranging arguments, might have extra
859 // arguments, etc. it's hard to *really* know where we should provide
860 // this error label, so as a heuristic, we point to the provided arg, or
861 // to the call if the missing inputs pass the provided args.
862 match &missing_idxs[..] {
864 let (_, input_ty) = formal_and_expected_inputs[expected_idx];
865 let span = if let Some((_, arg_span)) =
866 provided_arg_tys.get(expected_idx.to_provided_idx())
872 let rendered = if !has_error_or_infer([input_ty]) {
873 format!(" of type `{}`", input_ty)
877 labels.push((span, format!("an argument{} is missing", rendered)));
878 suggestion_text = match suggestion_text {
879 SuggestionText::None => SuggestionText::Provide(false),
880 SuggestionText::Provide(_) => SuggestionText::Provide(true),
881 _ => SuggestionText::DidYouMean,
884 &[first_idx, second_idx] => {
885 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
886 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
887 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
888 provided_arg_tys.get(first_idx.to_provided_idx()),
889 provided_arg_tys.get(second_idx.to_provided_idx()),
891 first_span.to(*second_span)
896 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
898 " of type `{}` and `{}`",
899 first_expected_ty, second_expected_ty
904 labels.push((span, format!("two arguments{} are missing", rendered)));
905 suggestion_text = match suggestion_text {
906 SuggestionText::None | SuggestionText::Provide(_) => {
907 SuggestionText::Provide(true)
909 _ => SuggestionText::DidYouMean,
912 &[first_idx, second_idx, third_idx] => {
913 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
914 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
915 let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
916 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
917 provided_arg_tys.get(first_idx.to_provided_idx()),
918 provided_arg_tys.get(third_idx.to_provided_idx()),
920 first_span.to(*third_span)
924 let rendered = if !has_error_or_infer([
930 " of type `{}`, `{}`, and `{}`",
931 first_expected_ty, second_expected_ty, third_expected_ty
936 labels.push((span, format!("three arguments{} are missing", rendered)));
937 suggestion_text = match suggestion_text {
938 SuggestionText::None | SuggestionText::Provide(_) => {
939 SuggestionText::Provide(true)
941 _ => SuggestionText::DidYouMean,
945 let first_idx = *missing_idxs.first().unwrap();
946 let last_idx = *missing_idxs.last().unwrap();
947 // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
948 // It's hard to *really* know where we should provide this error label, so this is a
950 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
951 provided_arg_tys.get(first_idx.to_provided_idx()),
952 provided_arg_tys.get(last_idx.to_provided_idx()),
954 first_span.to(*last_span)
958 labels.push((span, format!("multiple arguments are missing")));
959 suggestion_text = match suggestion_text {
960 SuggestionText::None | SuggestionText::Provide(_) => {
961 SuggestionText::Provide(true)
963 _ => SuggestionText::DidYouMean,
974 let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
975 let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
976 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
977 format!(", found `{}`", first_provided_ty)
983 format!("expected `{}`{}", first_expected_ty, first_provided_ty_name),
986 let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
987 let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
988 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
989 format!(", found `{}`", second_provided_ty)
995 format!("expected `{}`{}", second_expected_ty, second_provided_ty_name),
998 suggestion_text = match suggestion_text {
999 SuggestionText::None => SuggestionText::Swap,
1000 _ => SuggestionText::DidYouMean,
1003 Error::Permutation(args) => {
1004 for (dst_arg, dest_input) in args {
1005 let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
1006 let (provided_ty, provided_span) = provided_arg_tys[dest_input];
1007 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1008 format!(", found `{}`", provided_ty)
1014 format!("expected `{}`{}", expected_ty, provided_ty_name),
1018 suggestion_text = match suggestion_text {
1019 SuggestionText::None => SuggestionText::Reorder,
1020 _ => SuggestionText::DidYouMean,
1026 // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
1027 if labels.len() <= 5 {
1028 for (span, label) in labels {
1029 err.span_label(span, label);
1033 // Call out where the function is defined
1034 self.label_fn_like(&mut err, fn_def_id, callee_ty);
1036 // And add a suggestion block for all of the parameters
1037 let suggestion_text = match suggestion_text {
1038 SuggestionText::None => None,
1039 SuggestionText::Provide(plural) => {
1040 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
1042 SuggestionText::Remove(plural) => {
1043 Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
1045 SuggestionText::Swap => Some("swap these arguments".to_string()),
1046 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
1047 SuggestionText::DidYouMean => Some("did you mean".to_string()),
1049 if let Some(suggestion_text) = suggestion_text {
1050 let source_map = self.sess().source_map();
1051 let mut suggestion = format!(
1053 source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| fn_def_id
1054 .map_or("".to_string(), |fn_def_id| tcx.item_name(fn_def_id).to_string()))
1056 let mut needs_comma = false;
1057 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1063 let suggestion_text = if let Some(provided_idx) = provided_idx
1064 && let (_, provided_span) = provided_arg_tys[*provided_idx]
1065 && let Ok(arg_text) =
1066 source_map.span_to_snippet(provided_span)
1070 // Propose a placeholder of the correct type
1071 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1072 if expected_ty.is_unit() {
1074 } else if expected_ty.is_suggestable(tcx, false) {
1075 format!("/* {} */", expected_ty)
1077 "/* value */".to_string()
1080 suggestion += &suggestion_text;
1083 err.span_suggestion_verbose(
1087 Applicability::HasPlaceholders,
1094 // AST fragment checking
1095 pub(in super::super) fn check_lit(
1098 expected: Expectation<'tcx>,
1103 ast::LitKind::Str(..) => tcx.mk_static_str(),
1104 ast::LitKind::ByteStr(ref v) => {
1105 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
1107 ast::LitKind::Byte(_) => tcx.types.u8,
1108 ast::LitKind::Char(_) => tcx.types.char,
1109 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)),
1110 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)),
1111 ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
1112 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1113 ty::Int(_) | ty::Uint(_) => Some(ty),
1114 ty::Char => Some(tcx.types.u8),
1115 ty::RawPtr(..) => Some(tcx.types.usize),
1116 ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
1119 opt_ty.unwrap_or_else(|| self.next_int_var())
1121 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
1122 tcx.mk_mach_float(ty::float_ty(t))
1124 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1125 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1126 ty::Float(_) => Some(ty),
1129 opt_ty.unwrap_or_else(|| self.next_float_var())
1131 ast::LitKind::Bool(_) => tcx.types.bool,
1132 ast::LitKind::Err(_) => tcx.ty_error(),
1136 pub fn check_struct_path(
1140 ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
1141 let path_span = qpath.span();
1142 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1143 let variant = match def {
1145 self.set_tainted_by_errors();
1148 Res::Def(DefKind::Variant, _) => match ty.kind() {
1149 ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
1150 _ => bug!("unexpected type: {:?}", ty),
1152 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1153 | Res::SelfTy { .. } => match ty.kind() {
1154 ty::Adt(adt, substs) if !adt.is_enum() => {
1155 Some((adt.non_enum_variant(), adt.did(), substs))
1159 _ => bug!("unexpected definition: {:?}", def),
1162 if let Some((variant, did, substs)) = variant {
1163 debug!("check_struct_path: did={:?} substs={:?}", did, substs);
1164 self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
1166 // Check bounds on type arguments used in the path.
1167 self.add_required_obligations(path_span, did, substs);
1173 // E0071 might be caused by a spelling error, which will have
1174 // already caused an error message and probably a suggestion
1175 // elsewhere. Refrain from emitting more unhelpful errors here
1183 "expected struct, variant or union type, found {}",
1184 ty.sort_string(self.tcx)
1186 .span_label(path_span, "not a struct")
1194 pub fn check_decl_initializer(
1197 pat: &'tcx hir::Pat<'tcx>,
1198 init: &'tcx hir::Expr<'tcx>,
1200 // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
1201 // for #42640 (default match binding modes).
1204 let ref_bindings = pat.contains_explicit_ref_binding();
1206 let local_ty = self.local_ty(init.span, hir_id).revealed_ty;
1207 if let Some(m) = ref_bindings {
1208 // Somewhat subtle: if we have a `ref` binding in the pattern,
1209 // we want to avoid introducing coercions for the RHS. This is
1210 // both because it helps preserve sanity and, in the case of
1211 // ref mut, for soundness (issue #23116). In particular, in
1212 // the latter case, we need to be clear that the type of the
1213 // referent for the reference that results is *equal to* the
1214 // type of the place it is referencing, and not some
1215 // supertype thereof.
1216 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1217 self.demand_eqtype(init.span, local_ty, init_ty);
1220 self.check_expr_coercable_to_type(init, local_ty, None)
1224 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
1225 // Determine and write the type which we'll check the pattern against.
1226 let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty;
1227 self.write_ty(decl.hir_id, decl_ty);
1229 // Type check the initializer.
1230 if let Some(ref init) = decl.init {
1231 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
1232 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty);
1235 // Does the expected pattern type originate from an expression and what is the span?
1236 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1237 (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
1238 (_, Some(init)) => {
1239 (true, Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1240 } // No explicit type; so use the scrutinee.
1241 _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
1244 // Type check the pattern. Override if necessary to avoid knock-on errors.
1245 self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
1246 let pat_ty = self.node_ty(decl.pat.hir_id);
1247 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
1249 if let Some(blk) = decl.els {
1250 let previous_diverges = self.diverges.get();
1251 let else_ty = self.check_block_with_expected(blk, NoExpectation);
1252 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1253 if let Some(mut err) =
1254 self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1258 self.diverges.set(previous_diverges);
1262 /// Type check a `let` statement.
1263 pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
1264 self.check_decl(local.into());
1267 pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
1268 // Don't do all the complex logic below for `DeclItem`.
1270 hir::StmtKind::Item(..) => return,
1271 hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1274 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1276 // Hide the outer diverging and `has_errors` flags.
1277 let old_diverges = self.diverges.replace(Diverges::Maybe);
1278 let old_has_errors = self.has_errors.replace(false);
1281 hir::StmtKind::Local(l) => {
1282 self.check_decl_local(l);
1285 hir::StmtKind::Item(_) => {}
1286 hir::StmtKind::Expr(ref expr) => {
1287 // Check with expected type of `()`.
1288 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
1289 if expr.can_have_side_effects() {
1290 self.suggest_semicolon_at_end(expr.span, err);
1294 hir::StmtKind::Semi(ref expr) => {
1295 // All of this is equivalent to calling `check_expr`, but it is inlined out here
1296 // in order to capture the fact that this `match` is the last statement in its
1297 // function. This is done for better suggestions to remove the `;`.
1298 let expectation = match expr.kind {
1299 hir::ExprKind::Match(..) if is_last => IsLast(stmt.span),
1302 self.check_expr_with_expectation(expr, expectation);
1306 // Combine the diverging and `has_error` flags.
1307 self.diverges.set(self.diverges.get() | old_diverges);
1308 self.has_errors.set(self.has_errors.get() | old_has_errors);
1311 pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1312 let unit = self.tcx.mk_unit();
1313 let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
1315 // if the block produces a `!` value, that can always be
1316 // (effectively) coerced to unit.
1318 self.demand_suptype(blk.span, unit, ty);
1322 pub(in super::super) fn check_block_with_expected(
1324 blk: &'tcx hir::Block<'tcx>,
1325 expected: Expectation<'tcx>,
1327 let prev = self.ps.replace(self.ps.get().recurse(blk));
1329 // In some cases, blocks have just one exit, but other blocks
1330 // can be targeted by multiple breaks. This can happen both
1331 // with labeled blocks as well as when we desugar
1332 // a `try { ... }` expression.
1336 // 'a: { if true { break 'a Err(()); } Ok(()) }
1338 // Here we would wind up with two coercions, one from
1339 // `Err(())` and the other from the tail expression
1340 // `Ok(())`. If the tail expression is omitted, that's a
1341 // "forced unit" -- unless the block diverges, in which
1342 // case we can ignore the tail expression (e.g., `'a: {
1343 // break 'a 22; }` would not force the type of the block
1345 let tail_expr = blk.expr.as_ref();
1346 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1347 let coerce = if blk.targeted_by_break {
1348 CoerceMany::new(coerce_to_ty)
1350 let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
1351 Some(e) => slice::from_ref(e),
1354 CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
1357 let prev_diverges = self.diverges.get();
1358 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1360 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1361 for (pos, s) in blk.stmts.iter().enumerate() {
1362 self.check_stmt(s, blk.stmts.len() - 1 == pos);
1365 // check the tail expression **without** holding the
1366 // `enclosing_breakables` lock below.
1367 let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
1369 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1370 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1371 let coerce = ctxt.coerce.as_mut().unwrap();
1372 if let Some(tail_expr_ty) = tail_expr_ty {
1373 let tail_expr = tail_expr.unwrap();
1374 let span = self.get_expr_coercion_span(tail_expr);
1375 let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
1376 let ty_for_diagnostic = coerce.merged_ty();
1377 // We use coerce_inner here because we want to augment the error
1378 // suggesting to wrap the block in square brackets if it might've
1379 // been mistaken array syntax
1380 coerce.coerce_inner(
1385 Some(&mut |diag: &mut Diagnostic| {
1386 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1391 // Subtle: if there is no explicit tail expression,
1392 // that is typically equivalent to a tail expression
1393 // of `()` -- except if the block diverges. In that
1394 // case, there is no value supplied from the tail
1395 // expression (assuming there are no other breaks,
1396 // this implies that the type of the block will be
1399 // #41425 -- label the implicit `()` as being the
1400 // "found type" here, rather than the "expected type".
1401 if !self.diverges.get().is_always() {
1402 // #50009 -- Do not point at the entire fn block span, point at the return type
1403 // span, as it is the cause of the requirement, and
1404 // `consider_hint_about_removing_semicolon` will point at the last expression
1405 // if it were a relevant part of the error. This improves usability in editors
1406 // that highlight errors inline.
1407 let mut sp = blk.span;
1408 let mut fn_span = None;
1409 if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
1410 let ret_sp = decl.output.span();
1411 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1412 // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
1413 // output would otherwise be incorrect and even misleading. Make sure
1414 // the span we're aiming at correspond to a `fn` body.
1415 if block_sp == blk.span {
1417 fn_span = Some(ident.span);
1421 coerce.coerce_forced_unit(
1425 if let Some(expected_ty) = expected.only_has_type(self) {
1426 if !self.consider_removing_semicolon(blk, expected_ty, err) {
1427 self.consider_returning_binding(blk, expected_ty, err);
1429 if expected_ty == self.tcx.types.bool {
1430 // If this is caused by a missing `let` in a `while let`,
1431 // silence this redundant error, as we already emit E0070.
1433 // Our block must be a `assign desugar local; assignment`
1434 if let Some(hir::Node::Block(hir::Block {
1439 hir::StmtKind::Local(hir::Local {
1441 hir::LocalSource::AssignDesugar(_),
1448 hir::StmtKind::Expr(hir::Expr {
1449 kind: hir::ExprKind::Assign(..),
1456 })) = self.tcx.hir().find(blk.hir_id)
1458 self.comes_from_while_condition(blk.hir_id, |_| {
1459 err.downgrade_to_delayed_bug();
1464 if let Some(fn_span) = fn_span {
1467 "implicitly returns `()` as its body has no tail or `return` \
1479 // If we can break from the block, then the block's exit is always reachable
1480 // (... as long as the entry is reachable) - regardless of the tail of the block.
1481 self.diverges.set(prev_diverges);
1484 let mut ty = ctxt.coerce.unwrap().complete(self);
1486 if self.has_errors.get() || ty.references_error() {
1487 ty = self.tcx.ty_error()
1490 self.write_ty(blk.hir_id, ty);
1496 fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
1497 let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id));
1499 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
1500 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1501 let body = self.tcx.hir().body(body_id);
1502 if let ExprKind::Block(block, _) = &body.value.kind {
1503 return Some(block.span);
1511 /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
1512 fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
1513 let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id));
1514 self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
1517 /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
1518 /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
1519 /// when given code like the following:
1521 /// if false { return 0i32; } else { 1u32 }
1522 /// // ^^^^ point at this instead of the whole `if` expression
1524 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1525 let check_in_progress = |elem: &hir::Expr<'_>| {
1526 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
1527 |_| match elem.kind {
1528 // Point at the tail expression when possible.
1529 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
1535 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
1536 if let Some(rslt) = check_in_progress(el) {
1541 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1542 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1543 if let Some(span) = iter.next() {
1544 if iter.next().is_none() {
1553 fn overwrite_local_ty_if_err(
1556 pat: &'tcx hir::Pat<'tcx>,
1560 if ty.references_error() {
1561 // Override the types everywhere with `err()` to avoid knock on errors.
1562 self.write_ty(hir_id, ty);
1563 self.write_ty(pat.hir_id, ty);
1564 let local_ty = LocalTy { decl_ty, revealed_ty: ty };
1565 self.locals.borrow_mut().insert(hir_id, local_ty);
1566 self.locals.borrow_mut().insert(pat.hir_id, local_ty);
1570 // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
1571 // The newly resolved definition is written into `type_dependent_defs`.
1572 fn finish_resolving_struct_path(
1577 ) -> (Res, Ty<'tcx>) {
1579 QPath::Resolved(ref maybe_qself, ref path) => {
1580 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
1581 let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
1584 QPath::TypeRelative(ref qself, ref segment) => {
1585 let ty = self.to_ty(qself);
1587 let result = <dyn AstConv<'_>>::associated_path_to_ty(
1588 self, hir_id, path_span, ty, qself, segment, true,
1590 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
1591 let result = result.map(|(_, kind, def_id)| (kind, def_id));
1593 // Write back the new resolution.
1594 self.write_resolution(hir_id, result);
1596 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1598 QPath::LangItem(lang_item, span, id) => {
1599 self.resolve_lang_item_path(lang_item, span, hir_id, id)
1604 /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
1605 /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
1606 /// reference a type argument. The reason to walk also the checked type is that the coerced type
1607 /// can be not easily comparable with predicate type (because of coercion). If the types match
1608 /// for either checked or coerced type, and there's only *one* argument that does, we point at
1609 /// the corresponding argument's expression span instead of the `fn` call path span.
1610 fn point_at_arg_instead_of_call_if_possible(
1612 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1613 expr: &'tcx hir::Expr<'tcx>,
1615 args: &'tcx [hir::Expr<'tcx>],
1616 expected_tys: &[Ty<'tcx>],
1618 // We *do not* do this for desugared call spans to keep good diagnostics when involving
1619 // the `?` operator.
1620 if call_sp.desugaring_kind().is_some() {
1624 'outer: for error in errors {
1625 // Only if the cause is somewhere inside the expression we want try to point at arg.
1626 // Otherwise, it means that the cause is somewhere else and we should not change
1627 // anything because we can break the correct span.
1628 if !call_sp.contains(error.obligation.cause.span) {
1632 // Peel derived obligation, because it's the type that originally
1633 // started this inference chain that matters, not the one we wound
1634 // up with at the end.
1635 fn unpeel_to_top<'a, 'tcx>(
1636 mut code: &'a ObligationCauseCode<'tcx>,
1637 ) -> &'a ObligationCauseCode<'tcx> {
1638 let mut result_code = code;
1640 let parent = match code {
1641 ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
1642 ObligationCauseCode::BuiltinDerivedObligation(c)
1643 | ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
1644 _ => break result_code,
1646 (result_code, code) = (code, parent);
1649 let self_: ty::subst::GenericArg<'_> =
1650 match unpeel_to_top(error.obligation.cause.code()) {
1651 ObligationCauseCode::BuiltinDerivedObligation(code)
1652 | ObligationCauseCode::DerivedObligation(code) => {
1653 code.parent_trait_pred.self_ty().skip_binder().into()
1655 ObligationCauseCode::ImplDerivedObligation(code) => {
1656 code.derived.parent_trait_pred.self_ty().skip_binder().into()
1658 _ if let ty::PredicateKind::Trait(predicate) =
1659 error.obligation.predicate.kind().skip_binder() =>
1661 predicate.self_ty().into()
1665 let self_ = self.resolve_vars_if_possible(self_);
1666 let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
1668 let typeck_results = self.typeck_results.borrow();
1670 for (idx, arg) in args.iter().enumerate() {
1671 // Don't adjust the span if we already have a more precise span
1672 // within one of the args.
1673 if arg.span.contains(error.obligation.cause.span) {
1674 let references_arg =
1675 typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
1676 || expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
1677 if references_arg && !arg.span.from_expansion() {
1678 error.obligation.cause.map_code(|parent_code| {
1679 ObligationCauseCode::FunctionArgumentObligation {
1680 arg_hir_id: args[idx].hir_id,
1681 call_hir_id: expr.hir_id,
1690 // Collect the argument position for all arguments that could have caused this
1691 // `FulfillmentError`.
1692 let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
1694 .flat_map(|(idx, (expected_ty, arg))| {
1695 if let Some(arg_ty) = typeck_results.expr_ty_opt(arg) {
1696 vec![(idx, arg_ty), (idx, *expected_ty)]
1701 .filter_map(|(i, ty)| {
1702 let ty = self.resolve_vars_if_possible(ty);
1703 // We walk the argument type because the argument's type could have
1704 // been `Option<T>`, but the `FulfillmentError` references `T`.
1705 if ty_matches_self(ty) { Some(i) } else { None }
1709 // Both checked and coerced types could have matched, thus we need to remove
1712 // We sort primitive type usize here and can use unstable sort
1713 referenced_in.sort_unstable();
1714 referenced_in.dedup();
1716 if let &[idx] = &referenced_in[..] {
1717 // Do not point at the inside of a macro.
1718 // That would often result in poor error messages.
1719 if args[idx].span.from_expansion() {
1722 // We make sure that only *one* argument matches the obligation failure
1723 // and we assign the obligation's span to its expression's.
1724 error.obligation.cause.span = args[idx].span;
1725 error.obligation.cause.map_code(|parent_code| {
1726 ObligationCauseCode::FunctionArgumentObligation {
1727 arg_hir_id: args[idx].hir_id,
1728 call_hir_id: expr.hir_id,
1732 } else if error.obligation.cause.span == call_sp {
1733 // Make function calls point at the callee, not the whole thing.
1734 if let hir::ExprKind::Call(callee, _) = expr.kind {
1735 error.obligation.cause.span = callee.span;
1741 /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
1742 /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
1743 /// were caused by them. If they were, we point at the corresponding type argument's span
1744 /// instead of the `fn` call path span.
1745 fn point_at_type_arg_instead_of_call_if_possible(
1747 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1748 call_expr: &'tcx hir::Expr<'tcx>,
1750 if let hir::ExprKind::Call(path, _) = &call_expr.kind {
1751 if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
1752 for error in errors {
1753 if let ty::PredicateKind::Trait(predicate) =
1754 error.obligation.predicate.kind().skip_binder()
1756 // If any of the type arguments in this path segment caused the
1757 // `FulfillmentError`, point at its span (#61860).
1761 .filter_map(|seg| seg.args.as_ref())
1762 .flat_map(|a| a.args.iter())
1764 if let hir::GenericArg::Type(hir_ty) = &arg
1766 self.typeck_results.borrow().node_type_opt(hir_ty.hir_id)
1767 && self.resolve_vars_if_possible(ty) == predicate.self_ty()
1769 error.obligation.cause.span = hir_ty.span;
1781 err: &mut Diagnostic,
1782 callable_def_id: Option<DefId>,
1783 callee_ty: Option<Ty<'tcx>>,
1785 let Some(mut def_id) = callable_def_id else {
1789 if let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1790 // Possibly points at either impl or trait item, so try to get it
1791 // to point to trait item, then get the parent.
1792 // This parent might be an impl in the case of an inherent function,
1793 // but the next check will fail.
1794 && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
1795 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1796 // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
1797 && let Some(call_kind) = ty::ClosureKind::from_def_id(self.tcx, maybe_trait_def_id)
1798 && let Some(callee_ty) = callee_ty
1800 let callee_ty = callee_ty.peel_refs();
1801 match *callee_ty.kind() {
1802 ty::Param(param) => {
1804 self.tcx.generics_of(self.body_id.owner).type_param(¶m, self.tcx);
1805 if param.kind.is_synthetic() {
1806 // if it's `impl Fn() -> ..` then just fall down to the def-id based logic
1807 def_id = param.def_id;
1809 // Otherwise, find the predicate that makes this generic callable,
1810 // and point at that.
1811 let instantiated = self
1813 .explicit_predicates_of(self.body_id.owner)
1814 .instantiate_identity(self.tcx);
1815 // FIXME(compiler-errors): This could be problematic if something has two
1816 // fn-like predicates with different args, but callable types really never
1817 // do that, so it's OK.
1818 for (predicate, span) in
1819 std::iter::zip(instantiated.predicates, instantiated.spans)
1821 if let ty::PredicateKind::Trait(pred) = predicate.kind().skip_binder()
1822 && pred.self_ty().peel_refs() == callee_ty
1823 && ty::ClosureKind::from_def_id(self.tcx, pred.def_id()).is_some()
1825 err.span_note(span, "callable defined here");
1831 ty::Opaque(new_def_id, _)
1832 | ty::Closure(new_def_id, _)
1833 | ty::FnDef(new_def_id, _) => {
1834 def_id = new_def_id;
1837 // Look for a user-provided impl of a `Fn` trait, and point to it.
1838 let new_def_id = self.probe(|_| {
1839 let trait_ref = ty::TraitRef::new(
1840 call_kind.to_def_id(self.tcx),
1841 self.tcx.mk_substs([
1842 ty::GenericArg::from(callee_ty),
1843 self.next_ty_var(TypeVariableOrigin {
1844 kind: TypeVariableOriginKind::MiscVariable,
1845 span: rustc_span::DUMMY_SP,
1850 let obligation = traits::Obligation::new(
1851 traits::ObligationCause::dummy(),
1853 ty::Binder::dummy(ty::TraitPredicate {
1855 constness: ty::BoundConstness::NotConst,
1856 polarity: ty::ImplPolarity::Positive,
1859 match SelectionContext::new(&self).select(&obligation) {
1860 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1861 Some(impl_source.impl_def_id)
1866 if let Some(new_def_id) = new_def_id {
1867 def_id = new_def_id;
1875 if let Some(def_span) = self.tcx.def_ident_span(def_id) && !def_span.is_dummy() {
1876 let mut spans: MultiSpan = def_span.into();
1881 .get_if_local(def_id)
1882 .and_then(|node| node.body_id())
1884 .flat_map(|id| self.tcx.hir().body(id).params);
1886 for param in params {
1887 spans.push_span_label(param.span, "");
1890 let def_kind = self.tcx.def_kind(def_id);
1891 err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
1893 let def_kind = self.tcx.def_kind(def_id);
1895 self.tcx.def_span(def_id),
1896 &format!("{} defined here", def_kind.descr(def_id)),