]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
db1acb599271696008ec0143c1f68a587ddf173f
[rust.git] / compiler / rustc_hir_typeck / src / fn_ctxt / adjust_fulfillment_errors.rs
1 use crate::FnCtxt;
2 use rustc_hir as hir;
3 use rustc_hir::def::Res;
4 use rustc_hir::def_id::DefId;
5 use rustc_infer::traits::ObligationCauseCode;
6 use rustc_middle::ty::{self, DefIdTree, Ty, TypeSuperVisitable, TypeVisitable, TypeVisitor};
7 use rustc_span::{self, Span};
8 use rustc_trait_selection::traits;
9
10 use std::ops::ControlFlow;
11
12 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13     pub fn adjust_fulfillment_error_for_expr_obligation(
14         &self,
15         error: &mut traits::FulfillmentError<'tcx>,
16     ) -> bool {
17         let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
18             = *error.obligation.cause.code().peel_derives() else { return false; };
19         let hir = self.tcx.hir();
20         let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
21
22         let Some(unsubstituted_pred) =
23             self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
24             else { return false; };
25
26         let generics = self.tcx.generics_of(def_id);
27         let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
28             ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs,
29             ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs,
30             _ => ty::List::empty(),
31         };
32
33         let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
34             predicate_substs.types().find_map(|ty| {
35                 ty.walk().find_map(|arg| {
36                     if let ty::GenericArgKind::Type(ty) = arg.unpack()
37                         && let ty::Param(param_ty) = ty.kind()
38                         && matches(param_ty)
39                     {
40                         Some(arg)
41                     } else {
42                         None
43                     }
44                 })
45             })
46         };
47
48         // Prefer generics that are local to the fn item, since these are likely
49         // to be the cause of the unsatisfied predicate.
50         let mut param_to_point_at = find_param_matching(&|param_ty| {
51             self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
52         });
53         // Fall back to generic that isn't local to the fn item. This will come
54         // from a trait or impl, for example.
55         let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
56             self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
57                 && param_ty.name != rustc_span::symbol::kw::SelfUpper
58         });
59         // Finally, the `Self` parameter is possibly the reason that the predicate
60         // is unsatisfied. This is less likely to be true for methods, because
61         // method probe means that we already kinda check that the predicates due
62         // to the `Self` type are true.
63         let mut self_param_to_point_at =
64             find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
65
66         // Finally, for ambiguity-related errors, we actually want to look
67         // for a parameter that is the source of the inference type left
68         // over in this predicate.
69         if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
70             fallback_param_to_point_at = None;
71             self_param_to_point_at = None;
72             param_to_point_at =
73                 self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
74         }
75
76         if self.closure_span_overlaps_error(error, expr.span) {
77             return false;
78         }
79
80         match &expr.kind {
81             hir::ExprKind::Path(qpath) => {
82                 if let hir::Node::Expr(hir::Expr {
83                     kind: hir::ExprKind::Call(callee, args),
84                     hir_id: call_hir_id,
85                     span: call_span,
86                     ..
87                 }) = hir.get_parent(expr.hir_id)
88                     && callee.hir_id == expr.hir_id
89                 {
90                     if self.closure_span_overlaps_error(error, *call_span) {
91                         return false;
92                     }
93
94                     for param in
95                         [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
96                         .into_iter()
97                         .flatten()
98                     {
99                         if self.blame_specific_arg_if_possible(
100                                 error,
101                                 def_id,
102                                 param,
103                                 *call_hir_id,
104                                 callee.span,
105                                 None,
106                                 args,
107                             )
108                         {
109                             return true;
110                         }
111                     }
112                 }
113                 // Notably, we only point to params that are local to the
114                 // item we're checking, since those are the ones we are able
115                 // to look in the final `hir::PathSegment` for. Everything else
116                 // would require a deeper search into the `qpath` than I think
117                 // is worthwhile.
118                 if let Some(param_to_point_at) = param_to_point_at
119                     && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
120                 {
121                     return true;
122                 }
123             }
124             hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
125                 for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
126                     .into_iter()
127                     .flatten()
128                 {
129                     if self.blame_specific_arg_if_possible(
130                         error,
131                         def_id,
132                         param,
133                         hir_id,
134                         segment.ident.span,
135                         Some(receiver),
136                         args,
137                     ) {
138                         return true;
139                     }
140                 }
141                 if let Some(param_to_point_at) = param_to_point_at
142                     && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
143                 {
144                     return true;
145                 }
146             }
147             hir::ExprKind::Struct(qpath, fields, ..) => {
148                 if let Res::Def(
149                     hir::def::DefKind::Struct | hir::def::DefKind::Variant,
150                     variant_def_id,
151                 ) = self.typeck_results.borrow().qpath_res(qpath, hir_id)
152                 {
153                     for param in
154                         [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
155                     {
156                         if let Some(param) = param {
157                             let refined_expr = self.point_at_field_if_possible(
158                                 def_id,
159                                 param,
160                                 variant_def_id,
161                                 fields,
162                             );
163
164                             match refined_expr {
165                                 None => {}
166                                 Some((refined_expr, _)) => {
167                                     error.obligation.cause.span = refined_expr
168                                         .span
169                                         .find_ancestor_in_same_ctxt(error.obligation.cause.span)
170                                         .unwrap_or(refined_expr.span);
171                                     return true;
172                                 }
173                             }
174                         }
175                     }
176                 }
177                 if let Some(param_to_point_at) = param_to_point_at
178                     && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
179                 {
180                     return true;
181                 }
182             }
183             _ => {}
184         }
185
186         false
187     }
188
189     fn point_at_path_if_possible(
190         &self,
191         error: &mut traits::FulfillmentError<'tcx>,
192         def_id: DefId,
193         param: ty::GenericArg<'tcx>,
194         qpath: &hir::QPath<'tcx>,
195     ) -> bool {
196         match qpath {
197             hir::QPath::Resolved(_, path) => {
198                 if let Some(segment) = path.segments.last()
199                     && self.point_at_generic_if_possible(error, def_id, param, segment)
200                 {
201                     return true;
202                 }
203             }
204             hir::QPath::TypeRelative(_, segment) => {
205                 if self.point_at_generic_if_possible(error, def_id, param, segment) {
206                     return true;
207                 }
208             }
209             _ => {}
210         }
211
212         false
213     }
214
215     fn point_at_generic_if_possible(
216         &self,
217         error: &mut traits::FulfillmentError<'tcx>,
218         def_id: DefId,
219         param_to_point_at: ty::GenericArg<'tcx>,
220         segment: &hir::PathSegment<'tcx>,
221     ) -> bool {
222         let own_substs = self
223             .tcx
224             .generics_of(def_id)
225             .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
226         let Some((index, _)) = own_substs
227             .iter()
228             .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
229             .enumerate()
230             .find(|(_, arg)| **arg == param_to_point_at) else { return false };
231         let Some(arg) = segment
232             .args()
233             .args
234             .iter()
235             .filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
236             .nth(index) else { return false; };
237         error.obligation.cause.span = arg
238             .span()
239             .find_ancestor_in_same_ctxt(error.obligation.cause.span)
240             .unwrap_or(arg.span());
241         true
242     }
243
244     fn find_ambiguous_parameter_in<T: TypeVisitable<'tcx>>(
245         &self,
246         item_def_id: DefId,
247         t: T,
248     ) -> Option<ty::GenericArg<'tcx>> {
249         struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
250         impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> {
251             type BreakTy = ty::GenericArg<'tcx>;
252             fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
253                 if let Some(origin) = self.0.type_var_origin(ty)
254                     && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
255                         origin.kind
256                     && let generics = self.0.tcx.generics_of(self.1)
257                     && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
258                     && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
259                         .get(index as usize)
260                 {
261                     ControlFlow::Break(*subst)
262                 } else {
263                     ty.super_visit_with(self)
264                 }
265             }
266         }
267         t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
268     }
269
270     fn closure_span_overlaps_error(
271         &self,
272         error: &traits::FulfillmentError<'tcx>,
273         span: Span,
274     ) -> bool {
275         if let traits::FulfillmentErrorCode::CodeSelectionError(
276             traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
277         ) = error.code
278             && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
279             && span.overlaps(self.tcx.def_span(*def_id))
280         {
281             true
282         } else {
283             false
284         }
285     }
286
287     fn point_at_field_if_possible(
288         &self,
289         def_id: DefId,
290         param_to_point_at: ty::GenericArg<'tcx>,
291         variant_def_id: DefId,
292         expr_fields: &[hir::ExprField<'tcx>],
293     ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
294         let def = self.tcx.adt_def(def_id);
295
296         let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
297         let fields_referencing_param: Vec<_> = def
298             .variant_with_id(variant_def_id)
299             .fields
300             .iter()
301             .filter(|field| {
302                 let field_ty = field.ty(self.tcx, identity_substs);
303                 Self::find_param_in_ty(field_ty.into(), param_to_point_at)
304             })
305             .collect();
306
307         if let [field] = fields_referencing_param.as_slice() {
308             for expr_field in expr_fields {
309                 // Look for the ExprField that matches the field, using the
310                 // same rules that check_expr_struct uses for macro hygiene.
311                 if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
312                 {
313                     return Some((expr_field.expr, self.tcx.type_of(field.did)));
314                 }
315             }
316         }
317
318         None
319     }
320
321     /// - `blame_specific_*` means that the function will recursively traverse the expression,
322     /// looking for the most-specific-possible span to blame.
323     ///
324     /// - `point_at_*` means that the function will only go "one level", pointing at the specific
325     /// expression mentioned.
326     ///
327     /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
328     /// the provided function call expression, and mark it as responsible for the fullfillment
329     /// error.
330     fn blame_specific_arg_if_possible(
331         &self,
332         error: &mut traits::FulfillmentError<'tcx>,
333         def_id: DefId,
334         param_to_point_at: ty::GenericArg<'tcx>,
335         call_hir_id: hir::HirId,
336         callee_span: Span,
337         receiver: Option<&'tcx hir::Expr<'tcx>>,
338         args: &'tcx [hir::Expr<'tcx>],
339     ) -> bool {
340         let ty = self.tcx.type_of(def_id);
341         if !ty.is_fn() {
342             return false;
343         }
344         let sig = ty.fn_sig(self.tcx).skip_binder();
345         let args_referencing_param: Vec<_> = sig
346             .inputs()
347             .iter()
348             .enumerate()
349             .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at))
350             .collect();
351         // If there's one field that references the given generic, great!
352         if let [(idx, _)] = args_referencing_param.as_slice()
353             && let Some(arg) = receiver
354                 .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
355
356             error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
357
358             if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) {
359                 // This is more specific than pointing at the entire argument.
360                 self.blame_specific_expr_if_possible(error, arg_expr)
361             }
362
363             error.obligation.cause.map_code(|parent_code| {
364                 ObligationCauseCode::FunctionArgumentObligation {
365                     arg_hir_id: arg.hir_id,
366                     call_hir_id,
367                     parent_code,
368                 }
369             });
370             return true;
371         } else if args_referencing_param.len() > 0 {
372             // If more than one argument applies, then point to the callee span at least...
373             // We have chance to fix this up further in `point_at_generics_if_possible`
374             error.obligation.cause.span = callee_span;
375         }
376
377         false
378     }
379
380     /**
381      * Recursively searches for the most-specific blamable expression.
382      * For example, if you have a chain of constraints like:
383      * - want `Vec<i32>: Copy`
384      * - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
385      * - because `(Option<Vec<i32>, bool)` needs `Option<Vec<i32>>: Copy` because `impl <A: Copy, B: Copy> Copy for (A, B)`
386      * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible`
387      * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint.
388      *
389      * This function only updates the error span.
390      */
391     pub fn blame_specific_expr_if_possible(
392         &self,
393         error: &mut traits::FulfillmentError<'tcx>,
394         expr: &'tcx hir::Expr<'tcx>,
395     ) {
396         // Whether it succeeded or failed, it likely made some amount of progress.
397         // In the very worst case, it's just the same `expr` we originally passed in.
398         let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
399             &error.obligation.cause.code(),
400             expr,
401         ) {
402             Ok(expr) => expr,
403             Err(expr) => expr,
404         };
405
406         // Either way, use this expression to update the error span.
407         // If it doesn't overlap the existing span at all, use the original span.
408         // FIXME: It would possibly be better to do this more continuously, at each level...
409         error.obligation.cause.span = expr
410             .span
411             .find_ancestor_in_same_ctxt(error.obligation.cause.span)
412             .unwrap_or(error.obligation.cause.span);
413     }
414
415     fn blame_specific_expr_if_possible_for_obligation_cause_code(
416         &self,
417         obligation_cause_code: &traits::ObligationCauseCode<'tcx>,
418         expr: &'tcx hir::Expr<'tcx>,
419     ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
420         match obligation_cause_code {
421             traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => {
422                 // This is the "root"; we assume that the `expr` is already pointing here.
423                 // Therefore, we return `Ok` so that this `expr` can be refined further.
424                 Ok(expr)
425             }
426             traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
427                 .blame_specific_expr_if_possible_for_derived_predicate_obligation(
428                     impl_derived,
429                     expr,
430                 ),
431             _ => {
432                 // We don't recognize this kind of constraint, so we cannot refine the expression
433                 // any further.
434                 Err(expr)
435             }
436         }
437     }
438
439     /// We want to achieve the error span in the following example:
440     ///
441     /// ```ignore (just for demonstration)
442     /// struct Burrito<Filling> {
443     ///   filling: Filling,
444     /// }
445     /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
446     /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
447     ///
448     /// fn will_type_error() {
449     ///   eat_delicious_food(Burrito { filling: Kale });
450     /// } //                                    ^--- The trait bound `Kale: Delicious`
451     ///   //                                         is not satisfied
452     /// ```
453     ///
454     /// Without calling this function, the error span will cover the entire argument expression.
455     ///
456     /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
457     /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
458     ///
459     /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
460     /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
461     /// only a partial success - but it cannot be refined even further.
462     fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
463         &self,
464         obligation: &traits::ImplDerivedObligationCause<'tcx>,
465         expr: &'tcx hir::Expr<'tcx>,
466     ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
467         // First, we attempt to refine the `expr` for our span using the parent obligation.
468         // If this cannot be done, then we are already stuck, so we stop early (hence the use
469         // of the `?` try operator here).
470         let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code(
471             &*obligation.derived.parent_code,
472             expr,
473         )?;
474
475         // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
476         // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
477         // that struct type.
478         let impl_trait_self_ref: Option<ty::TraitRef<'tcx>> =
479             self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder());
480
481         let Some(impl_trait_self_ref) = impl_trait_self_ref else {
482             // It is possible that this is absent. In this case, we make no progress.
483             return Err(expr);
484         };
485
486         // We only really care about the `Self` type itself, which we extract from the ref.
487         let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
488
489         let impl_predicates: ty::GenericPredicates<'tcx> =
490             self.tcx.predicates_of(obligation.impl_def_id);
491         let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
492             // We don't have the index, so we can only guess.
493             return Err(expr);
494         };
495
496         if impl_predicate_index >= impl_predicates.predicates.len() {
497             // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
498             return Err(expr);
499         }
500         let relevant_broken_predicate: ty::PredicateKind<'tcx> =
501             impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
502
503         match relevant_broken_predicate {
504             ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
505                 // ...
506                 self.blame_specific_part_of_expr_corresponding_to_generic_param(
507                     broken_trait.trait_ref.self_ty().into(),
508                     expr,
509                     impl_self_ty.into(),
510                 )
511             }
512             _ => Err(expr),
513         }
514     }
515
516     /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`.
517     /// For example, given
518     /// - expr: `(Some(vec![1, 2, 3]), false)`
519     /// - param: `T`
520     /// - in_ty: `(Option<Vec<T>, bool)`
521     /// we would drill until we arrive at `vec![1, 2, 3]`.
522     ///
523     /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`),
524     /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
525     /// `foo()` and then return `Err("foo()")`.
526     ///
527     /// This means that you can (and should) use the `?` try operator to chain multiple calls to this
528     /// function with different types, since you can only continue drilling the second time if you
529     /// succeeded the first time.
530     fn blame_specific_part_of_expr_corresponding_to_generic_param(
531         &self,
532         param: ty::GenericArg<'tcx>,
533         expr: &'tcx hir::Expr<'tcx>,
534         in_ty: ty::GenericArg<'tcx>,
535     ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
536         if param == in_ty {
537             // The types match exactly, so we have drilled as far as we can.
538             return Ok(expr);
539         }
540
541         let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
542             return Err(expr);
543         };
544
545         if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
546             (&expr.kind, in_ty.kind())
547         {
548             if in_ty_elements.len() != expr_elements.len() {
549                 return Err(expr);
550             }
551             // Find out which of `in_ty_elements` refer to `param`.
552             // FIXME: It may be better to take the first if there are multiple,
553             // just so that the error points to a smaller expression.
554             let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
555                 Self::find_param_in_ty((*in_ty_elem).into(), param)
556             })) else {
557                 // The param is not mentioned, or it is mentioned in multiple indexes.
558                 return Err(expr);
559             };
560
561             return self.blame_specific_part_of_expr_corresponding_to_generic_param(
562                 param,
563                 drill_expr,
564                 drill_ty.into(),
565             );
566         }
567
568         if let (
569             hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest),
570             ty::Adt(in_ty_adt, in_ty_adt_generic_args),
571         ) = (&expr.kind, in_ty.kind())
572         {
573             // First, confirm that this struct is the same one as in the types, and if so,
574             // find the right variant.
575             let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else {
576                 return Err(expr);
577             };
578
579             let variant_def_id = match expr_struct_def_kind {
580                 hir::def::DefKind::Struct => {
581                     if in_ty_adt.did() != expr_struct_def_id {
582                         // FIXME: Deal with type aliases?
583                         return Err(expr);
584                     }
585                     expr_struct_def_id
586                 }
587                 hir::def::DefKind::Variant => {
588                     // If this is a variant, its parent is the type definition.
589                     if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
590                         // FIXME: Deal with type aliases?
591                         return Err(expr);
592                     }
593                     expr_struct_def_id
594                 }
595                 _ => {
596                     return Err(expr);
597                 }
598             };
599
600             // We need to know which of the generic parameters mentions our target param.
601             // We expect that at least one of them does, since it is expected to be mentioned.
602             let Some((drill_generic_index, generic_argument_type)) =
603                 Self::is_iterator_singleton(
604                     in_ty_adt_generic_args.iter().enumerate().filter(
605                         |(_index, in_ty_generic)| {
606                             Self::find_param_in_ty(*in_ty_generic, param)
607                         },
608                     ),
609                 ) else {
610                     return Err(expr);
611                 };
612
613             let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
614             if drill_generic_index >= struct_generic_parameters.params.len() {
615                 return Err(expr);
616             }
617
618             let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
619                 struct_generic_parameters.param_at(drill_generic_index, self.tcx),
620             );
621
622             // We make 3 steps:
623             // Suppose we have a type like
624             // ```ignore (just for demonstration)
625             // struct ExampleStruct<T> {
626             //   enabled: bool,
627             //   item: Option<(usize, T, bool)>,
628             // }
629             //
630             // f(ExampleStruct {
631             //   enabled: false,
632             //   item: Some((0, Box::new(String::new()), 1) }, true)),
633             // });
634             // ```
635             // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
636             // for `String: Copy`, which isn't true here.
637             //
638             // (1) First, we drill into `.item` and highlight that expression
639             // (2) Then we use the template type `Option<(usize, T, bool)>` to
640             //     drill into the `T`, arriving at a `Box<String>` expression.
641             // (3) Then we keep going, drilling into this expression using our
642             //     outer contextual information.
643
644             // (1) Find the (unique) field which mentions the type in our constraint:
645             let (field_expr, field_type) = self
646                 .point_at_field_if_possible(
647                     in_ty_adt.did(),
648                     param_to_point_at_in_struct,
649                     variant_def_id,
650                     expr_struct_fields,
651                 )
652                 .ok_or(expr)?;
653
654             // (2) Continue drilling into the struct, ignoring the struct's
655             // generic argument types.
656             let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
657                 param_to_point_at_in_struct,
658                 field_expr,
659                 field_type.into(),
660             )?;
661
662             // (3) Continue drilling into the expression, having "passed
663             // through" the struct entirely.
664             return self.blame_specific_part_of_expr_corresponding_to_generic_param(
665                 param,
666                 expr,
667                 generic_argument_type,
668             );
669         }
670
671         if let (
672             hir::ExprKind::Call(expr_callee, expr_args),
673             ty::Adt(in_ty_adt, in_ty_adt_generic_args),
674         ) = (&expr.kind, in_ty.kind())
675         {
676             let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else {
677                 // FIXME: This case overlaps with another one worth handling,
678                 // which should happen above since it applies to non-ADTs:
679                 // we can drill down into regular generic functions.
680                 return Err(expr);
681             };
682             // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
683
684             let Res::Def(expr_struct_def_kind, expr_ctor_def_id) = self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id) else {
685                 return Err(expr);
686             };
687
688             let variant_def_id = match expr_struct_def_kind {
689                 hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
690                     if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
691                         // FIXME: Deal with type aliases?
692                         return Err(expr);
693                     }
694                     self.tcx.parent(expr_ctor_def_id)
695                 }
696                 hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
697                     // If this is a variant, its parent is the type definition.
698                     if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
699                         // FIXME: Deal with type aliases?
700                         return Err(expr);
701                     }
702                     expr_ctor_def_id
703                 }
704                 _ => {
705                     return Err(expr);
706                 }
707             };
708
709             // We need to know which of the generic parameters mentions our target param.
710             // We expect that at least one of them does, since it is expected to be mentioned.
711             let Some((drill_generic_index, generic_argument_type)) =
712                 Self::is_iterator_singleton(
713                     in_ty_adt_generic_args.iter().enumerate().filter(
714                         |(_index, in_ty_generic)| {
715                             Self::find_param_in_ty(*in_ty_generic, param)
716                         },
717                     ),
718                 ) else {
719                     return Err(expr);
720                 };
721
722             let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
723             if drill_generic_index >= struct_generic_parameters.params.len() {
724                 return Err(expr);
725             }
726
727             let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
728                 struct_generic_parameters.param_at(drill_generic_index, self.tcx),
729             );
730
731             // We make 3 steps:
732             // Suppose we have a type like
733             // ```ignore (just for demonstration)
734             // struct ExampleStruct<T> {
735             //   enabled: bool,
736             //   item: Option<(usize, T, bool)>,
737             // }
738             //
739             // f(ExampleStruct {
740             //   enabled: false,
741             //   item: Some((0, Box::new(String::new()), 1) }, true)),
742             // });
743             // ```
744             // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
745             // for `String: Copy`, which isn't true here.
746             //
747             // (1) First, we drill into `.item` and highlight that expression
748             // (2) Then we use the template type `Option<(usize, T, bool)>` to
749             //     drill into the `T`, arriving at a `Box<String>` expression.
750             // (3) Then we keep going, drilling into this expression using our
751             //     outer contextual information.
752
753             // (1) Find the (unique) field index which mentions the type in our constraint:
754             let Some((field_index, field_type)) = Self::is_iterator_singleton(
755                 in_ty_adt
756                     .variant_with_id(variant_def_id)
757                     .fields
758                     .iter()
759                     .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
760                     .enumerate()
761                     .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param))
762             ) else {
763                 return Err(expr);
764             };
765
766             if field_index >= expr_args.len() {
767                 return Err(expr);
768             }
769
770             // (2) Continue drilling into the struct, ignoring the struct's
771             // generic argument types.
772             let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
773                 param_to_point_at_in_struct,
774                 &expr_args[field_index],
775                 field_type.into(),
776             )?;
777
778             // (3) Continue drilling into the expression, having "passed
779             // through" the struct entirely.
780             return self.blame_specific_part_of_expr_corresponding_to_generic_param(
781                 param,
782                 expr,
783                 generic_argument_type,
784             );
785         }
786
787         // At this point, none of the basic patterns matched.
788         // One major possibility which remains is that we have a function call.
789         // In this case, it's often possible to dive deeper into the call to find something to blame,
790         // but this is not always possible.
791
792         Err(expr)
793     }
794
795     // FIXME: This can be made into a private, non-impl function later.
796     /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
797     /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
798     pub fn find_param_in_ty(
799         ty: ty::GenericArg<'tcx>,
800         param_to_point_at: ty::GenericArg<'tcx>,
801     ) -> bool {
802         let mut walk = ty.walk();
803         while let Some(arg) = walk.next() {
804             if arg == param_to_point_at {
805             return true;
806         } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
807             && let ty::Alias(ty::Projection, ..) = ty.kind()
808         {
809             // This logic may seem a bit strange, but typically when
810             // we have a projection type in a function signature, the
811             // argument that's being passed into that signature is
812             // not actually constraining that projection's substs in
813             // a meaningful way. So we skip it, and see improvements
814             // in some UI tests.
815             walk.skip_current_subtree();
816         }
817         }
818         false
819     }
820
821     // FIXME: This can be made into a private, non-impl function later.
822     /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
823     pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
824         match (iterator.next(), iterator.next()) {
825             (_, Some(_)) => None,
826             (first, _) => first,
827         }
828     }
829 }