]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
use `pluralize!`
[rust.git] / compiler / rustc_typeck / src / check / fn_ctxt / checks.rs
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,
5 };
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::*;
11 use crate::check::{
12     potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
13     LocalTy, Needs, TupleArgumentsFlag,
14 };
15 use crate::structured_errors::StructuredDiagnostic;
16
17 use rustc_ast as ast;
18 use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
19 use rustc_hir as hir;
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};
35
36 use std::iter;
37 use std::slice;
38
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(..) {
44             cast.check(self);
45         }
46     }
47
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);
53         }
54     }
55
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).check_asm(asm, enclosing_id);
62         }
63     }
64
65     pub(in super::super) fn check_method_argument_types(
66         &self,
67         sp: Span,
68         expr: &'tcx hir::Expr<'tcx>,
69         method: Result<MethodCallee<'tcx>, ()>,
70         args_no_rcvr: &'tcx [hir::Expr<'tcx>],
71         tuple_arguments: TupleArgumentsFlag,
72         expected: Expectation<'tcx>,
73     ) -> Ty<'tcx> {
74         let has_error = match method {
75             Ok(method) => method.substs.references_error() || method.sig.references_error(),
76             Err(_) => true,
77         };
78         if has_error {
79             let err_inputs = self.err_args(args_no_rcvr.len());
80
81             let err_inputs = match tuple_arguments {
82                 DontTupleArguments => err_inputs,
83                 TupleArguments => vec![self.tcx.intern_tup(&err_inputs)],
84             };
85
86             self.check_argument_types(
87                 sp,
88                 expr,
89                 &err_inputs,
90                 None,
91                 args_no_rcvr,
92                 false,
93                 tuple_arguments,
94                 method.ok().map(|method| method.def_id),
95             );
96             return self.tcx.ty_error();
97         }
98
99         let method = method.unwrap();
100         // HACK(eddyb) ignore self in the definition (see above).
101         let expected_input_tys = self.expected_inputs_for_expected_output(
102             sp,
103             expected,
104             method.sig.output(),
105             &method.sig.inputs()[1..],
106         );
107         self.check_argument_types(
108             sp,
109             expr,
110             &method.sig.inputs()[1..],
111             expected_input_tys,
112             args_no_rcvr,
113             method.sig.c_variadic,
114             tuple_arguments,
115             Some(method.def_id),
116         );
117         method.sig.output()
118     }
119
120     /// Generic function that factors out common logic from function calls,
121     /// method calls and overloaded operators.
122     pub(in super::super) fn check_argument_types(
123         &self,
124         // Span enclosing the call site
125         call_span: Span,
126         // Expression of the call site
127         call_expr: &'tcx hir::Expr<'tcx>,
128         // Types (as defined in the *signature* of the target function)
129         formal_input_tys: &[Ty<'tcx>],
130         // More specific expected types, after unifying with caller output types
131         expected_input_tys: Option<Vec<Ty<'tcx>>>,
132         // The expressions for each provided argument
133         provided_args: &'tcx [hir::Expr<'tcx>],
134         // Whether the function is variadic, for example when imported from C
135         c_variadic: bool,
136         // Whether the arguments have been bundled in a tuple (ex: closures)
137         tuple_arguments: TupleArgumentsFlag,
138         // The DefId for the function being called, for better error messages
139         fn_def_id: Option<DefId>,
140     ) {
141         let tcx = self.tcx;
142
143         // Conceptually, we've got some number of expected inputs, and some number of provided aguments
144         // and we can form a grid of whether each argument could satisfy a given input:
145         //      in1 | in2 | in3 | ...
146         // arg1  ?  |     |     |
147         // arg2     |  ?  |     |
148         // arg3     |     |  ?  |
149         // ...
150         // Initially, we just check the diagonal, because in the case of correct code
151         // these are the only checks that matter
152         // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
153         // better error messages about invalid method calls.
154
155         // All the input types from the fn signature must outlive the call
156         // so as to validate implied bounds.
157         for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
158             self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
159         }
160
161         let mut err_code = "E0061";
162
163         // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
164         let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
165             let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
166             match tuple_type.kind() {
167                 // We expected a tuple and got a tuple
168                 ty::Tuple(arg_types) => {
169                     // Argument length differs
170                     if arg_types.len() != provided_args.len() {
171                         err_code = "E0057";
172                     }
173                     let expected_input_tys = match expected_input_tys {
174                         Some(expected_input_tys) => match expected_input_tys.get(0) {
175                             Some(ty) => match ty.kind() {
176                                 ty::Tuple(tys) => Some(tys.iter().collect()),
177                                 _ => None,
178                             },
179                             None => None,
180                         },
181                         None => None,
182                     };
183                     (arg_types.iter().collect(), expected_input_tys)
184                 }
185                 _ => {
186                     // Otherwise, there's a mismatch, so clear out what we're expecting, and set
187                     // our input types to err_args so we don't blow up the error messages
188                     struct_span_err!(
189                         tcx.sess,
190                         call_span,
191                         E0059,
192                         "cannot use call notation; the first type parameter \
193                          for the function trait is neither a tuple nor unit"
194                     )
195                     .emit();
196                     (self.err_args(provided_args.len()), None)
197                 }
198             }
199         } else {
200             (formal_input_tys.to_vec(), expected_input_tys)
201         };
202
203         // If there are no external expectations at the call site, just use the types from the function defn
204         let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
205             assert_eq!(expected_input_tys.len(), formal_input_tys.len());
206             expected_input_tys
207         } else {
208             formal_input_tys.clone()
209         };
210
211         let minimum_input_count = expected_input_tys.len();
212         let provided_arg_count = provided_args.len();
213
214         // We introduce a helper function to demand that a given argument satisfy a given input
215         // This is more complicated than just checking type equality, as arguments could be coerced
216         // This version writes those types back so further type checking uses the narrowed types
217         let demand_compatible = |idx| {
218             let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
219             let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
220             let provided_arg = &provided_args[idx];
221
222             debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
223
224             // We're on the happy path here, so we'll do a more involved check and write back types
225             // To check compatibility, we'll do 3 things:
226             // 1. Unify the provided argument with the expected type
227             let expectation = Expectation::rvalue_hint(self, expected_input_ty);
228
229             let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
230
231             // 2. Coerce to the most detailed type that could be coerced
232             //    to, which is `expected_ty` if `rvalue_hint` returns an
233             //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
234             let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
235
236             // Cause selection errors caused by resolving a single argument to point at the
237             // argument and not the call. This lets us customize the span pointed to in the
238             // fulfillment error to be more accurate.
239             let coerced_ty =
240                 self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
241                     self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
242                     self.point_at_arg_instead_of_call_if_possible(
243                         errors,
244                         call_expr,
245                         call_span,
246                         provided_args,
247                         &expected_input_tys,
248                     );
249                 });
250
251             let coerce_error = self
252                 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
253                 .err();
254
255             if coerce_error.is_some() {
256                 return Compatibility::Incompatible(coerce_error);
257             }
258
259             // 3. Check if the formal type is a supertype of the checked one
260             //    and register any such obligations for future type checks
261             let supertype_error = self
262                 .at(&self.misc(provided_arg.span), self.param_env)
263                 .sup(formal_input_ty, coerced_ty);
264             let subtyping_error = match supertype_error {
265                 Ok(InferOk { obligations, value: () }) => {
266                     self.register_predicates(obligations);
267                     None
268                 }
269                 Err(err) => Some(err),
270             };
271
272             // If neither check failed, the types are compatible
273             match subtyping_error {
274                 None => Compatibility::Compatible,
275                 Some(_) => Compatibility::Incompatible(subtyping_error),
276             }
277         };
278
279         // To start, we only care "along the diagonal", where we expect every
280         // provided arg to be in the right spot
281         let mut compatibility_diagonal =
282             vec![Compatibility::Incompatible(None); provided_args.len()];
283
284         // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
285         // if the wrong number of arguments were supplied, we CAN'T be satisfied,
286         // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
287         // otherwise, they need to be identical, because rust doesn't currently support variadic functions
288         let mut call_appears_satisfied = if c_variadic {
289             provided_arg_count >= minimum_input_count
290         } else {
291             provided_arg_count == minimum_input_count
292         };
293
294         // Check the arguments.
295         // We do this in a pretty awful way: first we type-check any arguments
296         // that are not closures, then we type-check the closures. This is so
297         // that we have more information about the types of arguments when we
298         // type-check the functions. This isn't really the right way to do this.
299         for check_closures in [false, true] {
300             // More awful hacks: before we check argument types, try to do
301             // an "opportunistic" trait resolution of any trait bounds on
302             // the call. This helps coercions.
303             if check_closures {
304                 self.select_obligations_where_possible(false, |errors| {
305                     self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
306                     self.point_at_arg_instead_of_call_if_possible(
307                         errors,
308                         call_expr,
309                         call_span,
310                         &provided_args,
311                         &expected_input_tys,
312                     );
313                 })
314             }
315
316             // Check each argument, to satisfy the input it was provided for
317             // Visually, we're traveling down the diagonal of the compatibility matrix
318             for (idx, arg) in provided_args.iter().enumerate() {
319                 // Warn only for the first loop (the "no closures" one).
320                 // Closure arguments themselves can't be diverging, but
321                 // a previous argument can, e.g., `foo(panic!(), || {})`.
322                 if !check_closures {
323                     self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
324                 }
325
326                 // For C-variadic functions, we don't have a declared type for all of
327                 // the arguments hence we only do our usual type checking with
328                 // the arguments who's types we do know. However, we *can* check
329                 // for unreachable expressions (see above).
330                 // FIXME: unreachable warning current isn't emitted
331                 if idx >= minimum_input_count {
332                     continue;
333                 }
334
335                 let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
336                 if is_closure != check_closures {
337                     continue;
338                 }
339
340                 let compatible = demand_compatible(idx);
341                 let is_compatible = matches!(compatible, Compatibility::Compatible);
342                 compatibility_diagonal[idx] = compatible;
343
344                 if !is_compatible {
345                     call_appears_satisfied = false;
346                 }
347             }
348         }
349
350         if c_variadic && provided_arg_count < minimum_input_count {
351             err_code = "E0060";
352         }
353
354         for arg in provided_args.iter().skip(minimum_input_count) {
355             // Make sure we've checked this expr at least once.
356             let arg_ty = self.check_expr(&arg);
357
358             // If the function is c-style variadic, we skipped a bunch of arguments
359             // so we need to check those, and write out the types
360             // Ideally this would be folded into the above, for uniform style
361             // but c-variadic is already a corner case
362             if c_variadic {
363                 fn variadic_error<'tcx>(
364                     sess: &'tcx Session,
365                     span: Span,
366                     ty: Ty<'tcx>,
367                     cast_ty: &str,
368                 ) {
369                     use crate::structured_errors::MissingCastForVariadicArg;
370
371                     MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
372                 }
373
374                 // There are a few types which get autopromoted when passed via varargs
375                 // in C but we just error out instead and require explicit casts.
376                 let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
377                 match arg_ty.kind() {
378                     ty::Float(ty::FloatTy::F32) => {
379                         variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
380                     }
381                     ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
382                         variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
383                     }
384                     ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
385                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
386                     }
387                     ty::FnDef(..) => {
388                         let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
389                         let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
390                         variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
391                     }
392                     _ => {}
393                 }
394             }
395         }
396
397         if !call_appears_satisfied {
398             let compatibility_diagonal = IndexVec::from_raw(compatibility_diagonal);
399             let provided_args = IndexVec::from_iter(provided_args.iter().take(if c_variadic {
400                 minimum_input_count
401             } else {
402                 provided_arg_count
403             }));
404             debug_assert_eq!(
405                 formal_input_tys.len(),
406                 expected_input_tys.len(),
407                 "expected formal_input_tys to be the same size as expected_input_tys"
408             );
409             let formal_and_expected_inputs = IndexVec::from_iter(
410                 formal_input_tys
411                     .iter()
412                     .copied()
413                     .zip(expected_input_tys.iter().copied())
414                     .map(|vars| self.resolve_vars_if_possible(vars)),
415             );
416
417             self.report_arg_errors(
418                 compatibility_diagonal,
419                 formal_and_expected_inputs,
420                 provided_args,
421                 c_variadic,
422                 err_code,
423                 fn_def_id,
424                 call_span,
425                 call_expr,
426             );
427         }
428     }
429
430     fn report_arg_errors(
431         &self,
432         compatibility_diagonal: IndexVec<ProvidedIdx, Compatibility<'tcx>>,
433         formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
434         provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
435         c_variadic: bool,
436         err_code: &str,
437         fn_def_id: Option<DefId>,
438         call_span: Span,
439         call_expr: &hir::Expr<'tcx>,
440     ) {
441         // Next, let's construct the error
442         let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
443             hir::ExprKind::Call(
444                 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
445                 _,
446             ) => {
447                 if let Res::Def(DefKind::Ctor(of, _), _) =
448                     self.typeck_results.borrow().qpath_res(qpath, *hir_id)
449                 {
450                     (call_span, *span, Some(of))
451                 } else {
452                     (call_span, *span, None)
453                 }
454             }
455             hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
456             hir::ExprKind::MethodCall(path_segment, _, span) => {
457                 let ident_span = path_segment.ident.span;
458                 let ident_span = if let Some(args) = path_segment.args {
459                     ident_span.with_hi(args.span_ext.hi())
460                 } else {
461                     ident_span
462                 };
463                 (
464                     *span, ident_span, None, // methods are never ctors
465                 )
466             }
467             k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
468         };
469         let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
470         let call_name = match ctor_of {
471             Some(CtorOf::Struct) => "struct",
472             Some(CtorOf::Variant) => "enum variant",
473             None => "function",
474         };
475
476         // Don't print if it has error types or is just plain `_`
477         fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
478             tys.into_iter().any(|ty| ty.references_error() || ty.is_ty_var())
479         }
480
481         self.set_tainted_by_errors();
482         let tcx = self.tcx;
483
484         // Get the argument span in the context of the call span so that
485         // suggestions and labels are (more) correct when an arg is a
486         // macro invocation.
487         let normalize_span = |span: Span| -> Span {
488             let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span);
489             // Sometimes macros mess up the spans, so do not normalize the
490             // arg span to equal the error span, because that's less useful
491             // than pointing out the arg expr in the wrong context.
492             if normalized_span.source_equal(error_span) { span } else { normalized_span }
493         };
494
495         // Precompute the provided types and spans, since that's all we typically need for below
496         let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
497             .iter()
498             .map(|expr| {
499                 let ty = self
500                     .typeck_results
501                     .borrow()
502                     .expr_ty_adjusted_opt(*expr)
503                     .unwrap_or_else(|| tcx.ty_error());
504                 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
505             })
506             .collect();
507         let callee_expr = match &call_expr.peel_blocks().kind {
508             hir::ExprKind::Call(callee, _) => Some(*callee),
509             hir::ExprKind::MethodCall(_, callee, _) => {
510                 if let Some((DefKind::AssocFn, def_id)) =
511                     self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
512                     && let Some(assoc) = tcx.opt_associated_item(def_id)
513                     && assoc.fn_has_self_parameter
514                 {
515                     Some(&callee[0])
516                 } else {
517                     None
518                 }
519             }
520             _ => None,
521         };
522         let callee_ty = callee_expr
523             .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
524
525         // A "softer" version of the `demand_compatible`, which checks types without persisting them,
526         // and treats error types differently
527         // This will allow us to "probe" for other argument orders that would likely have been correct
528         let check_compatible = |provided_idx: ProvidedIdx, expected_idx: ExpectedIdx| {
529             if provided_idx.as_usize() == expected_idx.as_usize() {
530                 return compatibility_diagonal[provided_idx].clone();
531             }
532
533             let (formal_input_ty, expected_input_ty) = formal_and_expected_inputs[expected_idx];
534             // If either is an error type, we defy the usual convention and consider them to *not* be
535             // coercible. This prevents our error message heuristic from trying to pass errors into
536             // every argument.
537             if (formal_input_ty, expected_input_ty).references_error() {
538                 return Compatibility::Incompatible(None);
539             }
540
541             let (arg_ty, arg_span) = provided_arg_tys[provided_idx];
542
543             let expectation = Expectation::rvalue_hint(self, expected_input_ty);
544             let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
545             let can_coerce = self.can_coerce(arg_ty, coerced_ty);
546             if !can_coerce {
547                 return Compatibility::Incompatible(None);
548             }
549
550             // Using probe here, since we don't want this subtyping to affect inference.
551             let subtyping_error = self.probe(|_| {
552                 self.at(&self.misc(arg_span), self.param_env).sup(formal_input_ty, coerced_ty).err()
553             });
554
555             // Same as above: if either the coerce type or the checked type is an error type,
556             // consider them *not* compatible.
557             let references_error = (coerced_ty, arg_ty).references_error();
558             match (references_error, subtyping_error) {
559                 (false, None) => Compatibility::Compatible,
560                 (_, subtyping_error) => Compatibility::Incompatible(subtyping_error),
561             }
562         };
563
564         // The algorithm here is inspired by levenshtein distance and longest common subsequence.
565         // We'll try to detect 4 different types of mistakes:
566         // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
567         // - An input is missing, which isn't satisfied by *any* of the other arguments
568         // - Some number of arguments have been provided in the wrong order
569         // - A type is straight up invalid
570
571         // First, let's find the errors
572         let (mut errors, matched_inputs) =
573             ArgMatrix::new(provided_args.len(), formal_and_expected_inputs.len(), check_compatible)
574                 .find_errors();
575
576         // First, check if we just need to wrap some arguments in a tuple.
577         if let Some((mismatch_idx, terr)) =
578             compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {
579                 if let Compatibility::Incompatible(Some(terr)) = c { Some((i, terr)) } else { None }
580             })
581         {
582             // Is the first bad expected argument a tuple?
583             // Do we have as many extra provided arguments as the tuple's length?
584             // If so, we might have just forgotten to wrap some args in a tuple.
585             if let Some(ty::Tuple(tys)) =
586                 formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
587                 // If the tuple is unit, we're not actually wrapping any arguments.
588                 && !tys.is_empty()
589                 && provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
590             {
591                 // Wrap up the N provided arguments starting at this position in a tuple.
592                 let provided_as_tuple = tcx.mk_tup(
593                     provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
594                 );
595
596                 let mut satisfied = true;
597                 // Check if the newly wrapped tuple + rest of the arguments are compatible.
598                 for ((_, expected_ty), provided_ty) in std::iter::zip(
599                     formal_and_expected_inputs.iter().skip(mismatch_idx),
600                     [provided_as_tuple].into_iter().chain(
601                         provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
602                     ),
603                 ) {
604                     if !self.can_coerce(provided_ty, *expected_ty) {
605                         satisfied = false;
606                         break;
607                     }
608                 }
609
610                 // If they're compatible, suggest wrapping in an arg, and we're done!
611                 // Take some care with spans, so we don't suggest wrapping a macro's
612                 // innards in parenthesis, for example.
613                 if satisfied
614                     && let Some((_, lo)) =
615                         provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx))
616                     && let Some((_, hi)) =
617                         provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1))
618                 {
619                     let mut err;
620                     if tys.len() == 1 {
621                         // A tuple wrap suggestion actually occurs within,
622                         // so don't do anything special here.
623                         err = self.report_and_explain_type_error(
624                             TypeTrace::types(
625                                 &self.misc(*lo),
626                                 true,
627                                 formal_and_expected_inputs[mismatch_idx.into()].1,
628                                 provided_arg_tys[mismatch_idx.into()].0,
629                             ),
630                             terr,
631                         );
632                         err.span_label(
633                             full_call_span,
634                             format!("arguments to this {} are incorrect", call_name),
635                         );
636                     } else {
637                         err = tcx.sess.struct_span_err_with_code(
638                             full_call_span,
639                             &format!(
640                                 "this {} takes {}{} but {} {} supplied",
641                                 call_name,
642                                 if c_variadic { "at least " } else { "" },
643                                 potentially_plural_count(
644                                     formal_and_expected_inputs.len(),
645                                     "argument"
646                                 ),
647                                 potentially_plural_count(provided_args.len(), "argument"),
648                                 pluralize!("was", provided_args.len())
649                             ),
650                             DiagnosticId::Error(err_code.to_owned()),
651                         );
652                         err.multipart_suggestion_verbose(
653                             "wrap these arguments in parentheses to construct a tuple",
654                             vec![
655                                 (lo.shrink_to_lo(), "(".to_string()),
656                                 (hi.shrink_to_hi(), ")".to_string()),
657                             ],
658                             Applicability::MachineApplicable,
659                         );
660                     };
661                     self.label_fn_like(&mut err, fn_def_id, callee_ty);
662                     err.emit();
663                     return;
664                 }
665             }
666         }
667
668         // Okay, so here's where it gets complicated in regards to what errors
669         // we emit and how.
670         // There are 3 different "types" of errors we might encounter.
671         //   1) Missing/extra/swapped arguments
672         //   2) Valid but incorrect arguments
673         //   3) Invalid arguments
674         //      - Currently I think this only comes up with `CyclicTy`
675         //
676         // We first need to go through, remove those from (3) and emit those
677         // as their own error, particularly since they're error code and
678         // message is special. From what I can tell, we *must* emit these
679         // here (vs somewhere prior to this function) since the arguments
680         // become invalid *because* of how they get used in the function.
681         // It is what it is.
682
683         if errors.is_empty() {
684             if cfg!(debug_assertions) {
685                 span_bug!(error_span, "expected errors from argument matrix");
686             } else {
687                 tcx.sess
688                     .struct_span_err(
689                         error_span,
690                         "argument type mismatch was detected, \
691                         but rustc had trouble determining where",
692                     )
693                     .note(
694                         "we would appreciate a bug report: \
695                         https://github.com/rust-lang/rust/issues/new",
696                     )
697                     .emit();
698             }
699             return;
700         }
701
702         errors.drain_filter(|error| {
703                 let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(error)) = error else { return false };
704                 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
705                 let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
706                 let cause = &self.misc(provided_span);
707                 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
708                 if let Some(e) = error {
709                     if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
710                         self.report_and_explain_type_error(trace, e).emit();
711                         return true;
712                     }
713                 }
714                 false
715             });
716
717         // We're done if we found errors, but we already emitted them.
718         if errors.is_empty() {
719             return;
720         }
721
722         // Okay, now that we've emitted the special errors separately, we
723         // are only left missing/extra/swapped and mismatched arguments, both
724         // can be collated pretty easily if needed.
725
726         // Next special case: if there is only one "Incompatible" error, just emit that
727         if let [
728             Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))),
729         ] = &errors[..]
730         {
731             let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
732             let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
733             let cause = &self.misc(provided_arg_span);
734             let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
735             let mut err = self.report_and_explain_type_error(trace, err);
736             self.emit_coerce_suggestions(
737                 &mut err,
738                 &provided_args[*provided_idx],
739                 provided_ty,
740                 Expectation::rvalue_hint(self, expected_ty)
741                     .only_has_type(self)
742                     .unwrap_or(formal_ty),
743                 None,
744                 None,
745             );
746             err.span_label(
747                 full_call_span,
748                 format!("arguments to this {} are incorrect", call_name),
749             );
750             // Call out where the function is defined
751             self.label_fn_like(&mut err, fn_def_id, callee_ty);
752             err.emit();
753             return;
754         }
755
756         let mut err = if formal_and_expected_inputs.len() == provided_args.len() {
757             struct_span_err!(
758                 tcx.sess,
759                 full_call_span,
760                 E0308,
761                 "arguments to this {} are incorrect",
762                 call_name,
763             )
764         } else {
765             tcx.sess.struct_span_err_with_code(
766                 full_call_span,
767                 &format!(
768                     "this {} takes {}{} but {} {} supplied",
769                     call_name,
770                     if c_variadic { "at least " } else { "" },
771                     potentially_plural_count(formal_and_expected_inputs.len(), "argument"),
772                     potentially_plural_count(provided_args.len(), "argument"),
773                     pluralize!("was", provided_args.len())
774                 ),
775                 DiagnosticId::Error(err_code.to_owned()),
776             )
777         };
778
779         // As we encounter issues, keep track of what we want to provide for the suggestion
780         let mut labels = vec![];
781         // If there is a single error, we give a specific suggestion; otherwise, we change to
782         // "did you mean" with the suggested function call
783         enum SuggestionText {
784             None,
785             Provide(bool),
786             Remove(bool),
787             Swap,
788             Reorder,
789             DidYouMean,
790         }
791         let mut suggestion_text = SuggestionText::None;
792
793         let mut errors = errors.into_iter().peekable();
794         while let Some(error) = errors.next() {
795             match error {
796                 Error::Invalid(provided_idx, expected_idx, compatibility) => {
797                     let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
798                     let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
799                     if let Compatibility::Incompatible(error) = &compatibility {
800                         let cause = &self.misc(provided_span);
801                         let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
802                         if let Some(e) = error {
803                             self.note_type_err(
804                                 &mut err,
805                                 &trace.cause,
806                                 None,
807                                 Some(trace.values),
808                                 e,
809                                 false,
810                                 true,
811                             );
812                         }
813                     }
814
815                     self.emit_coerce_suggestions(
816                         &mut err,
817                         &provided_args[provided_idx],
818                         provided_ty,
819                         Expectation::rvalue_hint(self, expected_ty)
820                             .only_has_type(self)
821                             .unwrap_or(formal_ty),
822                         None,
823                         None,
824                     );
825                 }
826                 Error::Extra(arg_idx) => {
827                     let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
828                     let provided_ty_name = if !has_error_or_infer([provided_ty]) {
829                         // FIXME: not suggestable, use something else
830                         format!(" of type `{}`", provided_ty)
831                     } else {
832                         "".to_string()
833                     };
834                     labels
835                         .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
836                     suggestion_text = match suggestion_text {
837                         SuggestionText::None => SuggestionText::Remove(false),
838                         SuggestionText::Remove(_) => SuggestionText::Remove(true),
839                         _ => SuggestionText::DidYouMean,
840                     };
841                 }
842                 Error::Missing(expected_idx) => {
843                     // If there are multiple missing arguments adjacent to each other,
844                     // then we can provide a single error.
845
846                     let mut missing_idxs = vec![expected_idx];
847                     while let Some(e) = errors.next_if(|e| {
848                         matches!(e, Error::Missing(next_expected_idx)
849                             if *next_expected_idx == *missing_idxs.last().unwrap() + 1)
850                     }) {
851                         match e {
852                             Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
853                             _ => unreachable!(),
854                         }
855                     }
856
857                     // NOTE: Because we might be re-arranging arguments, might have extra
858                     // arguments, etc. it's hard to *really* know where we should provide
859                     // this error label, so as a heuristic, we point to the provided arg, or
860                     // to the call if the missing inputs pass the provided args.
861                     match &missing_idxs[..] {
862                         &[expected_idx] => {
863                             let (_, input_ty) = formal_and_expected_inputs[expected_idx];
864                             let span = if let Some((_, arg_span)) =
865                                 provided_arg_tys.get(expected_idx.to_provided_idx())
866                             {
867                                 *arg_span
868                             } else {
869                                 args_span
870                             };
871                             let rendered = if !has_error_or_infer([input_ty]) {
872                                 format!(" of type `{}`", input_ty)
873                             } else {
874                                 "".to_string()
875                             };
876                             labels.push((span, format!("an argument{} is missing", rendered)));
877                             suggestion_text = match suggestion_text {
878                                 SuggestionText::None => SuggestionText::Provide(false),
879                                 SuggestionText::Provide(_) => SuggestionText::Provide(true),
880                                 _ => SuggestionText::DidYouMean,
881                             };
882                         }
883                         &[first_idx, second_idx] => {
884                             let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
885                             let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
886                             let span = if let (Some((_, first_span)), Some((_, second_span))) = (
887                                 provided_arg_tys.get(first_idx.to_provided_idx()),
888                                 provided_arg_tys.get(second_idx.to_provided_idx()),
889                             ) {
890                                 first_span.to(*second_span)
891                             } else {
892                                 args_span
893                             };
894                             let rendered =
895                                 if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
896                                     format!(
897                                         " of type `{}` and `{}`",
898                                         first_expected_ty, second_expected_ty
899                                     )
900                                 } else {
901                                     "".to_string()
902                                 };
903                             labels.push((span, format!("two arguments{} are missing", rendered)));
904                             suggestion_text = match suggestion_text {
905                                 SuggestionText::None | SuggestionText::Provide(_) => {
906                                     SuggestionText::Provide(true)
907                                 }
908                                 _ => SuggestionText::DidYouMean,
909                             };
910                         }
911                         &[first_idx, second_idx, third_idx] => {
912                             let (_, first_expected_ty) = formal_and_expected_inputs[first_idx];
913                             let (_, second_expected_ty) = formal_and_expected_inputs[second_idx];
914                             let (_, third_expected_ty) = formal_and_expected_inputs[third_idx];
915                             let span = if let (Some((_, first_span)), Some((_, third_span))) = (
916                                 provided_arg_tys.get(first_idx.to_provided_idx()),
917                                 provided_arg_tys.get(third_idx.to_provided_idx()),
918                             ) {
919                                 first_span.to(*third_span)
920                             } else {
921                                 args_span
922                             };
923                             let rendered = if !has_error_or_infer([
924                                 first_expected_ty,
925                                 second_expected_ty,
926                                 third_expected_ty,
927                             ]) {
928                                 format!(
929                                     " of type `{}`, `{}`, and `{}`",
930                                     first_expected_ty, second_expected_ty, third_expected_ty
931                                 )
932                             } else {
933                                 "".to_string()
934                             };
935                             labels.push((span, format!("three arguments{} are missing", rendered)));
936                             suggestion_text = match suggestion_text {
937                                 SuggestionText::None | SuggestionText::Provide(_) => {
938                                     SuggestionText::Provide(true)
939                                 }
940                                 _ => SuggestionText::DidYouMean,
941                             };
942                         }
943                         missing_idxs => {
944                             let first_idx = *missing_idxs.first().unwrap();
945                             let last_idx = *missing_idxs.last().unwrap();
946                             // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
947                             // It's hard to *really* know where we should provide this error label, so this is a
948                             // decent heuristic
949                             let span = if let (Some((_, first_span)), Some((_, last_span))) = (
950                                 provided_arg_tys.get(first_idx.to_provided_idx()),
951                                 provided_arg_tys.get(last_idx.to_provided_idx()),
952                             ) {
953                                 first_span.to(*last_span)
954                             } else {
955                                 args_span
956                             };
957                             labels.push((span, format!("multiple arguments are missing")));
958                             suggestion_text = match suggestion_text {
959                                 SuggestionText::None | SuggestionText::Provide(_) => {
960                                     SuggestionText::Provide(true)
961                                 }
962                                 _ => SuggestionText::DidYouMean,
963                             };
964                         }
965                     }
966                 }
967                 Error::Swap(
968                     first_provided_idx,
969                     second_provided_idx,
970                     first_expected_idx,
971                     second_expected_idx,
972                 ) => {
973                     let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
974                     let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
975                     let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
976                         format!(", found `{}`", first_provided_ty)
977                     } else {
978                         String::new()
979                     };
980                     labels.push((
981                         first_span,
982                         format!("expected `{}`{}", first_expected_ty, first_provided_ty_name),
983                     ));
984
985                     let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
986                     let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
987                     let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
988                         format!(", found `{}`", second_provided_ty)
989                     } else {
990                         String::new()
991                     };
992                     labels.push((
993                         second_span,
994                         format!("expected `{}`{}", second_expected_ty, second_provided_ty_name),
995                     ));
996
997                     suggestion_text = match suggestion_text {
998                         SuggestionText::None => SuggestionText::Swap,
999                         _ => SuggestionText::DidYouMean,
1000                     };
1001                 }
1002                 Error::Permutation(args) => {
1003                     for (dst_arg, dest_input) in args {
1004                         let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
1005                         let (provided_ty, provided_span) = provided_arg_tys[dest_input];
1006                         let provided_ty_name = if !has_error_or_infer([provided_ty]) {
1007                             format!(", found `{}`", provided_ty)
1008                         } else {
1009                             String::new()
1010                         };
1011                         labels.push((
1012                             provided_span,
1013                             format!("expected `{}`{}", expected_ty, provided_ty_name),
1014                         ));
1015                     }
1016
1017                     suggestion_text = match suggestion_text {
1018                         SuggestionText::None => SuggestionText::Reorder,
1019                         _ => SuggestionText::DidYouMean,
1020                     };
1021                 }
1022             }
1023         }
1024
1025         // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
1026         if labels.len() <= 5 {
1027             for (span, label) in labels {
1028                 err.span_label(span, label);
1029             }
1030         }
1031
1032         // Call out where the function is defined
1033         self.label_fn_like(&mut err, fn_def_id, callee_ty);
1034
1035         // And add a suggestion block for all of the parameters
1036         let suggestion_text = match suggestion_text {
1037             SuggestionText::None => None,
1038             SuggestionText::Provide(plural) => {
1039                 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
1040             }
1041             SuggestionText::Remove(plural) => {
1042                 Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
1043             }
1044             SuggestionText::Swap => Some("swap these arguments".to_string()),
1045             SuggestionText::Reorder => Some("reorder these arguments".to_string()),
1046             SuggestionText::DidYouMean => Some("did you mean".to_string()),
1047         };
1048         if let Some(suggestion_text) = suggestion_text {
1049             let source_map = self.sess().source_map();
1050             let mut suggestion = format!(
1051                 "{}(",
1052                 source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| fn_def_id
1053                     .map_or("".to_string(), |fn_def_id| tcx.item_name(fn_def_id).to_string()))
1054             );
1055             let mut needs_comma = false;
1056             for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
1057                 if needs_comma {
1058                     suggestion += ", ";
1059                 } else {
1060                     needs_comma = true;
1061                 }
1062                 let suggestion_text = if let Some(provided_idx) = provided_idx
1063                     && let (_, provided_span) = provided_arg_tys[*provided_idx]
1064                     && let Ok(arg_text) =
1065                         source_map.span_to_snippet(provided_span)
1066                 {
1067                     arg_text
1068                 } else {
1069                     // Propose a placeholder of the correct type
1070                     let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
1071                     if expected_ty.is_unit() {
1072                         "()".to_string()
1073                     } else if expected_ty.is_suggestable(tcx, false) {
1074                         format!("/* {} */", expected_ty)
1075                     } else {
1076                         "/* value */".to_string()
1077                     }
1078                 };
1079                 suggestion += &suggestion_text;
1080             }
1081             suggestion += ")";
1082             err.span_suggestion_verbose(
1083                 error_span,
1084                 &suggestion_text,
1085                 suggestion,
1086                 Applicability::HasPlaceholders,
1087             );
1088         }
1089
1090         err.emit();
1091     }
1092
1093     // AST fragment checking
1094     pub(in super::super) fn check_lit(
1095         &self,
1096         lit: &hir::Lit,
1097         expected: Expectation<'tcx>,
1098     ) -> Ty<'tcx> {
1099         let tcx = self.tcx;
1100
1101         match lit.node {
1102             ast::LitKind::Str(..) => tcx.mk_static_str(),
1103             ast::LitKind::ByteStr(ref v) => {
1104                 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
1105             }
1106             ast::LitKind::Byte(_) => tcx.types.u8,
1107             ast::LitKind::Char(_) => tcx.types.char,
1108             ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)),
1109             ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)),
1110             ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
1111                 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1112                     ty::Int(_) | ty::Uint(_) => Some(ty),
1113                     ty::Char => Some(tcx.types.u8),
1114                     ty::RawPtr(..) => Some(tcx.types.usize),
1115                     ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
1116                     _ => None,
1117                 });
1118                 opt_ty.unwrap_or_else(|| self.next_int_var())
1119             }
1120             ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
1121                 tcx.mk_mach_float(ty::float_ty(t))
1122             }
1123             ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
1124                 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
1125                     ty::Float(_) => Some(ty),
1126                     _ => None,
1127                 });
1128                 opt_ty.unwrap_or_else(|| self.next_float_var())
1129             }
1130             ast::LitKind::Bool(_) => tcx.types.bool,
1131             ast::LitKind::Err(_) => tcx.ty_error(),
1132         }
1133     }
1134
1135     pub fn check_struct_path(
1136         &self,
1137         qpath: &QPath<'_>,
1138         hir_id: hir::HirId,
1139     ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
1140         let path_span = qpath.span();
1141         let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
1142         let variant = match def {
1143             Res::Err => {
1144                 self.set_tainted_by_errors();
1145                 return None;
1146             }
1147             Res::Def(DefKind::Variant, _) => match ty.kind() {
1148                 ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
1149                 _ => bug!("unexpected type: {:?}", ty),
1150             },
1151             Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1152             | Res::SelfTy { .. } => match ty.kind() {
1153                 ty::Adt(adt, substs) if !adt.is_enum() => {
1154                     Some((adt.non_enum_variant(), adt.did(), substs))
1155                 }
1156                 _ => None,
1157             },
1158             _ => bug!("unexpected definition: {:?}", def),
1159         };
1160
1161         if let Some((variant, did, substs)) = variant {
1162             debug!("check_struct_path: did={:?} substs={:?}", did, substs);
1163             self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
1164
1165             // Check bounds on type arguments used in the path.
1166             self.add_required_obligations(path_span, did, substs);
1167
1168             Some((variant, ty))
1169         } else {
1170             match ty.kind() {
1171                 ty::Error(_) => {
1172                     // E0071 might be caused by a spelling error, which will have
1173                     // already caused an error message and probably a suggestion
1174                     // elsewhere. Refrain from emitting more unhelpful errors here
1175                     // (issue #88844).
1176                 }
1177                 _ => {
1178                     struct_span_err!(
1179                         self.tcx.sess,
1180                         path_span,
1181                         E0071,
1182                         "expected struct, variant or union type, found {}",
1183                         ty.sort_string(self.tcx)
1184                     )
1185                     .span_label(path_span, "not a struct")
1186                     .emit();
1187                 }
1188             }
1189             None
1190         }
1191     }
1192
1193     pub fn check_decl_initializer(
1194         &self,
1195         hir_id: hir::HirId,
1196         pat: &'tcx hir::Pat<'tcx>,
1197         init: &'tcx hir::Expr<'tcx>,
1198     ) -> Ty<'tcx> {
1199         // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
1200         // for #42640 (default match binding modes).
1201         //
1202         // See #44848.
1203         let ref_bindings = pat.contains_explicit_ref_binding();
1204
1205         let local_ty = self.local_ty(init.span, hir_id).revealed_ty;
1206         if let Some(m) = ref_bindings {
1207             // Somewhat subtle: if we have a `ref` binding in the pattern,
1208             // we want to avoid introducing coercions for the RHS. This is
1209             // both because it helps preserve sanity and, in the case of
1210             // ref mut, for soundness (issue #23116). In particular, in
1211             // the latter case, we need to be clear that the type of the
1212             // referent for the reference that results is *equal to* the
1213             // type of the place it is referencing, and not some
1214             // supertype thereof.
1215             let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
1216             self.demand_eqtype(init.span, local_ty, init_ty);
1217             init_ty
1218         } else {
1219             self.check_expr_coercable_to_type(init, local_ty, None)
1220         }
1221     }
1222
1223     pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
1224         // Determine and write the type which we'll check the pattern against.
1225         let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty;
1226         self.write_ty(decl.hir_id, decl_ty);
1227
1228         // Type check the initializer.
1229         if let Some(ref init) = decl.init {
1230             let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
1231             self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty);
1232         }
1233
1234         // Does the expected pattern type originate from an expression and what is the span?
1235         let (origin_expr, ty_span) = match (decl.ty, decl.init) {
1236             (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
1237             (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee.
1238             _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
1239         };
1240
1241         // Type check the pattern. Override if necessary to avoid knock-on errors.
1242         self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
1243         let pat_ty = self.node_ty(decl.pat.hir_id);
1244         self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
1245
1246         if let Some(blk) = decl.els {
1247             let previous_diverges = self.diverges.get();
1248             let else_ty = self.check_block_with_expected(blk, NoExpectation);
1249             let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
1250             if let Some(mut err) =
1251                 self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
1252             {
1253                 err.emit();
1254             }
1255             self.diverges.set(previous_diverges);
1256         }
1257     }
1258
1259     /// Type check a `let` statement.
1260     pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
1261         self.check_decl(local.into());
1262     }
1263
1264     pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
1265         // Don't do all the complex logic below for `DeclItem`.
1266         match stmt.kind {
1267             hir::StmtKind::Item(..) => return,
1268             hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
1269         }
1270
1271         self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
1272
1273         // Hide the outer diverging and `has_errors` flags.
1274         let old_diverges = self.diverges.replace(Diverges::Maybe);
1275         let old_has_errors = self.has_errors.replace(false);
1276
1277         match stmt.kind {
1278             hir::StmtKind::Local(l) => {
1279                 self.check_decl_local(l);
1280             }
1281             // Ignore for now.
1282             hir::StmtKind::Item(_) => {}
1283             hir::StmtKind::Expr(ref expr) => {
1284                 // Check with expected type of `()`.
1285                 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
1286                     if expr.can_have_side_effects() {
1287                         self.suggest_semicolon_at_end(expr.span, err);
1288                     }
1289                 });
1290             }
1291             hir::StmtKind::Semi(ref expr) => {
1292                 // All of this is equivalent to calling `check_expr`, but it is inlined out here
1293                 // in order to capture the fact that this `match` is the last statement in its
1294                 // function. This is done for better suggestions to remove the `;`.
1295                 let expectation = match expr.kind {
1296                     hir::ExprKind::Match(..) if is_last => IsLast(stmt.span),
1297                     _ => NoExpectation,
1298                 };
1299                 self.check_expr_with_expectation(expr, expectation);
1300             }
1301         }
1302
1303         // Combine the diverging and `has_error` flags.
1304         self.diverges.set(self.diverges.get() | old_diverges);
1305         self.has_errors.set(self.has_errors.get() | old_has_errors);
1306     }
1307
1308     pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
1309         let unit = self.tcx.mk_unit();
1310         let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
1311
1312         // if the block produces a `!` value, that can always be
1313         // (effectively) coerced to unit.
1314         if !ty.is_never() {
1315             self.demand_suptype(blk.span, unit, ty);
1316         }
1317     }
1318
1319     pub(in super::super) fn check_block_with_expected(
1320         &self,
1321         blk: &'tcx hir::Block<'tcx>,
1322         expected: Expectation<'tcx>,
1323     ) -> Ty<'tcx> {
1324         let prev = self.ps.replace(self.ps.get().recurse(blk));
1325
1326         // In some cases, blocks have just one exit, but other blocks
1327         // can be targeted by multiple breaks. This can happen both
1328         // with labeled blocks as well as when we desugar
1329         // a `try { ... }` expression.
1330         //
1331         // Example 1:
1332         //
1333         //    'a: { if true { break 'a Err(()); } Ok(()) }
1334         //
1335         // Here we would wind up with two coercions, one from
1336         // `Err(())` and the other from the tail expression
1337         // `Ok(())`. If the tail expression is omitted, that's a
1338         // "forced unit" -- unless the block diverges, in which
1339         // case we can ignore the tail expression (e.g., `'a: {
1340         // break 'a 22; }` would not force the type of the block
1341         // to be `()`).
1342         let tail_expr = blk.expr.as_ref();
1343         let coerce_to_ty = expected.coercion_target_type(self, blk.span);
1344         let coerce = if blk.targeted_by_break {
1345             CoerceMany::new(coerce_to_ty)
1346         } else {
1347             let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
1348                 Some(e) => slice::from_ref(e),
1349                 None => &[],
1350             };
1351             CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
1352         };
1353
1354         let prev_diverges = self.diverges.get();
1355         let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
1356
1357         let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
1358             for (pos, s) in blk.stmts.iter().enumerate() {
1359                 self.check_stmt(s, blk.stmts.len() - 1 == pos);
1360             }
1361
1362             // check the tail expression **without** holding the
1363             // `enclosing_breakables` lock below.
1364             let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
1365
1366             let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
1367             let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
1368             let coerce = ctxt.coerce.as_mut().unwrap();
1369             if let Some(tail_expr_ty) = tail_expr_ty {
1370                 let tail_expr = tail_expr.unwrap();
1371                 let span = self.get_expr_coercion_span(tail_expr);
1372                 let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
1373                 let ty_for_diagnostic = coerce.merged_ty();
1374                 // We use coerce_inner here because we want to augment the error
1375                 // suggesting to wrap the block in square brackets if it might've
1376                 // been mistaken array syntax
1377                 coerce.coerce_inner(
1378                     self,
1379                     &cause,
1380                     Some(tail_expr),
1381                     tail_expr_ty,
1382                     Some(&mut |diag: &mut Diagnostic| {
1383                         self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
1384                     }),
1385                     false,
1386                 );
1387             } else {
1388                 // Subtle: if there is no explicit tail expression,
1389                 // that is typically equivalent to a tail expression
1390                 // of `()` -- except if the block diverges. In that
1391                 // case, there is no value supplied from the tail
1392                 // expression (assuming there are no other breaks,
1393                 // this implies that the type of the block will be
1394                 // `!`).
1395                 //
1396                 // #41425 -- label the implicit `()` as being the
1397                 // "found type" here, rather than the "expected type".
1398                 if !self.diverges.get().is_always() {
1399                     // #50009 -- Do not point at the entire fn block span, point at the return type
1400                     // span, as it is the cause of the requirement, and
1401                     // `consider_hint_about_removing_semicolon` will point at the last expression
1402                     // if it were a relevant part of the error. This improves usability in editors
1403                     // that highlight errors inline.
1404                     let mut sp = blk.span;
1405                     let mut fn_span = None;
1406                     if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
1407                         let ret_sp = decl.output.span();
1408                         if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
1409                             // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
1410                             // output would otherwise be incorrect and even misleading. Make sure
1411                             // the span we're aiming at correspond to a `fn` body.
1412                             if block_sp == blk.span {
1413                                 sp = ret_sp;
1414                                 fn_span = Some(ident.span);
1415                             }
1416                         }
1417                     }
1418                     coerce.coerce_forced_unit(
1419                         self,
1420                         &self.misc(sp),
1421                         &mut |err| {
1422                             if let Some(expected_ty) = expected.only_has_type(self) {
1423                                 if !self.consider_removing_semicolon(blk, expected_ty, err) {
1424                                     self.consider_returning_binding(blk, expected_ty, err);
1425                                 }
1426                                 if expected_ty == self.tcx.types.bool {
1427                                     // If this is caused by a missing `let` in a `while let`,
1428                                     // silence this redundant error, as we already emit E0070.
1429
1430                                     // Our block must be a `assign desugar local; assignment`
1431                                     if let Some(hir::Node::Block(hir::Block {
1432                                         stmts:
1433                                             [
1434                                                 hir::Stmt {
1435                                                     kind:
1436                                                         hir::StmtKind::Local(hir::Local {
1437                                                             source:
1438                                                                 hir::LocalSource::AssignDesugar(_),
1439                                                             ..
1440                                                         }),
1441                                                     ..
1442                                                 },
1443                                                 hir::Stmt {
1444                                                     kind:
1445                                                         hir::StmtKind::Expr(hir::Expr {
1446                                                             kind: hir::ExprKind::Assign(..),
1447                                                             ..
1448                                                         }),
1449                                                     ..
1450                                                 },
1451                                             ],
1452                                         ..
1453                                     })) = self.tcx.hir().find(blk.hir_id)
1454                                     {
1455                                         self.comes_from_while_condition(blk.hir_id, |_| {
1456                                             err.downgrade_to_delayed_bug();
1457                                         })
1458                                     }
1459                                 }
1460                             }
1461                             if let Some(fn_span) = fn_span {
1462                                 err.span_label(
1463                                     fn_span,
1464                                     "implicitly returns `()` as its body has no tail or `return` \
1465                                      expression",
1466                                 );
1467                             }
1468                         },
1469                         false,
1470                     );
1471                 }
1472             }
1473         });
1474
1475         if ctxt.may_break {
1476             // If we can break from the block, then the block's exit is always reachable
1477             // (... as long as the entry is reachable) - regardless of the tail of the block.
1478             self.diverges.set(prev_diverges);
1479         }
1480
1481         let mut ty = ctxt.coerce.unwrap().complete(self);
1482
1483         if self.has_errors.get() || ty.references_error() {
1484             ty = self.tcx.ty_error()
1485         }
1486
1487         self.write_ty(blk.hir_id, ty);
1488
1489         self.ps.set(prev);
1490         ty
1491     }
1492
1493     fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
1494         let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id));
1495         match node {
1496             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
1497             | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
1498                 let body = self.tcx.hir().body(body_id);
1499                 if let ExprKind::Block(block, _) = &body.value.kind {
1500                     return Some(block.span);
1501                 }
1502             }
1503             _ => {}
1504         }
1505         None
1506     }
1507
1508     /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
1509     fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
1510         let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id));
1511         self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
1512     }
1513
1514     /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
1515     /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
1516     /// when given code like the following:
1517     /// ```text
1518     /// if false { return 0i32; } else { 1u32 }
1519     /// //                               ^^^^ point at this instead of the whole `if` expression
1520     /// ```
1521     fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
1522         let check_in_progress = |elem: &hir::Expr<'_>| {
1523             self.in_progress_typeck_results
1524                 .and_then(|typeck_results| typeck_results.borrow().node_type_opt(elem.hir_id))
1525                 .and_then(|ty| {
1526                     if ty.is_never() {
1527                         None
1528                     } else {
1529                         Some(match elem.kind {
1530                             // Point at the tail expression when possible.
1531                             hir::ExprKind::Block(block, _) => {
1532                                 block.expr.map_or(block.span, |e| e.span)
1533                             }
1534                             _ => elem.span,
1535                         })
1536                     }
1537                 })
1538         };
1539
1540         if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
1541             if let Some(rslt) = check_in_progress(el) {
1542                 return rslt;
1543             }
1544         }
1545
1546         if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1547             let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1548             if let Some(span) = iter.next() {
1549                 if iter.next().is_none() {
1550                     return span;
1551                 }
1552             }
1553         }
1554
1555         expr.span
1556     }
1557
1558     fn overwrite_local_ty_if_err(
1559         &self,
1560         hir_id: hir::HirId,
1561         pat: &'tcx hir::Pat<'tcx>,
1562         decl_ty: Ty<'tcx>,
1563         ty: Ty<'tcx>,
1564     ) {
1565         if ty.references_error() {
1566             // Override the types everywhere with `err()` to avoid knock on errors.
1567             self.write_ty(hir_id, ty);
1568             self.write_ty(pat.hir_id, ty);
1569             let local_ty = LocalTy { decl_ty, revealed_ty: ty };
1570             self.locals.borrow_mut().insert(hir_id, local_ty);
1571             self.locals.borrow_mut().insert(pat.hir_id, local_ty);
1572         }
1573     }
1574
1575     // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
1576     // The newly resolved definition is written into `type_dependent_defs`.
1577     fn finish_resolving_struct_path(
1578         &self,
1579         qpath: &QPath<'_>,
1580         path_span: Span,
1581         hir_id: hir::HirId,
1582     ) -> (Res, Ty<'tcx>) {
1583         match *qpath {
1584             QPath::Resolved(ref maybe_qself, ref path) => {
1585                 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
1586                 let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
1587                 (path.res, ty)
1588             }
1589             QPath::TypeRelative(ref qself, ref segment) => {
1590                 let ty = self.to_ty(qself);
1591
1592                 let result = <dyn AstConv<'_>>::associated_path_to_ty(
1593                     self, hir_id, path_span, ty, qself, segment, true,
1594                 );
1595                 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
1596                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
1597
1598                 // Write back the new resolution.
1599                 self.write_resolution(hir_id, result);
1600
1601                 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1602             }
1603             QPath::LangItem(lang_item, span, id) => {
1604                 self.resolve_lang_item_path(lang_item, span, hir_id, id)
1605             }
1606         }
1607     }
1608
1609     /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
1610     /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
1611     /// reference a type argument. The reason to walk also the checked type is that the coerced type
1612     /// can be not easily comparable with predicate type (because of coercion). If the types match
1613     /// for either checked or coerced type, and there's only *one* argument that does, we point at
1614     /// the corresponding argument's expression span instead of the `fn` call path span.
1615     fn point_at_arg_instead_of_call_if_possible(
1616         &self,
1617         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1618         expr: &'tcx hir::Expr<'tcx>,
1619         call_sp: Span,
1620         args: &'tcx [hir::Expr<'tcx>],
1621         expected_tys: &[Ty<'tcx>],
1622     ) {
1623         // We *do not* do this for desugared call spans to keep good diagnostics when involving
1624         // the `?` operator.
1625         if call_sp.desugaring_kind().is_some() {
1626             return;
1627         }
1628
1629         'outer: for error in errors {
1630             // Only if the cause is somewhere inside the expression we want try to point at arg.
1631             // Otherwise, it means that the cause is somewhere else and we should not change
1632             // anything because we can break the correct span.
1633             if !call_sp.contains(error.obligation.cause.span) {
1634                 continue;
1635             }
1636
1637             // Peel derived obligation, because it's the type that originally
1638             // started this inference chain that matters, not the one we wound
1639             // up with at the end.
1640             fn unpeel_to_top<'a, 'tcx>(
1641                 mut code: &'a ObligationCauseCode<'tcx>,
1642             ) -> &'a ObligationCauseCode<'tcx> {
1643                 let mut result_code = code;
1644                 loop {
1645                     let parent = match code {
1646                         ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
1647                         ObligationCauseCode::BuiltinDerivedObligation(c)
1648                         | ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
1649                         _ => break result_code,
1650                     };
1651                     (result_code, code) = (code, parent);
1652                 }
1653             }
1654             let self_: ty::subst::GenericArg<'_> =
1655                 match unpeel_to_top(error.obligation.cause.code()) {
1656                     ObligationCauseCode::BuiltinDerivedObligation(code)
1657                     | ObligationCauseCode::DerivedObligation(code) => {
1658                         code.parent_trait_pred.self_ty().skip_binder().into()
1659                     }
1660                     ObligationCauseCode::ImplDerivedObligation(code) => {
1661                         code.derived.parent_trait_pred.self_ty().skip_binder().into()
1662                     }
1663                     _ if let ty::PredicateKind::Trait(predicate) =
1664                         error.obligation.predicate.kind().skip_binder() =>
1665                     {
1666                         predicate.self_ty().into()
1667                     }
1668                     _ => continue,
1669                 };
1670             let self_ = self.resolve_vars_if_possible(self_);
1671             let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
1672
1673             let typeck_results = self.typeck_results.borrow();
1674
1675             for (idx, arg) in args.iter().enumerate() {
1676                 // Don't adjust the span if we already have a more precise span
1677                 // within one of the args.
1678                 if arg.span.contains(error.obligation.cause.span) {
1679                     let references_arg =
1680                         typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
1681                             || expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
1682                     if references_arg && !arg.span.from_expansion() {
1683                         error.obligation.cause.map_code(|parent_code| {
1684                             ObligationCauseCode::FunctionArgumentObligation {
1685                                 arg_hir_id: args[idx].hir_id,
1686                                 call_hir_id: expr.hir_id,
1687                                 parent_code,
1688                             }
1689                         })
1690                     }
1691                     continue 'outer;
1692                 }
1693             }
1694
1695             // Collect the argument position for all arguments that could have caused this
1696             // `FulfillmentError`.
1697             let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
1698                 .enumerate()
1699                 .flat_map(|(idx, (expected_ty, arg))| {
1700                     if let Some(arg_ty) = typeck_results.expr_ty_opt(arg) {
1701                         vec![(idx, arg_ty), (idx, *expected_ty)]
1702                     } else {
1703                         vec![]
1704                     }
1705                 })
1706                 .filter_map(|(i, ty)| {
1707                     let ty = self.resolve_vars_if_possible(ty);
1708                     // We walk the argument type because the argument's type could have
1709                     // been `Option<T>`, but the `FulfillmentError` references `T`.
1710                     if ty_matches_self(ty) { Some(i) } else { None }
1711                 })
1712                 .collect();
1713
1714             // Both checked and coerced types could have matched, thus we need to remove
1715             // duplicates.
1716
1717             // We sort primitive type usize here and can use unstable sort
1718             referenced_in.sort_unstable();
1719             referenced_in.dedup();
1720
1721             if let &[idx] = &referenced_in[..] {
1722                 // Do not point at the inside of a macro.
1723                 // That would often result in poor error messages.
1724                 if args[idx].span.from_expansion() {
1725                     continue;
1726                 }
1727                 // We make sure that only *one* argument matches the obligation failure
1728                 // and we assign the obligation's span to its expression's.
1729                 error.obligation.cause.span = args[idx].span;
1730                 error.obligation.cause.map_code(|parent_code| {
1731                     ObligationCauseCode::FunctionArgumentObligation {
1732                         arg_hir_id: args[idx].hir_id,
1733                         call_hir_id: expr.hir_id,
1734                         parent_code,
1735                     }
1736                 });
1737             } else if error.obligation.cause.span == call_sp {
1738                 // Make function calls point at the callee, not the whole thing.
1739                 if let hir::ExprKind::Call(callee, _) = expr.kind {
1740                     error.obligation.cause.span = callee.span;
1741                 }
1742             }
1743         }
1744     }
1745
1746     /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
1747     /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
1748     /// were caused by them. If they were, we point at the corresponding type argument's span
1749     /// instead of the `fn` call path span.
1750     fn point_at_type_arg_instead_of_call_if_possible(
1751         &self,
1752         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1753         call_expr: &'tcx hir::Expr<'tcx>,
1754     ) {
1755         if let hir::ExprKind::Call(path, _) = &call_expr.kind {
1756             if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
1757                 for error in errors {
1758                     if let ty::PredicateKind::Trait(predicate) =
1759                         error.obligation.predicate.kind().skip_binder()
1760                     {
1761                         // If any of the type arguments in this path segment caused the
1762                         // `FulfillmentError`, point at its span (#61860).
1763                         for arg in path
1764                             .segments
1765                             .iter()
1766                             .filter_map(|seg| seg.args.as_ref())
1767                             .flat_map(|a| a.args.iter())
1768                         {
1769                             if let hir::GenericArg::Type(hir_ty) = &arg {
1770                                 let ty = self.resolve_vars_if_possible(
1771                                     self.typeck_results.borrow().node_type(hir_ty.hir_id),
1772                                 );
1773                                 if ty == predicate.self_ty() {
1774                                     error.obligation.cause.span = hir_ty.span;
1775                                 }
1776                             }
1777                         }
1778                     }
1779                 }
1780             }
1781         }
1782     }
1783
1784     fn label_fn_like(
1785         &self,
1786         err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>,
1787         callable_def_id: Option<DefId>,
1788         callee_ty: Option<Ty<'tcx>>,
1789     ) {
1790         let Some(mut def_id) = callable_def_id else {
1791             return;
1792         };
1793
1794         if let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
1795             // Possibly points at either impl or trait item, so try to get it
1796             // to point to trait item, then get the parent.
1797             // This parent might be an impl in the case of an inherent function,
1798             // but the next check will fail.
1799             && let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
1800             && let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
1801             // Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
1802             && let Some(call_kind) = ty::ClosureKind::from_def_id(self.tcx, maybe_trait_def_id)
1803             && let Some(callee_ty) = callee_ty
1804         {
1805             let callee_ty = callee_ty.peel_refs();
1806             match *callee_ty.kind() {
1807                 ty::Param(param) => {
1808                     let param =
1809                         self.tcx.generics_of(self.body_id.owner).type_param(&param, self.tcx);
1810                     if param.kind.is_synthetic() {
1811                         // if it's `impl Fn() -> ..` then just fall down to the def-id based logic
1812                         def_id = param.def_id;
1813                     } else {
1814                         // Otherwise, find the predicate that makes this generic callable,
1815                         // and point at that.
1816                         let instantiated = self
1817                             .tcx
1818                             .explicit_predicates_of(self.body_id.owner)
1819                             .instantiate_identity(self.tcx);
1820                         // FIXME(compiler-errors): This could be problematic if something has two
1821                         // fn-like predicates with different args, but callable types really never
1822                         // do that, so it's OK.
1823                         for (predicate, span) in
1824                             std::iter::zip(instantiated.predicates, instantiated.spans)
1825                         {
1826                             if let ty::PredicateKind::Trait(pred) = predicate.kind().skip_binder()
1827                                 && pred.self_ty().peel_refs() == callee_ty
1828                                 && ty::ClosureKind::from_def_id(self.tcx, pred.def_id()).is_some()
1829                             {
1830                                 err.span_note(span, "callable defined here");
1831                                 return;
1832                             }
1833                         }
1834                     }
1835                 }
1836                 ty::Opaque(new_def_id, _)
1837                 | ty::Closure(new_def_id, _)
1838                 | ty::FnDef(new_def_id, _) => {
1839                     def_id = new_def_id;
1840                 }
1841                 _ => {
1842                     // Look for a user-provided impl of a `Fn` trait, and point to it.
1843                     let new_def_id = self.probe(|_| {
1844                         let trait_ref = ty::TraitRef::new(
1845                             call_kind.to_def_id(self.tcx),
1846                             self.tcx.mk_substs([
1847                                 ty::GenericArg::from(callee_ty),
1848                                 self.next_ty_var(TypeVariableOrigin {
1849                                     kind: TypeVariableOriginKind::MiscVariable,
1850                                     span: rustc_span::DUMMY_SP,
1851                                 })
1852                                 .into(),
1853                             ].into_iter()),
1854                         );
1855                         let obligation = traits::Obligation::new(
1856                             traits::ObligationCause::dummy(),
1857                             self.param_env,
1858                             ty::Binder::dummy(ty::TraitPredicate {
1859                                 trait_ref,
1860                                 constness: ty::BoundConstness::NotConst,
1861                                 polarity: ty::ImplPolarity::Positive,
1862                             }),
1863                         );
1864                         match SelectionContext::new(&self).select(&obligation) {
1865                             Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
1866                                 Some(impl_source.impl_def_id)
1867                             }
1868                             _ => None
1869                         }
1870                     });
1871                     if let Some(new_def_id) = new_def_id {
1872                         def_id = new_def_id;
1873                     } else {
1874                         return;
1875                     }
1876                 }
1877             }
1878         }
1879
1880         if let Some(def_span) = self.tcx.def_ident_span(def_id) && !def_span.is_dummy() {
1881             let mut spans: MultiSpan = def_span.into();
1882
1883             let params = self
1884                 .tcx
1885                 .hir()
1886                 .get_if_local(def_id)
1887                 .and_then(|node| node.body_id())
1888                 .into_iter()
1889                 .flat_map(|id| self.tcx.hir().body(id).params);
1890
1891             for param in params {
1892                 spans.push_span_label(param.span, "");
1893             }
1894
1895             let def_kind = self.tcx.def_kind(def_id);
1896             err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
1897         } else {
1898             let def_kind = self.tcx.def_kind(def_id);
1899             err.span_note(
1900                 self.tcx.def_span(def_id),
1901                 &format!("{} defined here", def_kind.descr(def_id)),
1902             );
1903         }
1904     }
1905 }