]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Auto merge of #94255 - b-naber:use-mir-constant-in-thir, r=oli-obk
[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::gather_locals::Declaration;
4 use crate::check::method::MethodCallee;
5 use crate::check::Expectation::*;
6 use crate::check::TupleArgumentsFlag::*;
7 use crate::check::{
8     potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
9     LocalTy, Needs, TupleArgumentsFlag,
10 };
11
12 use rustc_ast as ast;
13 use rustc_data_structures::sync::Lrc;
14 use rustc_errors::{Applicability, Diagnostic, DiagnosticId, MultiSpan};
15 use rustc_hir as hir;
16 use rustc_hir::def::{CtorOf, DefKind, Res};
17 use rustc_hir::def_id::DefId;
18 use rustc_hir::{ExprKind, Node, QPath};
19 use rustc_middle::ty::adjustment::AllowTwoPhase;
20 use rustc_middle::ty::fold::TypeFoldable;
21 use rustc_middle::ty::{self, Ty};
22 use rustc_session::Session;
23 use rustc_span::symbol::Ident;
24 use rustc_span::{self, Span};
25 use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
26
27 use crate::structured_errors::StructuredDiagnostic;
28 use std::iter;
29 use std::slice;
30
31 struct FnArgsAsTuple<'hir> {
32     first: &'hir hir::Expr<'hir>,
33     last: &'hir hir::Expr<'hir>,
34 }
35
36 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37     pub(in super::super) fn check_casts(&self) {
38         let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
39         debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
40         for cast in deferred_cast_checks.drain(..) {
41             cast.check(self);
42         }
43     }
44
45     pub(in super::super) fn check_method_argument_types(
46         &self,
47         sp: Span,
48         expr: &'tcx hir::Expr<'tcx>,
49         method: Result<MethodCallee<'tcx>, ()>,
50         args_no_rcvr: &'tcx [hir::Expr<'tcx>],
51         tuple_arguments: TupleArgumentsFlag,
52         expected: Expectation<'tcx>,
53     ) -> Ty<'tcx> {
54         let has_error = match method {
55             Ok(method) => method.substs.references_error() || method.sig.references_error(),
56             Err(_) => true,
57         };
58         if has_error {
59             let err_inputs = self.err_args(args_no_rcvr.len());
60
61             let err_inputs = match tuple_arguments {
62                 DontTupleArguments => err_inputs,
63                 TupleArguments => vec![self.tcx.intern_tup(&err_inputs)],
64             };
65
66             self.check_argument_types(
67                 sp,
68                 expr,
69                 &err_inputs,
70                 vec![],
71                 args_no_rcvr,
72                 false,
73                 tuple_arguments,
74                 None,
75             );
76             return self.tcx.ty_error();
77         }
78
79         let method = method.unwrap();
80         // HACK(eddyb) ignore self in the definition (see above).
81         let expected_input_tys = self.expected_inputs_for_expected_output(
82             sp,
83             expected,
84             method.sig.output(),
85             &method.sig.inputs()[1..],
86         );
87         self.check_argument_types(
88             sp,
89             expr,
90             &method.sig.inputs()[1..],
91             expected_input_tys,
92             args_no_rcvr,
93             method.sig.c_variadic,
94             tuple_arguments,
95             Some(method.def_id),
96         );
97         method.sig.output()
98     }
99
100     /// Generic function that factors out common logic from function calls,
101     /// method calls and overloaded operators.
102     pub(in super::super) fn check_argument_types(
103         &self,
104         // Span enclosing the call site
105         call_span: Span,
106         // Expression of the call site
107         call_expr: &'tcx hir::Expr<'tcx>,
108         // Types (as defined in the *signature* of the target function)
109         formal_input_tys: &[Ty<'tcx>],
110         // More specific expected types, after unifying with caller output types
111         expected_input_tys: Vec<Ty<'tcx>>,
112         // The expressions for each provided argument
113         provided_args: &'tcx [hir::Expr<'tcx>],
114         // Whether the function is variadic, for example when imported from C
115         c_variadic: bool,
116         // Whether the arguments have been bundled in a tuple (ex: closures)
117         tuple_arguments: TupleArgumentsFlag,
118         // The DefId for the function being called, for better error messages
119         fn_def_id: Option<DefId>,
120     ) {
121         let tcx = self.tcx;
122         // Grab the argument types, supplying fresh type variables
123         // if the wrong number of arguments were supplied
124         let supplied_arg_count =
125             if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 };
126
127         // All the input types from the fn signature must outlive the call
128         // so as to validate implied bounds.
129         for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
130             self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
131         }
132
133         let expected_arg_count = formal_input_tys.len();
134
135         // expected_count, arg_count, error_code, sugg_unit, sugg_tuple_wrap_args
136         let mut arg_count_error: Option<(usize, usize, &str, bool, Option<FnArgsAsTuple<'_>>)> =
137             None;
138
139         // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
140         let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
141             let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
142             match tuple_type.kind() {
143                 // We expected a tuple and got a tuple
144                 ty::Tuple(arg_types) => {
145                     // Argument length differs
146                     if arg_types.len() != provided_args.len() {
147                         arg_count_error =
148                             Some((arg_types.len(), provided_args.len(), "E0057", false, None));
149                     }
150                     let expected_input_tys = match expected_input_tys.get(0) {
151                         Some(&ty) => match ty.kind() {
152                             ty::Tuple(tys) => tys.iter().collect(),
153                             _ => vec![],
154                         },
155                         None => vec![],
156                     };
157                     (arg_types.iter().collect(), expected_input_tys)
158                 }
159                 _ => {
160                     // Otherwise, there's a mismatch, so clear out what we're expecting, and set
161                     // our input types to err_args so we don't blow up the error messages
162                     struct_span_err!(
163                         tcx.sess,
164                         call_span,
165                         E0059,
166                         "cannot use call notation; the first type parameter \
167                          for the function trait is neither a tuple nor unit"
168                     )
169                     .emit();
170                     (self.err_args(provided_args.len()), vec![])
171                 }
172             }
173         } else if expected_arg_count == supplied_arg_count {
174             (formal_input_tys.to_vec(), expected_input_tys)
175         } else if c_variadic {
176             if supplied_arg_count >= expected_arg_count {
177                 (formal_input_tys.to_vec(), expected_input_tys)
178             } else {
179                 arg_count_error =
180                     Some((expected_arg_count, supplied_arg_count, "E0060", false, None));
181                 (self.err_args(supplied_arg_count), vec![])
182             }
183         } else {
184             // is the missing argument of type `()`?
185             let sugg_unit = if expected_input_tys.len() == 1 && supplied_arg_count == 0 {
186                 self.resolve_vars_if_possible(expected_input_tys[0]).is_unit()
187             } else if formal_input_tys.len() == 1 && supplied_arg_count == 0 {
188                 self.resolve_vars_if_possible(formal_input_tys[0]).is_unit()
189             } else {
190                 false
191             };
192
193             // are we passing elements of a tuple without the tuple parentheses?
194             let expected_input_tys = if expected_input_tys.is_empty() {
195                 // In most cases we can use expected_input_tys, but some callers won't have the type
196                 // information, in which case we fall back to the types from the input expressions.
197                 formal_input_tys
198             } else {
199                 &*expected_input_tys
200             };
201
202             let sugg_tuple_wrap_args = self.suggested_tuple_wrap(expected_input_tys, provided_args);
203
204             arg_count_error = Some((
205                 expected_arg_count,
206                 supplied_arg_count,
207                 "E0061",
208                 sugg_unit,
209                 sugg_tuple_wrap_args,
210             ));
211             (self.err_args(supplied_arg_count), vec![])
212         };
213
214         debug!(
215             "check_argument_types: formal_input_tys={:?}",
216             formal_input_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>()
217         );
218
219         // If there is no expectation, expect formal_input_tys.
220         let expected_input_tys = if !expected_input_tys.is_empty() {
221             expected_input_tys
222         } else {
223             formal_input_tys.clone()
224         };
225
226         assert_eq!(expected_input_tys.len(), formal_input_tys.len());
227
228         let provided_arg_count: usize = provided_args.len();
229
230         // Keep track of the fully coerced argument types
231         let mut final_arg_types: Vec<Option<(Ty<'_>, Ty<'_>)>> = vec![None; provided_arg_count];
232
233         // We introduce a helper function to demand that a given argument satisfy a given input
234         // This is more complicated than just checking type equality, as arguments could be coerced
235         // This version writes those types back so further type checking uses the narrowed types
236         let demand_compatible = |idx, final_arg_types: &mut Vec<Option<(Ty<'tcx>, Ty<'tcx>)>>| {
237             let formal_input_ty: Ty<'tcx> = formal_input_tys[idx];
238             let expected_input_ty: Ty<'tcx> = expected_input_tys[idx];
239             let provided_arg = &provided_args[idx];
240
241             debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
242
243             // The special-cased logic below has three functions:
244             // 1. Provide as good of an expected type as possible.
245             let expectation = Expectation::rvalue_hint(self, expected_input_ty);
246
247             let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
248
249             // 2. Coerce to the most detailed type that could be coerced
250             //    to, which is `expected_ty` if `rvalue_hint` returns an
251             //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
252             let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
253
254             // Keep track of these for below
255             final_arg_types[idx] = Some((checked_ty, coerced_ty));
256
257             // Cause selection errors caused by resolving a single argument to point at the
258             // argument and not the call. This is otherwise redundant with the `demand_coerce`
259             // call immediately after, but it lets us customize the span pointed to in the
260             // fulfillment error to be more accurate.
261             let coerced_ty =
262                 self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
263                     self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
264                     self.point_at_arg_instead_of_call_if_possible(
265                         errors,
266                         &final_arg_types,
267                         call_expr,
268                         call_span,
269                         provided_args,
270                     );
271                 });
272
273             final_arg_types[idx] = Some((checked_ty, coerced_ty));
274
275             // We're processing function arguments so we definitely want to use
276             // two-phase borrows.
277             self.demand_coerce(&provided_arg, checked_ty, coerced_ty, None, AllowTwoPhase::Yes);
278
279             // 3. Relate the expected type and the formal one,
280             //    if the expected type was used for the coercion.
281             self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty);
282         };
283
284         let minimum_input_count = formal_input_tys.len();
285
286         // Check the arguments.
287         // We do this in a pretty awful way: first we type-check any arguments
288         // that are not closures, then we type-check the closures. This is so
289         // that we have more information about the types of arguments when we
290         // type-check the functions. This isn't really the right way to do this.
291         for check_closures in [false, true] {
292             // More awful hacks: before we check argument types, try to do
293             // an "opportunistic" trait resolution of any trait bounds on
294             // the call. This helps coercions.
295             if check_closures {
296                 self.select_obligations_where_possible(false, |errors| {
297                     self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
298                     self.point_at_arg_instead_of_call_if_possible(
299                         errors,
300                         &final_arg_types,
301                         call_expr,
302                         call_span,
303                         &provided_args,
304                     );
305                 })
306             }
307
308             for (idx, arg) in provided_args.iter().enumerate() {
309                 // Warn only for the first loop (the "no closures" one).
310                 // Closure arguments themselves can't be diverging, but
311                 // a previous argument can, e.g., `foo(panic!(), || {})`.
312                 if !check_closures {
313                     self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
314                 }
315
316                 // For C-variadic functions, we don't have a declared type for all of
317                 // the arguments hence we only do our usual type checking with
318                 // the arguments who's types we do know. However, we *can* check
319                 // for unreachable expressions (see above).
320                 // FIXME: unreachable warning current isn't emitted
321                 if idx >= minimum_input_count {
322                     continue;
323                 }
324
325                 let is_closure = matches!(arg.kind, ExprKind::Closure(..));
326                 if is_closure != check_closures {
327                     continue;
328                 }
329
330                 demand_compatible(idx, &mut final_arg_types);
331             }
332         }
333
334         // If there was an error in parameter count, emit that here
335         if let Some((expected_count, arg_count, err_code, sugg_unit, sugg_tuple_wrap_args)) =
336             arg_count_error
337         {
338             let (span, start_span, args, ctor_of) = match &call_expr.kind {
339                 hir::ExprKind::Call(
340                     hir::Expr {
341                         span,
342                         kind:
343                             hir::ExprKind::Path(hir::QPath::Resolved(
344                                 _,
345                                 hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. },
346                             )),
347                         ..
348                     },
349                     args,
350                 ) => (*span, *span, &args[..], Some(of)),
351                 hir::ExprKind::Call(hir::Expr { span, .. }, args) => {
352                     (*span, *span, &args[..], None)
353                 }
354                 hir::ExprKind::MethodCall(path_segment, args, _) => (
355                     path_segment.ident.span,
356                     // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
357                     path_segment
358                         .args
359                         .and_then(|args| args.args.iter().last())
360                         // Account for `foo.bar::<T>()`.
361                         .map(|arg| {
362                             // Skip the closing `>`.
363                             tcx.sess
364                                 .source_map()
365                                 .next_point(tcx.sess.source_map().next_point(arg.span()))
366                         })
367                         .unwrap_or(path_segment.ident.span),
368                     &args[1..], // Skip the receiver.
369                     None,       // methods are never ctors
370                 ),
371                 k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
372             };
373             let arg_spans = if provided_args.is_empty() {
374                 // foo()
375                 // ^^^-- supplied 0 arguments
376                 // |
377                 // expected 2 arguments
378                 vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())]
379             } else {
380                 // foo(1, 2, 3)
381                 // ^^^ -  -  - supplied 3 arguments
382                 // |
383                 // expected 2 arguments
384                 args.iter().map(|arg| arg.span).collect::<Vec<Span>>()
385             };
386             let call_name = match ctor_of {
387                 Some(CtorOf::Struct) => "struct",
388                 Some(CtorOf::Variant) => "enum variant",
389                 None => "function",
390             };
391             let mut err = tcx.sess.struct_span_err_with_code(
392                 span,
393                 &format!(
394                     "this {} takes {}{} but {} {} supplied",
395                     call_name,
396                     if c_variadic { "at least " } else { "" },
397                     potentially_plural_count(expected_count, "argument"),
398                     potentially_plural_count(arg_count, "argument"),
399                     if arg_count == 1 { "was" } else { "were" }
400                 ),
401                 DiagnosticId::Error(err_code.to_owned()),
402             );
403             let label = format!("supplied {}", potentially_plural_count(arg_count, "argument"));
404             for (i, span) in arg_spans.into_iter().enumerate() {
405                 err.span_label(
406                     span,
407                     if arg_count == 0 || i + 1 == arg_count { &label } else { "" },
408                 );
409             }
410             if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
411                 let mut spans: MultiSpan = def_span.into();
412
413                 let params = tcx
414                     .hir()
415                     .get_if_local(def_id)
416                     .and_then(|node| node.body_id())
417                     .into_iter()
418                     .map(|id| tcx.hir().body(id).params)
419                     .flatten();
420
421                 for param in params {
422                     spans.push_span_label(param.span, String::new());
423                 }
424
425                 let def_kind = tcx.def_kind(def_id);
426                 err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
427             }
428             if sugg_unit {
429                 let sugg_span = tcx.sess.source_map().end_point(call_expr.span);
430                 // remove closing `)` from the span
431                 let sugg_span = sugg_span.shrink_to_lo();
432                 err.span_suggestion(
433                     sugg_span,
434                     "expected the unit value `()`; create it with empty parentheses",
435                     String::from("()"),
436                     Applicability::MachineApplicable,
437                 );
438             } else if let Some(FnArgsAsTuple { first, last }) = sugg_tuple_wrap_args {
439                 err.multipart_suggestion(
440                     "use parentheses to construct a tuple",
441                     vec![
442                         (first.span.shrink_to_lo(), '('.to_string()),
443                         (last.span.shrink_to_hi(), ')'.to_string()),
444                     ],
445                     Applicability::MachineApplicable,
446                 );
447             } else {
448                 err.span_label(
449                     span,
450                     format!(
451                         "expected {}{}",
452                         if c_variadic { "at least " } else { "" },
453                         potentially_plural_count(expected_count, "argument")
454                     ),
455                 );
456             }
457             err.emit();
458         }
459
460         for arg in provided_args.iter().skip(minimum_input_count) {
461             let arg_ty = self.check_expr(&arg);
462
463             if c_variadic {
464                 // We also need to make sure we at least write the ty of the other
465                 // arguments which we skipped above, either because they were additional
466                 // c_variadic args, or because we had an argument count mismatch.
467                 fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
468                     use crate::structured_errors::MissingCastForVariadicArg;
469
470                     MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
471                 }
472
473                 // There are a few types which get autopromoted when passed via varargs
474                 // in C but we just error out instead and require explicit casts.
475                 let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
476                 match arg_ty.kind() {
477                     ty::Float(ty::FloatTy::F32) => {
478                         variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
479                     }
480                     ty::Int(ty::IntTy::I8 | ty::IntTy::I16) | ty::Bool => {
481                         variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
482                     }
483                     ty::Uint(ty::UintTy::U8 | ty::UintTy::U16) => {
484                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
485                     }
486                     ty::FnDef(..) => {
487                         let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
488                         let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
489                         variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
490                     }
491                     _ => {}
492                 }
493             }
494         }
495     }
496
497     fn suggested_tuple_wrap(
498         &self,
499         expected_input_tys: &[Ty<'tcx>],
500         provided_args: &'tcx [hir::Expr<'tcx>],
501     ) -> Option<FnArgsAsTuple<'_>> {
502         let [expected_arg_type] = expected_input_tys[..] else { return None };
503
504         let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind()
505             else { return None };
506
507         let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect();
508
509         let all_match = iter::zip(expected_types, supplied_types)
510             .all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok());
511
512         if all_match {
513             match provided_args {
514                 [] => None,
515                 [_] => unreachable!(
516                     "shouldn't reach here - need count mismatch between 1-tuple and 1-argument"
517                 ),
518                 [first, .., last] => Some(FnArgsAsTuple { first, last }),
519             }
520         } else {
521             None
522         }
523     }
524
525     // AST fragment checking
526     pub(in super::super) fn check_lit(
527         &self,
528         lit: &hir::Lit,
529         expected: Expectation<'tcx>,
530     ) -> Ty<'tcx> {
531         let tcx = self.tcx;
532
533         match lit.node {
534             ast::LitKind::Str(..) => tcx.mk_static_str(),
535             ast::LitKind::ByteStr(ref v) => {
536                 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
537             }
538             ast::LitKind::Byte(_) => tcx.types.u8,
539             ast::LitKind::Char(_) => tcx.types.char,
540             ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => tcx.mk_mach_int(ty::int_ty(t)),
541             ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(ty::uint_ty(t)),
542             ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
543                 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
544                     ty::Int(_) | ty::Uint(_) => Some(ty),
545                     ty::Char => Some(tcx.types.u8),
546                     ty::RawPtr(..) => Some(tcx.types.usize),
547                     ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
548                     _ => None,
549                 });
550                 opt_ty.unwrap_or_else(|| self.next_int_var())
551             }
552             ast::LitKind::Float(_, ast::LitFloatType::Suffixed(t)) => {
553                 tcx.mk_mach_float(ty::float_ty(t))
554             }
555             ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => {
556                 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
557                     ty::Float(_) => Some(ty),
558                     _ => None,
559                 });
560                 opt_ty.unwrap_or_else(|| self.next_float_var())
561             }
562             ast::LitKind::Bool(_) => tcx.types.bool,
563             ast::LitKind::Err(_) => tcx.ty_error(),
564         }
565     }
566
567     pub fn check_struct_path(
568         &self,
569         qpath: &QPath<'_>,
570         hir_id: hir::HirId,
571     ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
572         let path_span = qpath.span();
573         let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
574         let variant = match def {
575             Res::Err => {
576                 self.set_tainted_by_errors();
577                 return None;
578             }
579             Res::Def(DefKind::Variant, _) => match ty.kind() {
580                 ty::Adt(adt, substs) => Some((adt.variant_of_res(def), adt.did(), substs)),
581                 _ => bug!("unexpected type: {:?}", ty),
582             },
583             Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
584             | Res::SelfTy { .. } => match ty.kind() {
585                 ty::Adt(adt, substs) if !adt.is_enum() => {
586                     Some((adt.non_enum_variant(), adt.did(), substs))
587                 }
588                 _ => None,
589             },
590             _ => bug!("unexpected definition: {:?}", def),
591         };
592
593         if let Some((variant, did, substs)) = variant {
594             debug!("check_struct_path: did={:?} substs={:?}", did, substs);
595             self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
596
597             // Check bounds on type arguments used in the path.
598             self.add_required_obligations(path_span, did, substs);
599
600             Some((variant, ty))
601         } else {
602             match ty.kind() {
603                 ty::Error(_) => {
604                     // E0071 might be caused by a spelling error, which will have
605                     // already caused an error message and probably a suggestion
606                     // elsewhere. Refrain from emitting more unhelpful errors here
607                     // (issue #88844).
608                 }
609                 _ => {
610                     struct_span_err!(
611                         self.tcx.sess,
612                         path_span,
613                         E0071,
614                         "expected struct, variant or union type, found {}",
615                         ty.sort_string(self.tcx)
616                     )
617                     .span_label(path_span, "not a struct")
618                     .emit();
619                 }
620             }
621             None
622         }
623     }
624
625     pub fn check_decl_initializer(
626         &self,
627         hir_id: hir::HirId,
628         pat: &'tcx hir::Pat<'tcx>,
629         init: &'tcx hir::Expr<'tcx>,
630     ) -> Ty<'tcx> {
631         // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed
632         // for #42640 (default match binding modes).
633         //
634         // See #44848.
635         let ref_bindings = pat.contains_explicit_ref_binding();
636
637         let local_ty = self.local_ty(init.span, hir_id).revealed_ty;
638         if let Some(m) = ref_bindings {
639             // Somewhat subtle: if we have a `ref` binding in the pattern,
640             // we want to avoid introducing coercions for the RHS. This is
641             // both because it helps preserve sanity and, in the case of
642             // ref mut, for soundness (issue #23116). In particular, in
643             // the latter case, we need to be clear that the type of the
644             // referent for the reference that results is *equal to* the
645             // type of the place it is referencing, and not some
646             // supertype thereof.
647             let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
648             self.demand_eqtype(init.span, local_ty, init_ty);
649             init_ty
650         } else {
651             self.check_expr_coercable_to_type(init, local_ty, None)
652         }
653     }
654
655     pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
656         // Determine and write the type which we'll check the pattern against.
657         let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty;
658         self.write_ty(decl.hir_id, decl_ty);
659
660         // Type check the initializer.
661         if let Some(ref init) = decl.init {
662             let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
663             self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty);
664         }
665
666         // Does the expected pattern type originate from an expression and what is the span?
667         let (origin_expr, ty_span) = match (decl.ty, decl.init) {
668             (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
669             (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee.
670             _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
671         };
672
673         // Type check the pattern. Override if necessary to avoid knock-on errors.
674         self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
675         let pat_ty = self.node_ty(decl.pat.hir_id);
676         self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
677     }
678
679     /// Type check a `let` statement.
680     pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
681         self.check_decl(local.into());
682     }
683
684     pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
685         // Don't do all the complex logic below for `DeclItem`.
686         match stmt.kind {
687             hir::StmtKind::Item(..) => return,
688             hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
689         }
690
691         self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement");
692
693         // Hide the outer diverging and `has_errors` flags.
694         let old_diverges = self.diverges.replace(Diverges::Maybe);
695         let old_has_errors = self.has_errors.replace(false);
696
697         match stmt.kind {
698             hir::StmtKind::Local(ref l) => {
699                 self.check_decl_local(&l);
700             }
701             // Ignore for now.
702             hir::StmtKind::Item(_) => {}
703             hir::StmtKind::Expr(ref expr) => {
704                 // Check with expected type of `()`.
705                 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
706                     if expr.can_have_side_effects() {
707                         self.suggest_semicolon_at_end(expr.span, err);
708                     }
709                 });
710             }
711             hir::StmtKind::Semi(ref expr) => {
712                 // All of this is equivalent to calling `check_expr`, but it is inlined out here
713                 // in order to capture the fact that this `match` is the last statement in its
714                 // function. This is done for better suggestions to remove the `;`.
715                 let expectation = match expr.kind {
716                     hir::ExprKind::Match(..) if is_last => IsLast(stmt.span),
717                     _ => NoExpectation,
718                 };
719                 self.check_expr_with_expectation(expr, expectation);
720             }
721         }
722
723         // Combine the diverging and `has_error` flags.
724         self.diverges.set(self.diverges.get() | old_diverges);
725         self.has_errors.set(self.has_errors.get() | old_has_errors);
726     }
727
728     pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
729         let unit = self.tcx.mk_unit();
730         let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
731
732         // if the block produces a `!` value, that can always be
733         // (effectively) coerced to unit.
734         if !ty.is_never() {
735             self.demand_suptype(blk.span, unit, ty);
736         }
737     }
738
739     pub(in super::super) fn check_block_with_expected(
740         &self,
741         blk: &'tcx hir::Block<'tcx>,
742         expected: Expectation<'tcx>,
743     ) -> Ty<'tcx> {
744         let prev = self.ps.replace(self.ps.get().recurse(blk));
745
746         // In some cases, blocks have just one exit, but other blocks
747         // can be targeted by multiple breaks. This can happen both
748         // with labeled blocks as well as when we desugar
749         // a `try { ... }` expression.
750         //
751         // Example 1:
752         //
753         //    'a: { if true { break 'a Err(()); } Ok(()) }
754         //
755         // Here we would wind up with two coercions, one from
756         // `Err(())` and the other from the tail expression
757         // `Ok(())`. If the tail expression is omitted, that's a
758         // "forced unit" -- unless the block diverges, in which
759         // case we can ignore the tail expression (e.g., `'a: {
760         // break 'a 22; }` would not force the type of the block
761         // to be `()`).
762         let tail_expr = blk.expr.as_ref();
763         let coerce_to_ty = expected.coercion_target_type(self, blk.span);
764         let coerce = if blk.targeted_by_break {
765             CoerceMany::new(coerce_to_ty)
766         } else {
767             let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
768                 Some(e) => slice::from_ref(e),
769                 None => &[],
770             };
771             CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
772         };
773
774         let prev_diverges = self.diverges.get();
775         let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
776
777         let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
778             for (pos, s) in blk.stmts.iter().enumerate() {
779                 self.check_stmt(s, blk.stmts.len() - 1 == pos);
780             }
781
782             // check the tail expression **without** holding the
783             // `enclosing_breakables` lock below.
784             let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
785
786             let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
787             let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
788             let coerce = ctxt.coerce.as_mut().unwrap();
789             if let Some(tail_expr_ty) = tail_expr_ty {
790                 let tail_expr = tail_expr.unwrap();
791                 let span = self.get_expr_coercion_span(tail_expr);
792                 let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
793                 let ty_for_diagnostic = coerce.merged_ty();
794                 // We use coerce_inner here because we want to augment the error
795                 // suggesting to wrap the block in square brackets if it might've
796                 // been mistaken array syntax
797                 coerce.coerce_inner(
798                     self,
799                     &cause,
800                     Some(tail_expr),
801                     tail_expr_ty,
802                     Some(&mut |diag: &mut Diagnostic| {
803                         self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
804                     }),
805                     false,
806                 );
807             } else {
808                 // Subtle: if there is no explicit tail expression,
809                 // that is typically equivalent to a tail expression
810                 // of `()` -- except if the block diverges. In that
811                 // case, there is no value supplied from the tail
812                 // expression (assuming there are no other breaks,
813                 // this implies that the type of the block will be
814                 // `!`).
815                 //
816                 // #41425 -- label the implicit `()` as being the
817                 // "found type" here, rather than the "expected type".
818                 if !self.diverges.get().is_always() {
819                     // #50009 -- Do not point at the entire fn block span, point at the return type
820                     // span, as it is the cause of the requirement, and
821                     // `consider_hint_about_removing_semicolon` will point at the last expression
822                     // if it were a relevant part of the error. This improves usability in editors
823                     // that highlight errors inline.
824                     let mut sp = blk.span;
825                     let mut fn_span = None;
826                     if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
827                         let ret_sp = decl.output.span();
828                         if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
829                             // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
830                             // output would otherwise be incorrect and even misleading. Make sure
831                             // the span we're aiming at correspond to a `fn` body.
832                             if block_sp == blk.span {
833                                 sp = ret_sp;
834                                 fn_span = Some(ident.span);
835                             }
836                         }
837                     }
838                     coerce.coerce_forced_unit(
839                         self,
840                         &self.misc(sp),
841                         &mut |err| {
842                             if let Some(expected_ty) = expected.only_has_type(self) {
843                                 self.consider_hint_about_removing_semicolon(blk, expected_ty, err);
844                                 if expected_ty == self.tcx.types.bool {
845                                     // If this is caused by a missing `let` in a `while let`,
846                                     // silence this redundant error, as we already emit E0070.
847
848                                     // Our block must be a `assign desugar local; assignment`
849                                     if let Some(hir::Node::Block(hir::Block {
850                                         stmts:
851                                             [
852                                                 hir::Stmt {
853                                                     kind:
854                                                         hir::StmtKind::Local(hir::Local {
855                                                             source:
856                                                                 hir::LocalSource::AssignDesugar(_),
857                                                             ..
858                                                         }),
859                                                     ..
860                                                 },
861                                                 hir::Stmt {
862                                                     kind:
863                                                         hir::StmtKind::Expr(hir::Expr {
864                                                             kind: hir::ExprKind::Assign(..),
865                                                             ..
866                                                         }),
867                                                     ..
868                                                 },
869                                             ],
870                                         ..
871                                     })) = self.tcx.hir().find(blk.hir_id)
872                                     {
873                                         self.comes_from_while_condition(blk.hir_id, |_| {
874                                             err.downgrade_to_delayed_bug();
875                                         })
876                                     }
877                                 }
878                             }
879                             if let Some(fn_span) = fn_span {
880                                 err.span_label(
881                                     fn_span,
882                                     "implicitly returns `()` as its body has no tail or `return` \
883                                      expression",
884                                 );
885                             }
886                         },
887                         false,
888                     );
889                 }
890             }
891         });
892
893         if ctxt.may_break {
894             // If we can break from the block, then the block's exit is always reachable
895             // (... as long as the entry is reachable) - regardless of the tail of the block.
896             self.diverges.set(prev_diverges);
897         }
898
899         let mut ty = ctxt.coerce.unwrap().complete(self);
900
901         if self.has_errors.get() || ty.references_error() {
902             ty = self.tcx.ty_error()
903         }
904
905         self.write_ty(blk.hir_id, ty);
906
907         self.ps.set(prev);
908         ty
909     }
910
911     /// A common error is to add an extra semicolon:
912     ///
913     /// ```
914     /// fn foo() -> usize {
915     ///     22;
916     /// }
917     /// ```
918     ///
919     /// This routine checks if the final statement in a block is an
920     /// expression with an explicit semicolon whose type is compatible
921     /// with `expected_ty`. If so, it suggests removing the semicolon.
922     fn consider_hint_about_removing_semicolon(
923         &self,
924         blk: &'tcx hir::Block<'tcx>,
925         expected_ty: Ty<'tcx>,
926         err: &mut Diagnostic,
927     ) {
928         if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
929             if let StatementAsExpression::NeedsBoxing = boxed {
930                 err.span_suggestion_verbose(
931                     span_semi,
932                     "consider removing this semicolon and boxing the expression",
933                     String::new(),
934                     Applicability::HasPlaceholders,
935                 );
936             } else {
937                 err.span_suggestion_short(
938                     span_semi,
939                     "remove this semicolon",
940                     String::new(),
941                     Applicability::MachineApplicable,
942                 );
943             }
944         }
945     }
946
947     fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
948         let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id));
949         match node {
950             Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
951             | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
952                 let body = self.tcx.hir().body(body_id);
953                 if let ExprKind::Block(block, _) = &body.value.kind {
954                     return Some(block.span);
955                 }
956             }
957             _ => {}
958         }
959         None
960     }
961
962     /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
963     fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
964         let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id));
965         self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
966     }
967
968     /// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
969     /// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
970     /// when given code like the following:
971     /// ```text
972     /// if false { return 0i32; } else { 1u32 }
973     /// //                               ^^^^ point at this instead of the whole `if` expression
974     /// ```
975     fn get_expr_coercion_span(&self, expr: &hir::Expr<'_>) -> rustc_span::Span {
976         let check_in_progress = |elem: &hir::Expr<'_>| {
977             self.in_progress_typeck_results
978                 .and_then(|typeck_results| typeck_results.borrow().node_type_opt(elem.hir_id))
979                 .and_then(|ty| {
980                     if ty.is_never() {
981                         None
982                     } else {
983                         Some(match elem.kind {
984                             // Point at the tail expression when possible.
985                             hir::ExprKind::Block(block, _) => {
986                                 block.expr.map_or(block.span, |e| e.span)
987                             }
988                             _ => elem.span,
989                         })
990                     }
991                 })
992         };
993
994         if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
995             if let Some(rslt) = check_in_progress(el) {
996                 return rslt;
997             }
998         }
999
1000         if let hir::ExprKind::Match(_, arms, _) = expr.kind {
1001             let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
1002             if let Some(span) = iter.next() {
1003                 if iter.next().is_none() {
1004                     return span;
1005                 }
1006             }
1007         }
1008
1009         expr.span
1010     }
1011
1012     fn overwrite_local_ty_if_err(
1013         &self,
1014         hir_id: hir::HirId,
1015         pat: &'tcx hir::Pat<'tcx>,
1016         decl_ty: Ty<'tcx>,
1017         ty: Ty<'tcx>,
1018     ) {
1019         if ty.references_error() {
1020             // Override the types everywhere with `err()` to avoid knock on errors.
1021             self.write_ty(hir_id, ty);
1022             self.write_ty(pat.hir_id, ty);
1023             let local_ty = LocalTy { decl_ty, revealed_ty: ty };
1024             self.locals.borrow_mut().insert(hir_id, local_ty);
1025             self.locals.borrow_mut().insert(pat.hir_id, local_ty);
1026         }
1027     }
1028
1029     // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
1030     // The newly resolved definition is written into `type_dependent_defs`.
1031     fn finish_resolving_struct_path(
1032         &self,
1033         qpath: &QPath<'_>,
1034         path_span: Span,
1035         hir_id: hir::HirId,
1036     ) -> (Res, Ty<'tcx>) {
1037         match *qpath {
1038             QPath::Resolved(ref maybe_qself, ref path) => {
1039                 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
1040                 let ty = <dyn AstConv<'_>>::res_to_ty(self, self_ty, path, true);
1041                 (path.res, ty)
1042             }
1043             QPath::TypeRelative(ref qself, ref segment) => {
1044                 let ty = self.to_ty(qself);
1045
1046                 let res = if let hir::TyKind::Path(QPath::Resolved(_, ref path)) = qself.kind {
1047                     path.res
1048                 } else {
1049                     Res::Err
1050                 };
1051                 let result = <dyn AstConv<'_>>::associated_path_to_ty(
1052                     self, hir_id, path_span, ty, res, segment, true,
1053                 );
1054                 let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
1055                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
1056
1057                 // Write back the new resolution.
1058                 self.write_resolution(hir_id, result);
1059
1060                 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
1061             }
1062             QPath::LangItem(lang_item, span, id) => {
1063                 self.resolve_lang_item_path(lang_item, span, hir_id, id)
1064             }
1065         }
1066     }
1067
1068     /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
1069     /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
1070     /// reference a type argument. The reason to walk also the checked type is that the coerced type
1071     /// can be not easily comparable with predicate type (because of coercion). If the types match
1072     /// for either checked or coerced type, and there's only *one* argument that does, we point at
1073     /// the corresponding argument's expression span instead of the `fn` call path span.
1074     fn point_at_arg_instead_of_call_if_possible(
1075         &self,
1076         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1077         final_arg_types: &[Option<(Ty<'tcx>, Ty<'tcx>)>],
1078         expr: &'tcx hir::Expr<'tcx>,
1079         call_sp: Span,
1080         args: &'tcx [hir::Expr<'tcx>],
1081     ) {
1082         // We *do not* do this for desugared call spans to keep good diagnostics when involving
1083         // the `?` operator.
1084         if call_sp.desugaring_kind().is_some() {
1085             return;
1086         }
1087
1088         for error in errors {
1089             // Only if the cause is somewhere inside the expression we want try to point at arg.
1090             // Otherwise, it means that the cause is somewhere else and we should not change
1091             // anything because we can break the correct span.
1092             if !call_sp.contains(error.obligation.cause.span) {
1093                 continue;
1094             }
1095
1096             // Peel derived obligation, because it's the type that originally
1097             // started this inference chain that matters, not the one we wound
1098             // up with at the end.
1099             fn unpeel_to_top(
1100                 mut code: Lrc<ObligationCauseCode<'_>>,
1101             ) -> Lrc<ObligationCauseCode<'_>> {
1102                 let mut result_code = code.clone();
1103                 loop {
1104                     let parent = match &*code {
1105                         ObligationCauseCode::ImplDerivedObligation(c) => {
1106                             c.derived.parent_code.clone()
1107                         }
1108                         ObligationCauseCode::BuiltinDerivedObligation(c)
1109                         | ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(),
1110                         _ => break,
1111                     };
1112                     result_code = std::mem::replace(&mut code, parent);
1113                 }
1114                 result_code
1115             }
1116             let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) {
1117                 ObligationCauseCode::BuiltinDerivedObligation(code) |
1118                 ObligationCauseCode::DerivedObligation(code) => {
1119                     code.parent_trait_pred.self_ty().skip_binder().into()
1120                 }
1121                 ObligationCauseCode::ImplDerivedObligation(code) => {
1122                     code.derived.parent_trait_pred.self_ty().skip_binder().into()
1123                 }
1124                 _ if let ty::PredicateKind::Trait(predicate) =
1125                     error.obligation.predicate.kind().skip_binder() => {
1126                         predicate.self_ty().into()
1127                     }
1128                 _ =>  continue,
1129             };
1130             let self_ = self.resolve_vars_if_possible(self_);
1131
1132             // Collect the argument position for all arguments that could have caused this
1133             // `FulfillmentError`.
1134             let mut referenced_in = final_arg_types
1135                 .iter()
1136                 .enumerate()
1137                 .filter_map(|(i, arg)| match arg {
1138                     Some((checked_ty, coerce_ty)) => Some([(i, *checked_ty), (i, *coerce_ty)]),
1139                     _ => None,
1140                 })
1141                 .flatten()
1142                 .flat_map(|(i, ty)| {
1143                     let ty = self.resolve_vars_if_possible(ty);
1144                     // We walk the argument type because the argument's type could have
1145                     // been `Option<T>`, but the `FulfillmentError` references `T`.
1146                     if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
1147                 })
1148                 .collect::<Vec<usize>>();
1149
1150             // Both checked and coerced types could have matched, thus we need to remove
1151             // duplicates.
1152
1153             // We sort primitive type usize here and can use unstable sort
1154             referenced_in.sort_unstable();
1155             referenced_in.dedup();
1156
1157             if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
1158                 // Do not point at the inside of a macro.
1159                 // That would often result in poor error messages.
1160                 if args[ref_in].span.from_expansion() {
1161                     return;
1162                 }
1163                 // We make sure that only *one* argument matches the obligation failure
1164                 // and we assign the obligation's span to its expression's.
1165                 error.obligation.cause.span = args[ref_in].span;
1166                 let parent_code = error.obligation.cause.clone_code();
1167                 *error.obligation.cause.make_mut_code() =
1168                     ObligationCauseCode::FunctionArgumentObligation {
1169                         arg_hir_id: args[ref_in].hir_id,
1170                         call_hir_id: expr.hir_id,
1171                         parent_code,
1172                     };
1173             } else if error.obligation.cause.span == call_sp {
1174                 // Make function calls point at the callee, not the whole thing.
1175                 if let hir::ExprKind::Call(callee, _) = expr.kind {
1176                     error.obligation.cause.span = callee.span;
1177                 }
1178             }
1179         }
1180     }
1181
1182     /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
1183     /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
1184     /// were caused by them. If they were, we point at the corresponding type argument's span
1185     /// instead of the `fn` call path span.
1186     fn point_at_type_arg_instead_of_call_if_possible(
1187         &self,
1188         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
1189         call_expr: &'tcx hir::Expr<'tcx>,
1190     ) {
1191         if let hir::ExprKind::Call(path, _) = &call_expr.kind {
1192             if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
1193                 for error in errors {
1194                     if let ty::PredicateKind::Trait(predicate) =
1195                         error.obligation.predicate.kind().skip_binder()
1196                     {
1197                         // If any of the type arguments in this path segment caused the
1198                         // `FulfillmentError`, point at its span (#61860).
1199                         for arg in path
1200                             .segments
1201                             .iter()
1202                             .filter_map(|seg| seg.args.as_ref())
1203                             .flat_map(|a| a.args.iter())
1204                         {
1205                             if let hir::GenericArg::Type(hir_ty) = &arg {
1206                                 if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
1207                                     &hir_ty.kind
1208                                 {
1209                                     // Avoid ICE with associated types. As this is best
1210                                     // effort only, it's ok to ignore the case. It
1211                                     // would trigger in `is_send::<T::AssocType>();`
1212                                     // from `typeck-default-trait-impl-assoc-type.rs`.
1213                                 } else {
1214                                     let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
1215                                     let ty = self.resolve_vars_if_possible(ty);
1216                                     if ty == predicate.self_ty() {
1217                                         error.obligation.cause.span = hir_ty.span;
1218                                     }
1219                                 }
1220                             }
1221                         }
1222                     }
1223                 }
1224             }
1225         }
1226     }
1227 }