1 use crate::coercion::CoerceMany;
2 use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
3 use crate::gather_locals::Declaration;
4 use crate::method::MethodCallee;
5 use crate::Expectation::*;
6 use crate::TupleArgumentsFlag::*;
8 struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy,
12 use rustc_data_structures::fx::FxIndexSet;
13 use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
15 use rustc_hir::def::{CtorOf, DefKind, Res};
16 use rustc_hir::def_id::DefId;
17 use rustc_hir::{ExprKind, Node, QPath};
18 use rustc_hir_analysis::astconv::AstConv;
19 use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
20 use rustc_hir_analysis::check::potentially_plural_count;
21 use rustc_hir_analysis::structured_errors::StructuredDiagnostic;
22 use rustc_index::vec::IndexVec;
23 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
24 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
25 use rustc_infer::infer::InferOk;
26 use rustc_infer::infer::TypeTrace;
27 use rustc_middle::ty::adjustment::AllowTwoPhase;
28 use rustc_middle::ty::visit::TypeVisitable;
29 use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
30 use rustc_session::Session;
31 use rustc_span::symbol::{kw, Ident};
32 use rustc_span::{self, sym, Span};
33 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
39 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
40 pub(in super::super) fn check_casts(&mut self) {
41 // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors
42 // when writing to `self.param_env`.
43 let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
45 debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
46 for cast in deferred_cast_checks.drain(..) {
47 let prev_env = self.param_env;
48 self.param_env = self.param_env.with_constness(cast.constness);
52 self.param_env = prev_env;
55 *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
58 pub(in super::super) fn check_transmutes(&self) {
59 let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
60 debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
61 for (from, to, hir_id) in deferred_transmute_checks.drain(..) {
62 self.check_transmute(from, to, hir_id);
66 pub(in super::super) fn check_asms(&self) {
67 let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
68 debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
69 for (asm, hir_id) in deferred_asm_checks.drain(..) {
70 let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
71 let get_operand_ty = |expr| {
72 let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
73 let ty = self.resolve_vars_if_possible(ty);
74 if ty.has_non_region_infer() {
77 self.tcx.erase_regions(ty)
80 InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty)
81 .check_asm(asm, enclosing_id);
85 pub(in super::super) fn check_method_argument_types(
88 expr: &'tcx hir::Expr<'tcx>,
89 method: Result<MethodCallee<'tcx>, ()>,
90 args_no_rcvr: &'tcx [hir::Expr<'tcx>],
91 tuple_arguments: TupleArgumentsFlag,
92 expected: Expectation<'tcx>,
94 let has_error = match method {
95 Ok(method) => method.substs.references_error() || method.sig.references_error(),
99 let err_inputs = self.err_args(args_no_rcvr.len());
101 let err_inputs = match tuple_arguments {
102 DontTupleArguments => err_inputs,
103 TupleArguments => vec![self.tcx.intern_tup(&err_inputs)],
106 self.check_argument_types(
114 method.ok().map(|method| method.def_id),
116 return self.tcx.ty_error();
119 let method = method.unwrap();
120 // HACK(eddyb) ignore self in the definition (see above).
121 let expected_input_tys = self.expected_inputs_for_expected_output(
125 &method.sig.inputs()[1..],
127 self.check_argument_types(
130 &method.sig.inputs()[1..],
133 method.sig.c_variadic,
141 /// Generic function that factors out common logic from function calls,
142 /// method calls and overloaded operators.
143 pub(in super::super) fn check_argument_types(
145 // Span enclosing the call site
147 // Expression of the call site
148 call_expr: &'tcx hir::Expr<'tcx>,
149 // Types (as defined in the *signature* of the target function)
150 formal_input_tys: &[Ty<'tcx>],
151 // More specific expected types, after unifying with caller output types
152 expected_input_tys: Option<Vec<Ty<'tcx>>>,
153 // The expressions for each provided argument
154 provided_args: &'tcx [hir::Expr<'tcx>],
155 // Whether the function is variadic, for example when imported from C
157 // Whether the arguments have been bundled in a tuple (ex: closures)
158 tuple_arguments: TupleArgumentsFlag,
159 // The DefId for the function being called, for better error messages
160 fn_def_id: Option<DefId>,
164 // Conceptually, we've got some number of expected inputs, and some number of provided arguments
165 // and we can form a grid of whether each argument could satisfy a given input:
166 // in1 | in2 | in3 | ...
171 // Initially, we just check the diagonal, because in the case of correct code
172 // these are the only checks that matter
173 // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
174 // better error messages about invalid method calls.
176 // All the input types from the fn signature must outlive the call
177 // so as to validate implied bounds.
178 for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
179 self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
182 let mut err_code = "E0061";
184 // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
185 let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
186 let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
187 match tuple_type.kind() {
188 // We expected a tuple and got a tuple
189 ty::Tuple(arg_types) => {
190 // Argument length differs
191 if arg_types.len() != provided_args.len() {
194 let expected_input_tys = match expected_input_tys {
195 Some(expected_input_tys) => match expected_input_tys.get(0) {
196 Some(ty) => match ty.kind() {
197 ty::Tuple(tys) => Some(tys.iter().collect()),
204 (arg_types.iter().collect(), expected_input_tys)
207 // Otherwise, there's a mismatch, so clear out what we're expecting, and set
208 // our input types to err_args so we don't blow up the error messages
213 "cannot use call notation; the first type parameter \
214 for the function trait is neither a tuple nor unit"
217 (self.err_args(provided_args.len()), None)
221 (formal_input_tys.to_vec(), expected_input_tys)
224 // If there are no external expectations at the call site, just use the types from the function defn
225 let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
226 assert_eq!(expected_input_tys.len(), formal_input_tys.len());
229 formal_input_tys.clone()
232 let minimum_input_count = expected_input_tys.len();
233 let provided_arg_count = provided_args.len();
235 let is_const_eval_select = matches!(fn_def_id, Some(def_id) if
236 self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
237 && self.tcx.is_intrinsic(def_id)
238 && self.tcx.item_name(def_id) == sym::const_eval_select);
240 // We introduce a helper function to demand that a given argument satisfy a given input
241 // This is more complicated than just checking type equality, as arguments could be coerced
242 // This version writes those types back so further type checking uses the narrowed types
243 let demand_compatible = |idx| {
244 let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
245 let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
246 let provided_arg = &provided_args[idx];
248 debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
250 // We're on the happy path here, so we'll do a more involved check and write back types
251 // To check compatibility, we'll do 3 things:
252 // 1. Unify the provided argument with the expected type
253 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
255 let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
257 // 2. Coerce to the most detailed type that could be coerced
258 // to, which is `expected_ty` if `rvalue_hint` returns an
259 // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
260 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
262 // Cause selection errors caused by resolving a single argument to point at the
263 // argument and not the call. This lets us customize the span pointed to in the
264 // fulfillment error to be more accurate.
265 let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
267 let coerce_error = self
268 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
271 if coerce_error.is_some() {
272 return Compatibility::Incompatible(coerce_error);
275 // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
276 // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
277 // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
279 // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
280 if is_const_eval_select && (1..=2).contains(&idx) {
281 if let ty::FnDef(def_id, _) = checked_ty.kind() {
282 if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) {
285 .struct_span_err(provided_arg.span, "this argument must be a `const fn`")
286 .help("consult the documentation on `const_eval_select` for more information")
292 .struct_span_err(provided_arg.span, "this argument must be a function item")
293 .note(format!("expected a function item, found {checked_ty}"))
295 "consult the documentation on `const_eval_select` for more information",
301 // 3. Check if the formal type is a supertype of the checked one
302 // and register any such obligations for future type checks
303 let supertype_error = self
304 .at(&self.misc(provided_arg.span), self.param_env)
305 .sup(formal_input_ty, coerced_ty);
306 let subtyping_error = match supertype_error {
307 Ok(InferOk { obligations, value: () }) => {
308 self.register_predicates(obligations);
311 Err(err) => Some(err),
314 // If neither check failed, the types are compatible
315 match subtyping_error {
316 None => Compatibility::Compatible,
317 Some(_) => Compatibility::Incompatible(subtyping_error),
321 // To start, we only care "along the diagonal", where we expect every
322 // provided arg to be in the right spot
323 let mut compatibility_diagonal =
324 vec![Compatibility::Incompatible(None); provided_args.len()];
326 // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
327 // if the wrong number of arguments were supplied, we CAN'T be satisfied,
328 // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
329 // otherwise, they need to be identical, because rust doesn't currently support variadic functions
330 let mut call_appears_satisfied = if c_variadic {
331 provided_arg_count >= minimum_input_count
333 provided_arg_count == minimum_input_count
336 // Check the arguments.
337 // We do this in a pretty awful way: first we type-check any arguments
338 // that are not closures, then we type-check the closures. This is so
339 // that we have more information about the types of arguments when we
340 // type-check the functions. This isn't really the right way to do this.
341 for check_closures in [false, true] {
342 // More awful hacks: before we check argument types, try to do
343 // an "opportunistic" trait resolution of any trait bounds on
344 // the call. This helps coercions.
346 self.select_obligations_where_possible(|_| {})
349 // Check each argument, to satisfy the input it was provided for
350 // Visually, we're traveling down the diagonal of the compatibility matrix
351 for (idx, arg) in provided_args.iter().enumerate() {
352 // Warn only for the first loop (the "no closures" one).
353 // Closure arguments themselves can't be diverging, but
354 // a previous argument can, e.g., `foo(panic!(), || {})`.
356 self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
359 // For C-variadic functions, we don't have a declared type for all of
360 // the arguments hence we only do our usual type checking with
361 // the arguments who's types we do know. However, we *can* check
362 // for unreachable expressions (see above).
363 // FIXME: unreachable warning current isn't emitted
364 if idx >= minimum_input_count {
368 let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
369 if is_closure != check_closures {
373 let compatible = demand_compatible(idx);
374 let is_compatible = matches!(compatible, Compatibility::Compatible);
375 compatibility_diagonal[idx] = compatible;
378 call_appears_satisfied = false;
383 if c_variadic && provided_arg_count < minimum_input_count {
387 for arg in provided_args.iter().skip(minimum_input_count) {
388 // Make sure we've checked this expr at least once.
389 let arg_ty = self.check_expr(&arg);
391 // If the function is c-style variadic, we skipped a bunch of arguments
392 // so we need to check those, and write out the types
393 // Ideally this would be folded into the above, for uniform style
394 // but c-variadic is already a corner case
396 fn variadic_error<'tcx>(
402 use rustc_hir_analysis::structured_errors::MissingCastForVariadicArg;
404 MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
407 // There are a few types which get autopromoted when passed via varargs
408 // in C but we just error out instead and require explicit casts.
409 let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
410 match arg_ty.kind() {
411 ty::Float(ty::FloatTy::F32) => {
412 variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
414 ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
415 variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
417 ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
418 variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
421 let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
422 let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
423 variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
430 if !call_appears_satisfied {
431 let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
432 let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
438 formal_input_tys.len(),
439 expected_input_tys.len(),
440 "expected formal_input_tys to be the same size as expected_input_tys"
442 let formal_and_expected_inputs = IndexVec::from_iter(
446 .zip(expected_input_tys.iter().copied())
447 .map(|vars| self.resolve_vars_if_possible(vars)),
450 self.report_arg_errors(
451 compatibility_diagonal,
452 formal_and_expected_inputs,
463 fn report_arg_errors(
465 compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
466 formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
467 provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
470 fn_def_id: Option<DefId>,
472 call_expr: &hir::Expr<'tcx>,
474 // Next, let's construct the error
475 let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind {
477 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
480 if let Res::Def(DefKind::Ctor(of, _), _) =
481 self.typeck_results.borrow().qpath_res(qpath, *hir_id)
483 let name = match of {
484 CtorOf::Struct => "struct",
485 CtorOf::Variant => "enum variant",
487 (call_span, *span, name, false)
489 (call_span, *span, "function", false)
492 hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, "function", false),
493 hir::ExprKind::MethodCall(path_segment, _, _, span) => {
494 let ident_span = path_segment.ident.span;
495 let ident_span = if let Some(args) = path_segment.args {
496 ident_span.with_hi(args.span_ext.hi())
500 (*span, ident_span, "method", true)
502 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
504 let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
506 // Don't print if it has error types or is just plain `_`
507 fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
508 tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
512 // FIXME: taint after emitting errors and pass through an `ErrorGuaranteed`
513 self.set_tainted_by_errors(
514 tcx.sess.delay_span_bug(call_span, "no errors reported for args"),
517 // Get the argument span in the context of the call span so that
518 // suggestions and labels are (more) correct when an arg is a
520 let normalize_span = |span: Span| -> Span {
521 let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span);
522 // Sometimes macros mess up the spans, so do not normalize the
523 // arg span to equal the error span, because that's less useful
524 // than pointing out the arg expr in the wrong context.
525 if normalized_span.source_equal(error_span) { span } else { normalized_span }
528 // Precompute the provided types and spans, since that's all we typically need for below
529 let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
535 .expr_ty_adjusted_opt(*expr)
536 .unwrap_or_else(|| tcx.ty_error());
537 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
540 let callee_expr = match &call_expr.peel_blocks().kind {
541 hir::ExprKind::Call(callee, _) => Some(*callee),
542 hir::ExprKind::MethodCall(_, receiver, ..) => {
543 if let Some((DefKind::AssocFn, def_id)) =
544 self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
545 && let Some(assoc) = tcx.opt_associated_item(def_id)
546 && assoc.fn_has_self_parameter
555 let callee_ty = callee_expr
556 .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
558 // A "softer" version of the `demand_compatible`, which checks types without persisting them,
559 // and treats error types differently
560 // This will allow us to "probe" for other argument orders that would likely have been correct
561 let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
562 if provided_idx.as_usize() == expected_idx.as_usize() {
563 return compatibility_diagonal[provided_idx].clone();
566 let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
567 // If either is an error type, we defy the usual convention and consider them to *not* be
568 // coercible. This prevents our error message heuristic from trying to pass errors into
570 if (formal_input_ty, expected_input_ty).references_error() {
571 return Compatibility::Incompatible(None);
574 let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
576 let expectation = Expectation::rvalue_hint(self, expected_input_ty);
577 let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
578 let can_coerce = self.can_coerce(arg_ty, coerced_ty);
580 return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
581 ty::error::ExpectedFound::new(true, coerced_ty, arg_ty),
585 // Using probe here, since we don't want this subtyping to affect inference.
586 let subtyping_error = self.probe(|_| {
587 self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err()
590 // Same as above: if either the coerce type or the checked type is an error type,
591 // consider them *not* compatible.
592 let references_error = (coerced_ty, arg_ty).references_error();
593 match (references_error, subtyping_error) {
594 (false, None) => Compatibility::Compatible,
595 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
599 let mk_trace = |span, (formal_ty, expected_ty), provided_ty| {
600 let mismatched_ty = if expected_ty == provided_ty {
601 // If expected == provided, then we must have failed to sup
602 // the formal type. Avoid printing out "expected Ty, found Ty"
608 TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty)
611 // The algorithm here is inspired by levenshtein distance and longest common subsequence.
612 // We'll try to detect 4 different types of mistakes:
613 // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
614 // - An input is missing, which isn't satisfied by *any* of the other arguments
615 // - Some number of arguments have been provided in the wrong order
616 // - A type is straight up invalid
618 // First, let's find the errors
619 let (mut errors, matched_inputs) =
620 ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
623 // First, check if we just need to wrap some arguments in a tuple.
624 if let Some((mismatch_idx, terr)) =
625 compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {
626 if let Compatibility::Incompatible(Some(terr)) = c {
633 // Is the first bad expected argument a tuple?
634 // Do we have as many extra provided arguments as the tuple's length?
635 // If so, we might have just forgotten to wrap some args in a tuple.
636 if let Some(ty::Tuple(tys)) =
637 formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
638 // If the tuple is unit, we're not actually wrapping any arguments.
640 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
642 // Wrap up the N provided arguments starting at this position in a tuple.
643 let provided_as_tuple = tcx.mk_tup(
644 provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
647 let mut satisfied = true;
648 // Check if the newly wrapped tuple + rest of the arguments are compatible.
649 for ((_, expected_ty), provided_ty) in std::iter::zip(
650 formal_and_expected_inputs.iter().skip(mismatch_idx),
651 [provided_as_tuple].into_iter().chain(
652 provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
655 if !self.can_coerce(provided_ty, *expected_ty) {
661 // If they're compatible, suggest wrapping in an arg, and we're done!
662 // Take some care with spans, so we don't suggest wrapping a macro's
663 // innards in parenthesis, for example.
665 && let Some((_, lo)) =
666 provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx))
667 && let Some((_, hi)) =
668 provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1))
672 // A tuple wrap suggestion actually occurs within,
673 // so don't do anything special here.
674 err = self.err_ctxt().report_and_explain_type_error(
677 formal_and_expected_inputs[mismatch_idx.into()],
678 provided_arg_tys[mismatch_idx.into()].0,
684 format!("arguments to this {} are incorrect", call_name),
687 err = tcx.sess.struct_span_err_with_code(
690 "{call_name} takes {}{} but {} {} supplied",
691 if c_variadic { "at least " } else { "" },
692 potentially_plural_count(
693 formal_and_expected_inputs.len(),
696 potentially_plural_count(provided_args.len(), "argument"),
697 pluralize!("was", provided_args.len())
699 DiagnosticId::Error(err_code.to_owned()),
701 err.multipart_suggestion_verbose(
702 "wrap these arguments in parentheses to construct a tuple",
704 (lo.shrink_to_lo(), "(".to_string()),
705 (hi.shrink_to_hi(), ")".to_string()),
707 Applicability::MachineApplicable,
723 // Okay, so here's where it gets complicated in regards to what errors
725 // There are 3 different "types" of errors we might encounter.
726 // 1) Missing/extra/swapped arguments
727 // 2) Valid but incorrect arguments
728 // 3) Invalid arguments
729 // - Currently I think this only comes up with `CyclicTy`
731 // We first need to go through, remove those from (3) and emit those
732 // as their own error, particularly since they're error code and
733 // message is special. From what I can tell, we *must* emit these
734 // here (vs somewhere prior to this function) since the arguments
735 // become invalid *because* of how they get used in the function.
738 if errors.is_empty() {
739 if cfg!(debug_assertions) {
740 span_bug!(error_span, "expected errors from argument matrix");
745 "argument type mismatch was detected, \
746 but rustc had trouble determining where",
749 "we would appreciate a bug report: \
750 https://github.com/rust-lang/rust/issues/new",
757 errors.drain_filter(|error| {
758 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
759 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
760 let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
761 if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
762 self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
768 // We're done if we found errors, but we already emitted them.
769 if errors.is_empty() {
773 // Okay, now that we've emitted the special errors separately, we
774 // are only left missing/extra/swapped and mismatched arguments, both
775 // can be collated pretty easily if needed.
777 // Next special case: if there is only one "Incompatible" error, just emit that
779 Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
782 let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
783 let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
784 let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
785 let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
786 self.emit_coerce_suggestions(
788 &provided_args[*provided_idx],
790 Expectation::rvalue_hint(self, expected_ty)
792 .unwrap_or(formal_ty),
798 format!("arguments to this {} are incorrect", call_name),
800 if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
801 (callee_ty, &call_expr.kind)
803 // Type that would have accepted this argument if it hadn't been inferred earlier.
804 // FIXME: We leave an inference variable for now, but it'd be nice to get a more
805 // specific type to increase the accuracy of the diagnostic.
806 let expected = self.infcx.next_ty_var(TypeVariableOrigin {
807 kind: TypeVariableOriginKind::MiscVariable,
808 span: full_call_span,
810 self.point_at_expr_source_of_inferred_type(
818 // Call out where the function is defined
823 Some(expected_idx.as_usize()),
830 let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
835 "arguments to this {} are incorrect",
839 tcx.sess.struct_span_err_with_code(
842 "this {} takes {}{} but {} {} supplied",
844 if c_variadic { "at least " } else { "" },
845 potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
846 potentially_plural_count(provided_args.len(), "argument"),
847 pluralize!("was", provided_args.len())
849 DiagnosticId::Error(err_code.to_owned()),
853 // As we encounter issues, keep track of what we want to provide for the suggestion
854 let mut labels = vec![];
855 // If there is a single error, we give a specific suggestion; otherwise, we change to
856 // "did you mean" with the suggested function call
857 enum SuggestionText {
865 let mut suggestion_text = SuggestionText::None;
867 let mut errors = errors.into_iter().peekable();
868 while let Some(error) = errors.next() {
870 Error::Invalid(provided_idx, expected_idx, compatibility) => {
871 let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
872 let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
873 if let Compatibility::Incompatible(error) = compatibility {
874 let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
875 if let Some(e) = error {
876 self.err_ctxt().note_type_err(
888 self.emit_coerce_suggestions(
890 &provided_args[provided_idx],
892 Expectation::rvalue_hint(self, expected_ty)
894 .unwrap_or(formal_ty),
899 Error::Extra(arg_idx) => {
900 let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
901 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
902 // FIXME: not suggestable, use something else
903 format!(" of type `{}`", provided_ty)
908 .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
909 suggestion_text = match suggestion_text {
910 SuggestionText::None => SuggestionText::Remove(false),
911 SuggestionText::Remove(_) => SuggestionText::Remove(true),
912 _ => SuggestionText::DidYouMean,
915 Error::Missing(expected_idx) => {
916 // If there are multiple missing arguments adjacent to each other,
917 // then we can provide a single error.
919 let mut missing_idxs = vec![expected_idx];
920 while let Some(e) = errors.next_if(|e| {
921 matches!(e, Error::Missing(next_expected_idx)
922 if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
925 Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
930 // NOTE: Because we might be re-arranging arguments, might have extra
931 // arguments, etc. it's hard to *really* know where we should provide
932 // this error label, so as a heuristic, we point to the provided arg, or
933 // to the call if the missing inputs pass the provided args.
934 match &missing_idxs[..] {
936 let (_, input_ty) = formal_and_expected_inputs[expected_idx];
937 let span = if let Some((_, arg_span)) =
938 provided_arg_tys.get(expected_idx.to_provided_idx())
944 let rendered = if !has_error_or_infer([input_ty]) {
945 format!(" of type `{}`", input_ty)
949 labels.push((span, format!("an argument{} is missing", rendered)));
950 suggestion_text = match suggestion_text {
951 SuggestionText::None => SuggestionText::Provide(false),
952 SuggestionText::Provide(_) => SuggestionText::Provide(true),
953 _ => SuggestionText::DidYouMean,
956 &[first_idx, second_idx] => {
957 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
958 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
959 let span = if let (Some((_, first_span)), Some((_, second_span))) = (
960 provided_arg_tys.get(first_idx.to_provided_idx()),
961 provided_arg_tys.get(second_idx.to_provided_idx()),
963 first_span.to(*second_span)
968 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
970 " of type `{}` and `{}`",
971 first_expected_ty, second_expected_ty
976 labels.push((span, format!("two arguments{} are missing", rendered)));
977 suggestion_text = match suggestion_text {
978 SuggestionText::None | SuggestionText::Provide(_) => {
979 SuggestionText::Provide(true)
981 _ => SuggestionText::DidYouMean,
984 &[first_idx, second_idx, third_idx] => {
985 let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
986 let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
987 let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
988 let span = if let (Some((_, first_span)), Some((_, third_span))) = (
989 provided_arg_tys.get(first_idx.to_provided_idx()),
990 provided_arg_tys.get(third_idx.to_provided_idx()),
992 first_span.to(*third_span)
996 let rendered = if !has_error_or_infer([
1002 " of type `{}`, `{}`, and `{}`",
1003 first_expected_ty, second_expected_ty, third_expected_ty
1008 labels.push((span, format!("three arguments{} are missing", rendered)));
1009 suggestion_text = match suggestion_text {
1010 SuggestionText::None | SuggestionText::Provide(_) => {
1011 SuggestionText::Provide(true)
1013 _ => SuggestionText::DidYouMean,
1017 let first_idx = *missing_idxs.first().unwrap();
1018 let last_idx = *missing_idxs.last().unwrap();
1019 // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
1020 // It's hard to *really* know where we should provide this error label, so this is a
1022 let span = if let (Some((_, first_span)), Some((_, last_span))) = (
1023 provided_arg_tys.get(first_idx.to_provided_idx()),
1024 provided_arg_tys.get(last_idx.to_provided_idx()),
1026 first_span.to(*last_span)
1030 labels.push((span, "multiple arguments are missing".to_string()));
1031 suggestion_text = match suggestion_text {
1032 SuggestionText::None | SuggestionText::Provide(_) => {
1033 SuggestionText::Provide(true)
1035 _ => SuggestionText::DidYouMean,
1042 second_provided_idx,
1044 second_expected_idx,
1046 let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
1047 let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
1048 let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
1049 format!(", found `{}`", first_provided_ty)
1055 format!("expected `{}`{}", first_expected_ty, first_provided_ty_name),
1058 let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
1059 let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
1060 let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
1061 format!(", found `{}`", second_provided_ty)
1067 format!("expected `{}`{}", second_expected_ty, second_provided_ty_name),
1070 suggestion_text = match suggestion_text {
1071 SuggestionText::None => SuggestionText::Swap,
1072 _ => SuggestionText::DidYouMean,
1075 Error::Permutation(args) => {
1076 for (dst_arg, dest_input) in args {
1077 let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
1078 let (provided_ty, provided_span) = provided_arg_tys[dest_input];
1079 let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1080 format!(", found `{}`", provided_ty)
1086 format!("expected `{}`{}", expected_ty, provided_ty_name),
1090 suggestion_text = match suggestion_text {
1091 SuggestionText::None => SuggestionText::Reorder,
1092 _ => SuggestionText::DidYouMean,
1098 // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
1099 if labels.len() <= 5 {
1100 for (span, label) in labels {
1101 err.span_label(span, label);
1105 // Call out where the function is defined
1106 self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method);
1108 // And add a suggestion block for all of the parameters
1109 let suggestion_text = match suggestion_text {
1110 SuggestionText::None => None,
1111 SuggestionText::Provide(plural) => {
1112 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
1114 SuggestionText::Remove(plural) => {
1115 Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
1117 SuggestionText::Swap => Some("swap these arguments".to_string()),
1118 SuggestionText::Reorder => Some("reorder these arguments".to_string()),
1119 SuggestionText::DidYouMean => Some("did you mean".to_string()),
1121 if let Some(suggestion_text) = suggestion_text {
1122 let source_map = self.sess().source_map();
1123 let (mut suggestion, suggestion_span) =
1124 if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) {
1125 ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
1130 source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
1131 fn_def_id.map_or("".to_string(), |fn_def_id| {
1132 tcx.item_name(fn_def_id).to_string()
1139 let mut needs_comma = false;
1140 for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1146 let suggestion_text = if let Some(provided_idx) = provided_idx
1147 && let (_, provided_span) = provided_arg_tys[*provided_idx]
1148 && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
1152 // Propose a placeholder of the correct type
1153 let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1154 if expected_ty.is_unit() {
1156 } else if expected_ty.is_suggestable(tcx, false) {
1157 format!("/* {} */", expected_ty)
1158 } else if let Some(fn_def_id) = fn_def_id
1159 && self.tcx.def_kind(fn_def_id).is_fn_like()
1160 && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
1161 && let Some(arg) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
1162 && arg.name != kw::SelfLower
1164 format!("/* {} */", arg.name)
1166 "/* value */".to_string()
1169 suggestion += &suggestion_text;
1172 err.span_suggestion_verbose(
1176 Applicability::HasPlaceholders,
1183 // AST fragment checking
1184 pub(in super::super) fn check_lit(
1187 expected: Expectation<'tcx>,
1192 ast::LitKind::Str(..) => tcx.mk_static_str(),
1193 ast::LitKind::ByteStr(ref v, _) => {
1194 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
1196 ast::LitKind::Byte(_) => tcx.types.u8,
1197 ast::LitKind::Char(_) => tcx.types.char,
1198 ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)),
1199 ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)),
1200 ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
1201 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1202 ty::Int(_) | ty::Uint(_) => Some(ty),
1203 ty::Char => Some(tcx.types.u8),
1204 ty::RawPtr(..) => Some(tcx.types.usize),
1205 ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
1208 opt_ty.unwrap_or_else(|| self.next_int_var())
1210 ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
1211 tcx.mk_mach_float(ty::float_ty(t))
1213 ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1214 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1215 ty::Float(_) => Some(ty),
1218 opt_ty.unwrap_or_else(|| self.next_float_var())
1220 ast::LitKind::Bool(_) => tcx.types.bool,
1221 ast::LitKind::Err => tcx.ty_error(),
1225 pub fn check_struct_path(
1229 ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
1230 let path_span = qpath.span();
1231 let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1232 let variant = match def {
1234 self.set_tainted_by_errors(
1235 self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted"),
1239 Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
1241 Some((adt.variant_of_res(def), adt.did(), Self::user_substs_for_adt(ty)))
1243 _ => bug!("unexpected type: {:?}", ty.normalized),
1245 Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1246 | Res::SelfTyParam { .. }
1247 | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
1248 Some(adt) if !adt.is_enum() => {
1249 Some((adt.non_enum_variant(), adt.did(), Self::user_substs_for_adt(ty)))
1253 _ => bug!("unexpected definition: {:?}", def),
1256 if let Some((variant, did, ty::UserSubsts { substs, user_self_ty })) = variant {
1257 debug!("check_struct_path: did={:?} substs={:?}", did, substs);
1259 // Register type annotation.
1260 self.write_user_type_annotation_from_substs(hir_id, did, substs, user_self_ty);
1262 // Check bounds on type arguments used in the path.
1263 self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
1265 Some((variant, ty.normalized))
1267 match ty.normalized.kind() {
1269 // E0071 might be caused by a spelling error, which will have
1270 // already caused an error message and probably a suggestion
1271 // elsewhere. Refrain from emitting more unhelpful errors here
1279 "expected struct, variant or union type, found {}",
1280 ty.normalized.sort_string(self.tcx)
1282 .span_label(path_span, "not a struct")
1290 pub fn check_decl_initializer(
1293 pat: &'tcx hir::Pat<'tcx>,
1294 init: &'tcx hir::Expr<'tcx>,
1296 // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
1297 // for #42640 (default match binding modes).
1300 let ref_bindings = pat.contains_explicit_ref_binding();
1302 let local_ty = self.local_ty(init.span, hir_id).revealed_ty;
1303 if let Some(m) = ref_bindings {
1304 // Somewhat subtle: if we have a `ref` binding in the pattern,
1305 // we want to avoid introducing coercions for the RHS. This is
1306 // both because it helps preserve sanity and, in the case of
1307 // ref mut, for soundness (issue #23116). In particular, in
1308 // the latter case, we need to be clear that the type of the
1309 // referent for the reference that results is *equal to* the
1310 // type of the place it is referencing, and not some
1311 // supertype thereof.
1312 let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1313 self.demand_eqtype(init.span, local_ty, init_ty);
1316 self.check_expr_coercable_to_type(init, local_ty, None)
1320 pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
1321 // Determine and write the type which we'll check the pattern against.
1322 let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty;
1323 self.write_ty(decl.hir_id, decl_ty);
1325 // Type check the initializer.
1326 if let Some(ref init) = decl.init {
1327 let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
1328 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
1331 // Does the expected pattern type originate from an expression and what is the span?
1332 let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1333 (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
1334 (_, Some(init)) => {
1335 (true, Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
1336 } // No explicit type; so use the scrutinee.
1337 _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
1340 // Type check the pattern. Override if necessary to avoid knock-on errors.
1341 self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
1342 let pat_ty = self.node_ty(decl.pat.hir_id);
1343 self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
1345 if let Some(blk) = decl.els {
1346 let previous_diverges = self.diverges.get();
1347 let else_ty = self.check_block_with_expected(blk, NoExpectation);
1348 let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1349 if let Some(mut err) =
1350 self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1354 self.diverges.set(previous_diverges);
1358 /// Type check a `let` statement.
1359 pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
1360 self.check_decl(local.into());
1363 pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
1364 // Don't do all the complex logic below for `DeclItem`.
1366 hir::StmtKind::Item(..) => return,
1367 hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1370 self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1372 // Hide the outer diverging and `has_errors` flags.
1373 let old_diverges = self.diverges.replace(Diverges::Maybe);
1376 hir::StmtKind::Local(l) => {
1377 self.check_decl_local(l);
1380 hir::StmtKind::Item(_) => {}
1381 hir::StmtKind::Expr(ref expr) => {
1382 // Check with expected type of `()`.
1383 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
1384 if expr.can_have_side_effects() {
1385 self.suggest_semicolon_at_end(expr.span, err);
1389 hir::StmtKind::Semi(ref expr) => {
1390 // All of this is equivalent to calling `check_expr`, but it is inlined out here
1391 // in order to capture the fact that this `match` is the last statement in its
1392 // function. This is done for better suggestions to remove the `;`.
1393 let expectation = match expr.kind {
1394 hir::ExprKind::Match(..) if is_last => IsLast(stmt.span),
1397 self.check_expr_with_expectation(expr, expectation);
1401 // Combine the diverging and `has_error` flags.
1402 self.diverges.set(self.diverges.get() | old_diverges);
1405 pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1406 let unit = self.tcx.mk_unit();
1407 let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
1409 // if the block produces a `!` value, that can always be
1410 // (effectively) coerced to unit.
1412 self.demand_suptype(blk.span, unit, ty);
1416 pub(in super::super) fn check_block_with_expected(
1418 blk: &'tcx hir::Block<'tcx>,
1419 expected: Expectation<'tcx>,
1421 // In some cases, blocks have just one exit, but other blocks
1422 // can be targeted by multiple breaks. This can happen both
1423 // with labeled blocks as well as when we desugar
1424 // a `try { ... }` expression.
1428 // 'a: { if true { break 'a Err(()); } Ok(()) }
1430 // Here we would wind up with two coercions, one from
1431 // `Err(())` and the other from the tail expression
1432 // `Ok(())`. If the tail expression is omitted, that's a
1433 // "forced unit" -- unless the block diverges, in which
1434 // case we can ignore the tail expression (e.g., `'a: {
1435 // break 'a 22; }` would not force the type of the block
1437 let tail_expr = blk.expr.as_ref();
1438 let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1439 let coerce = if blk.targeted_by_break {
1440 CoerceMany::new(coerce_to_ty)
1442 let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
1443 Some(e) => slice::from_ref(e),
1446 CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
1449 let prev_diverges = self.diverges.get();
1450 let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1452 let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1453 for (pos, s) in blk.stmts.iter().enumerate() {
1454 self.check_stmt(s, blk.stmts.len() - 1 == pos);
1457 // check the tail expression **without** holding the
1458 // `enclosing_breakables` lock below.
1459 let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
1461 let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1462 let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1463 let coerce = ctxt.coerce.as_mut().unwrap();
1464 if let Some(tail_expr_ty) = tail_expr_ty {
1465 let tail_expr = tail_expr.unwrap();
1466 let span = self.get_expr_coercion_span(tail_expr);
1467 let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
1468 let ty_for_diagnostic = coerce.merged_ty();
1469 // We use coerce_inner here because we want to augment the error
1470 // suggesting to wrap the block in square brackets if it might've
1471 // been mistaken array syntax
1472 coerce.coerce_inner(
1477 Some(&mut |diag: &mut Diagnostic| {
1478 self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1483 // Subtle: if there is no explicit tail expression,
1484 // that is typically equivalent to a tail expression
1485 // of `()` -- except if the block diverges. In that
1486 // case, there is no value supplied from the tail
1487 // expression (assuming there are no other breaks,
1488 // this implies that the type of the block will be
1491 // #41425 -- label the implicit `()` as being the
1492 // "found type" here, rather than the "expected type".
1493 if !self.diverges.get().is_always() {
1494 // #50009 -- Do not point at the entire fn block span, point at the return type
1495 // span, as it is the cause of the requirement, and
1496 // `consider_hint_about_removing_semicolon` will point at the last expression
1497 // if it were a relevant part of the error. This improves usability in editors
1498 // that highlight errors inline.
1499 let mut sp = blk.span;
1500 let mut fn_span = None;
1501 if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
1502 let ret_sp = decl.output.span();
1503 if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1504 // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
1505 // output would otherwise be incorrect and even misleading. Make sure
1506 // the span we're aiming at correspond to a `fn` body.
1507 if block_sp == blk.span {
1509 fn_span = Some(ident.span);
1513 coerce.coerce_forced_unit(
1517 if let Some(expected_ty) = expected.only_has_type(self) {
1518 if !self.consider_removing_semicolon(blk, expected_ty, err) {
1519 self.err_ctxt().consider_returning_binding(
1525 if expected_ty == self.tcx.types.bool {
1526 // If this is caused by a missing `let` in a `while let`,
1527 // silence this redundant error, as we already emit E0070.
1529 // Our block must be a `assign desugar local; assignment`
1530 if let Some(hir::Node::Block(hir::Block {
1535 hir::StmtKind::Local(hir::Local {
1537 hir::LocalSource::AssignDesugar(_),
1544 hir::StmtKind::Expr(hir::Expr {
1545 kind: hir::ExprKind::Assign(..),
1552 })) = self.tcx.hir().find(blk.hir_id)
1554 self.comes_from_while_condition(blk.hir_id, |_| {
1555 err.downgrade_to_delayed_bug();
1560 if let Some(fn_span) = fn_span {
1563 "implicitly returns `()` as its body has no tail or `return` \
1575 // If we can break from the block, then the block's exit is always reachable
1576 // (... as long as the entry is reachable) - regardless of the tail of the block.
1577 self.diverges.set(prev_diverges);
1580 let ty = ctxt.coerce.unwrap().complete(self);
1582 self.write_ty(blk.hir_id, ty);
1587 fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
1588 let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
1590 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
1591 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1592 let body = self.tcx.hir().body(body_id);
1593 if let ExprKind::Block(block, _) = &body.value.kind {
1594 return Some(block.span);
1602 /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
1603 fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
1604 let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
1605 self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
1608 /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
1609 /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
1610 /// when given code like the following:
1612 /// if false { return 0i32; } else { 1u32 }
1613 /// // ^^^^ point at this instead of the whole `if` expression
1615 fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1616 let check_in_progress = |elem: &hir::Expr<'_>| {
1617 self.typeck_results.borrow().node_type_opt(elem.hir_id).filter(|ty| !ty.is_never()).map(
1618 |_| match elem.kind {
1619 // Point at the tail expression when possible.
1620 hir::ExprKind::Block(block, _) => block.expr.map_or(block.span, |e| e.span),
1626 if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
1627 if let Some(rslt) = check_in_progress(el) {
1632 if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1633 let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1634 if let Some(span) = iter.next() {
1635 if iter.next().is_none() {
1644 fn overwrite_local_ty_if_err(
1647 pat: &'tcx hir::Pat<'tcx>,
1650 if ty.references_error() {
1651 // Override the types everywhere with `err()` to avoid knock on errors.
1652 let err = self.tcx.ty_error();
1653 self.write_ty(hir_id, err);
1654 self.write_ty(pat.hir_id, err);
1655 let local_ty = LocalTy { decl_ty: err, revealed_ty: err };
1656 self.locals.borrow_mut().insert(hir_id, local_ty);
1657 self.locals.borrow_mut().insert(pat.hir_id, local_ty);
1661 // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
1662 // The newly resolved definition is written into `type_dependent_defs`.
1663 fn finish_resolving_struct_path(
1668 ) -> (Res, RawTy<'tcx>) {
1670 QPath::Resolved(ref maybe_qself, ref path) => {
1671 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
1672 let ty = self.astconv().res_to_ty(self_ty, path, true);
1673 (path.res, self.handle_raw_ty(path_span, ty))
1675 QPath::TypeRelative(ref qself, ref segment) => {
1676 let ty = self.to_ty(qself);
1680 .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
1681 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
1682 let ty = self.handle_raw_ty(path_span, ty);
1683 let result = result.map(|(_, kind, def_id)| (kind, def_id));
1685 // Write back the new resolution.
1686 self.write_resolution(hir_id, result);
1688 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1690 QPath::LangItem(lang_item, span, id) => {
1691 let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id);
1692 (res, self.handle_raw_ty(path_span, ty))
1697 /// Given a vector of fulfillment errors, try to adjust the spans of the
1698 /// errors to more accurately point at the cause of the failure.
1700 /// This applies to calls, methods, and struct expressions. This will also
1701 /// try to deduplicate errors that are due to the same cause but might
1702 /// have been created with different [`ObligationCause`][traits::ObligationCause]s.
1703 pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
1705 errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1707 // Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
1708 // other errors that have the same span and predicate can also get fixed,
1709 // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
1710 // This is important since if we adjust one span but not the other, then
1711 // we will have "duplicated" the error on the UI side.
1712 let mut remap_cause = FxIndexSet::default();
1713 let mut not_adjusted = vec![];
1715 for error in errors {
1716 let before_span = error.obligation.cause.span;
1717 if self.adjust_fulfillment_error_for_expr_obligation(error)
1718 || before_span != error.obligation.cause.span
1720 // Store both the predicate and the predicate *without constness*
1721 // since sometimes we instantiate and check both of these in a
1722 // method call, for example.
1723 remap_cause.insert((
1725 error.obligation.predicate,
1726 error.obligation.cause.clone(),
1728 remap_cause.insert((
1730 error.obligation.predicate.without_const(self.tcx),
1731 error.obligation.cause.clone(),
1734 // If it failed to be adjusted once around, it may be adjusted
1735 // via the "remap cause" mapping the second time...
1736 not_adjusted.push(error);
1740 // Adjust any other errors that come from other cause codes, when these
1741 // errors are of the same predicate as one we successfully adjusted, and
1742 // when their spans overlap (suggesting they're due to the same root cause).
1744 // This is because due to normalization, we often register duplicate
1745 // obligations with misc obligations that are basically impossible to
1746 // line back up with a useful ExprBindingObligation.
1747 for error in not_adjusted {
1748 for (span, predicate, cause) in &remap_cause {
1749 if *predicate == error.obligation.predicate
1750 && span.contains(error.obligation.cause.span)
1752 error.obligation.cause = cause.clone();
1761 err: &mut Diagnostic,
1762 callable_def_id: Option<DefId>,
1763 callee_ty: Option<Ty<'tcx>>,
1764 // A specific argument should be labeled, instead of all of them
1765 expected_idx: Option<usize>,
1768 let Some(mut def_id) = callable_def_id else {
1772 if let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1773 // Possibly points at either impl or trait item, so try to get it
1774 // to point to trait item, then get the parent.
1775 // This parent might be an impl in the case of an inherent function,
1776 // but the next check will fail.
1777 && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
1778 && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1779 // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
1780 && let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
1781 && let Some(callee_ty) = callee_ty
1783 let callee_ty = callee_ty.peel_refs();
1784 match *callee_ty.kind() {
1785 ty::Param(param) => {
1787 self.tcx.generics_of(self.body_id).type_param(¶m, self.tcx);
1788 if param.kind.is_synthetic() {
1789 // if it's `impl Fn() -> ..` then just fall down to the def-id based logic
1790 def_id = param.def_id;
1792 // Otherwise, find the predicate that makes this generic callable,
1793 // and point at that.
1794 let instantiated = self
1796 .explicit_predicates_of(self.body_id)
1797 .instantiate_identity(self.tcx);
1798 // FIXME(compiler-errors): This could be problematic if something has two
1799 // fn-like predicates with different args, but callable types really never
1800 // do that, so it's OK.
1801 for (predicate, span) in instantiated
1803 if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = predicate.kind().skip_binder()
1804 && pred.self_ty().peel_refs() == callee_ty
1805 && self.tcx.is_fn_trait(pred.def_id())
1807 err.span_note(span, "callable defined here");
1813 ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
1814 | ty::Closure(new_def_id, _)
1815 | ty::FnDef(new_def_id, _) => {
1816 def_id = new_def_id;
1819 // Look for a user-provided impl of a `Fn` trait, and point to it.
1820 let new_def_id = self.probe(|_| {
1821 let trait_ref = self.tcx.mk_trait_ref(
1822 call_kind.to_def_id(self.tcx),
1825 self.next_ty_var(TypeVariableOrigin {
1826 kind: TypeVariableOriginKind::MiscVariable,
1827 span: rustc_span::DUMMY_SP,
1831 let obligation = traits::Obligation::new(
1833 traits::ObligationCause::dummy(),
1835 ty::Binder::dummy(trait_ref),
1837 match SelectionContext::new(&self).select(&obligation) {
1838 Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1839 Some(impl_source.impl_def_id)
1844 if let Some(new_def_id) = new_def_id {
1845 def_id = new_def_id;
1853 if let Some(def_span) = self.tcx.def_ident_span(def_id) && !def_span.is_dummy() {
1854 let mut spans: MultiSpan = def_span.into();
1859 .get_if_local(def_id)
1860 .and_then(|node| node.body_id())
1862 .flat_map(|id| self.tcx.hir().body(id).params)
1863 .skip(if is_method { 1 } else { 0 });
1865 for (_, param) in params
1868 .filter(|(idx, _)| expected_idx.map_or(true, |expected_idx| expected_idx == *idx))
1870 spans.push_span_label(param.span, "");
1873 let def_kind = self.tcx.def_kind(def_id);
1874 err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
1875 } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
1876 && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
1878 let param = expected_idx
1879 .and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx));
1880 let (kind, span) = if let Some(param) = param {
1881 ("closure parameter", param.span)
1883 ("closure", self.tcx.def_span(def_id))
1885 err.span_note(span, &format!("{} defined here", kind));
1887 let def_kind = self.tcx.def_kind(def_id);
1889 self.tcx.def_span(def_id),
1890 &format!("{} defined here", def_kind.descr(def_id)),