rustc_hir_typeck/fn_ctxt/
adjust_fulfillment_errors.rs

1use std::ops::ControlFlow;
2
3use rustc_hir as hir;
4use rustc_hir::def::{DefKind, Res};
5use rustc_hir::def_id::DefId;
6use rustc_infer::traits::ObligationCauseCode;
7use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
8use rustc_span::{Span, kw};
9use rustc_trait_selection::traits;
10
11use crate::FnCtxt;
12
13enum ClauseFlavor {
14    /// Predicate comes from `predicates_of`.
15    Where,
16    /// Predicate comes from `const_conditions`.
17    Const,
18}
19
20impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21    pub(crate) fn adjust_fulfillment_error_for_expr_obligation(
22        &self,
23        error: &mut traits::FulfillmentError<'tcx>,
24    ) -> bool {
25        let (def_id, hir_id, idx, flavor) = match *error.obligation.cause.code().peel_derives() {
26            ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) => {
27                (def_id, hir_id, idx, ClauseFlavor::Where)
28            }
29            ObligationCauseCode::HostEffectInExpr(def_id, _, hir_id, idx) => {
30                (def_id, hir_id, idx, ClauseFlavor::Const)
31            }
32            _ => return false,
33        };
34
35        let uninstantiated_pred = match flavor {
36            ClauseFlavor::Where => {
37                if let Some(pred) = self
38                    .tcx
39                    .predicates_of(def_id)
40                    .instantiate_identity(self.tcx)
41                    .predicates
42                    .into_iter()
43                    .nth(idx)
44                {
45                    pred
46                } else {
47                    return false;
48                }
49            }
50            ClauseFlavor::Const => {
51                if let Some((pred, _)) = self
52                    .tcx
53                    .const_conditions(def_id)
54                    .instantiate_identity(self.tcx)
55                    .into_iter()
56                    .nth(idx)
57                {
58                    pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe)
59                } else {
60                    return false;
61                }
62            }
63        };
64
65        let generics = self.tcx.generics_of(def_id);
66        let (predicate_args, predicate_self_type_to_point_at) =
67            match uninstantiated_pred.kind().skip_binder() {
68                ty::ClauseKind::Trait(pred) => {
69                    (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into()))
70                }
71                ty::ClauseKind::HostEffect(pred) => {
72                    (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into()))
73                }
74                ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None),
75                ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None),
76                ty::ClauseKind::ConstEvaluatable(e) => (vec![e.into()], None),
77                _ => return false,
78            };
79
80        let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| {
81            predicate_args.iter().find_map(|arg| {
82                arg.walk().find_map(|arg| {
83                    if let ty::GenericArgKind::Type(ty) = arg.kind()
84                        && let ty::Param(param_ty) = *ty.kind()
85                        && matches(ty::ParamTerm::Ty(param_ty))
86                    {
87                        Some(arg)
88                    } else if let ty::GenericArgKind::Const(ct) = arg.kind()
89                        && let ty::ConstKind::Param(param_ct) = ct.kind()
90                        && matches(ty::ParamTerm::Const(param_ct))
91                    {
92                        Some(arg)
93                    } else {
94                        None
95                    }
96                })
97            })
98        };
99
100        // Prefer generics that are local to the fn item, since these are likely
101        // to be the cause of the unsatisfied predicate.
102        let mut param_to_point_at = find_param_matching(&|param_term| {
103            self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) == def_id
104        });
105        // Fall back to generic that isn't local to the fn item. This will come
106        // from a trait or impl, for example.
107        let mut fallback_param_to_point_at = find_param_matching(&|param_term| {
108            self.tcx.parent(generics.param_at(param_term.index(), self.tcx).def_id) != def_id
109                && !matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper)
110        });
111        // Finally, the `Self` parameter is possibly the reason that the predicate
112        // is unsatisfied. This is less likely to be true for methods, because
113        // method probe means that we already kinda check that the predicates due
114        // to the `Self` type are true.
115        let mut self_param_to_point_at = find_param_matching(
116            &|param_term| matches!(param_term, ty::ParamTerm::Ty(ty) if ty.name == kw::SelfUpper),
117        );
118
119        // Finally, for ambiguity-related errors, we actually want to look
120        // for a parameter that is the source of the inference type left
121        // over in this predicate.
122        if let traits::FulfillmentErrorCode::Ambiguity { .. } = error.code {
123            fallback_param_to_point_at = None;
124            self_param_to_point_at = None;
125            param_to_point_at =
126                self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
127        }
128
129        match self.tcx.hir_node(hir_id) {
130            hir::Node::Expr(expr) => self.point_at_expr_if_possible(
131                error,
132                def_id,
133                expr,
134                predicate_self_type_to_point_at,
135                param_to_point_at,
136                fallback_param_to_point_at,
137                self_param_to_point_at,
138            ),
139
140            hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => {
141                for param in [
142                    predicate_self_type_to_point_at,
143                    param_to_point_at,
144                    fallback_param_to_point_at,
145                    self_param_to_point_at,
146                ]
147                .into_iter()
148                .flatten()
149                {
150                    if self.point_at_path_if_possible(error, def_id, param, &qpath) {
151                        return true;
152                    }
153                }
154
155                false
156            }
157
158            _ => false,
159        }
160    }
161
162    fn point_at_expr_if_possible(
163        &self,
164        error: &mut traits::FulfillmentError<'tcx>,
165        callee_def_id: DefId,
166        expr: &'tcx hir::Expr<'tcx>,
167        predicate_self_type_to_point_at: Option<ty::GenericArg<'tcx>>,
168        param_to_point_at: Option<ty::GenericArg<'tcx>>,
169        fallback_param_to_point_at: Option<ty::GenericArg<'tcx>>,
170        self_param_to_point_at: Option<ty::GenericArg<'tcx>>,
171    ) -> bool {
172        if self.closure_span_overlaps_error(error, expr.span) {
173            return false;
174        }
175
176        match expr.kind {
177            hir::ExprKind::Call(
178                hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. },
179                args,
180            ) => {
181                if let Some(param) = predicate_self_type_to_point_at
182                    && self.point_at_path_if_possible(error, callee_def_id, param, &qpath)
183                {
184                    return true;
185                }
186
187                for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
188                    .into_iter()
189                    .flatten()
190                {
191                    if self.blame_specific_arg_if_possible(
192                        error,
193                        callee_def_id,
194                        param,
195                        expr.hir_id,
196                        *callee_span,
197                        None,
198                        args,
199                    ) {
200                        return true;
201                    }
202                }
203
204                for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
205                    .into_iter()
206                    .flatten()
207                {
208                    if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) {
209                        return true;
210                    }
211                }
212            }
213            hir::ExprKind::Path(qpath) => {
214                // If the parent is an call, then process this as a call.
215                //
216                // This is because the `WhereClauseInExpr` obligations come from
217                // the well-formedness of the *path* expression, but we care to
218                // point at the call expression (namely, its args).
219                if let hir::Node::Expr(
220                    call_expr @ hir::Expr { kind: hir::ExprKind::Call(callee, ..), .. },
221                ) = self.tcx.parent_hir_node(expr.hir_id)
222                    && callee.hir_id == expr.hir_id
223                {
224                    return self.point_at_expr_if_possible(
225                        error,
226                        callee_def_id,
227                        call_expr,
228                        predicate_self_type_to_point_at,
229                        param_to_point_at,
230                        fallback_param_to_point_at,
231                        self_param_to_point_at,
232                    );
233                }
234
235                // Otherwise, just try to point at path components.
236
237                if let Some(param) = predicate_self_type_to_point_at
238                    && self.point_at_path_if_possible(error, callee_def_id, param, &qpath)
239                {
240                    return true;
241                }
242
243                for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
244                    .into_iter()
245                    .flatten()
246                {
247                    if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) {
248                        return true;
249                    }
250                }
251            }
252            hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
253                if let Some(param) = predicate_self_type_to_point_at
254                    && self.point_at_generic_if_possible(error, callee_def_id, param, segment)
255                {
256                    // HACK: This is not correct, since `predicate_self_type_to_point_at` might
257                    // not actually correspond to the receiver of the method call. But we
258                    // re-adjust the cause code here in order to prefer pointing at one of
259                    // the method's turbofish segments but still use `FunctionArgumentObligation`
260                    // elsewhere. Hopefully this doesn't break something.
261                    error.obligation.cause.map_code(|parent_code| {
262                        ObligationCauseCode::FunctionArg {
263                            arg_hir_id: receiver.hir_id,
264                            call_hir_id: expr.hir_id,
265                            parent_code,
266                        }
267                    });
268                    return true;
269                }
270
271                for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
272                    .into_iter()
273                    .flatten()
274                {
275                    if self.blame_specific_arg_if_possible(
276                        error,
277                        callee_def_id,
278                        param,
279                        expr.hir_id,
280                        segment.ident.span,
281                        Some(receiver),
282                        args,
283                    ) {
284                        return true;
285                    }
286                }
287                if let Some(param_to_point_at) = param_to_point_at
288                    && self.point_at_generic_if_possible(
289                        error,
290                        callee_def_id,
291                        param_to_point_at,
292                        segment,
293                    )
294                {
295                    return true;
296                }
297                // Handle `Self` param specifically, since it's separated in
298                // the method call representation
299                if self_param_to_point_at.is_some() {
300                    error.obligation.cause.span = receiver
301                        .span
302                        .find_ancestor_in_same_ctxt(error.obligation.cause.span)
303                        .unwrap_or(receiver.span);
304                    return true;
305                }
306            }
307            hir::ExprKind::Struct(qpath, fields, ..) => {
308                if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
309                    self.typeck_results.borrow().qpath_res(qpath, expr.hir_id)
310                {
311                    for param in
312                        [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
313                            .into_iter()
314                            .flatten()
315                    {
316                        let refined_expr = self.point_at_field_if_possible(
317                            callee_def_id,
318                            param,
319                            variant_def_id,
320                            fields,
321                        );
322
323                        match refined_expr {
324                            None => {}
325                            Some((refined_expr, _)) => {
326                                error.obligation.cause.span = refined_expr
327                                    .span
328                                    .find_ancestor_in_same_ctxt(error.obligation.cause.span)
329                                    .unwrap_or(refined_expr.span);
330                                return true;
331                            }
332                        }
333                    }
334                }
335
336                for param in [
337                    predicate_self_type_to_point_at,
338                    param_to_point_at,
339                    fallback_param_to_point_at,
340                    self_param_to_point_at,
341                ]
342                .into_iter()
343                .flatten()
344                {
345                    if self.point_at_path_if_possible(error, callee_def_id, param, qpath) {
346                        return true;
347                    }
348                }
349            }
350            _ => {}
351        }
352
353        false
354    }
355
356    fn point_at_path_if_possible(
357        &self,
358        error: &mut traits::FulfillmentError<'tcx>,
359        def_id: DefId,
360        arg: ty::GenericArg<'tcx>,
361        qpath: &hir::QPath<'tcx>,
362    ) -> bool {
363        match qpath {
364            hir::QPath::Resolved(self_ty, path) => {
365                for segment in path.segments.iter().rev() {
366                    if let Res::Def(kind, def_id) = segment.res
367                        && !matches!(kind, DefKind::Mod | DefKind::ForeignMod)
368                        && self.point_at_generic_if_possible(error, def_id, arg, segment)
369                    {
370                        return true;
371                    }
372                }
373                // Handle `Self` param specifically, since it's separated in
374                // the path representation
375                if let Some(self_ty) = self_ty
376                    && let ty::GenericArgKind::Type(ty) = arg.kind()
377                    && ty == self.tcx.types.self_param
378                {
379                    error.obligation.cause.span = self_ty
380                        .span
381                        .find_ancestor_in_same_ctxt(error.obligation.cause.span)
382                        .unwrap_or(self_ty.span);
383                    return true;
384                }
385            }
386            hir::QPath::TypeRelative(self_ty, segment) => {
387                if self.point_at_generic_if_possible(error, def_id, arg, segment) {
388                    return true;
389                }
390                // Handle `Self` param specifically, since it's separated in
391                // the path representation
392                if let ty::GenericArgKind::Type(ty) = arg.kind()
393                    && ty == self.tcx.types.self_param
394                {
395                    error.obligation.cause.span = self_ty
396                        .span
397                        .find_ancestor_in_same_ctxt(error.obligation.cause.span)
398                        .unwrap_or(self_ty.span);
399                    return true;
400                }
401            }
402            _ => {}
403        }
404
405        false
406    }
407
408    fn point_at_generic_if_possible(
409        &self,
410        error: &mut traits::FulfillmentError<'tcx>,
411        def_id: DefId,
412        param_to_point_at: ty::GenericArg<'tcx>,
413        segment: &hir::PathSegment<'tcx>,
414    ) -> bool {
415        let own_args = self
416            .tcx
417            .generics_of(def_id)
418            .own_args(ty::GenericArgs::identity_for_item(self.tcx, def_id));
419        let Some(mut index) = own_args.iter().position(|arg| *arg == param_to_point_at) else {
420            return false;
421        };
422        // SUBTLE: We may or may not turbofish lifetime arguments, which will
423        // otherwise be elided. if our "own args" starts with a lifetime, but
424        // the args list does not, then we should chop off all of the lifetimes,
425        // since they're all elided.
426        let segment_args = segment.args().args;
427        if matches!(own_args[0].kind(), ty::GenericArgKind::Lifetime(_))
428            && segment_args.first().is_some_and(|arg| arg.is_ty_or_const())
429            && let Some(offset) = own_args.iter().position(|arg| {
430                matches!(arg.kind(), ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_))
431            })
432            && let Some(new_index) = index.checked_sub(offset)
433        {
434            index = new_index;
435        }
436        let Some(arg) = segment_args.get(index) else {
437            return false;
438        };
439        error.obligation.cause.span = arg
440            .span()
441            .find_ancestor_in_same_ctxt(error.obligation.cause.span)
442            .unwrap_or(arg.span());
443        true
444    }
445
446    fn find_ambiguous_parameter_in<T: TypeVisitable<TyCtxt<'tcx>>>(
447        &self,
448        item_def_id: DefId,
449        t: T,
450    ) -> Option<ty::GenericArg<'tcx>> {
451        struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
452        impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> {
453            type Result = ControlFlow<ty::GenericArg<'tcx>>;
454            fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
455                if let ty::Infer(ty::TyVar(vid)) = *ty.kind()
456                    && let Some(def_id) = self.0.type_var_origin(vid).param_def_id
457                    && let generics = self.0.tcx.generics_of(self.1)
458                    && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
459                    && let Some(arg) =
460                        ty::GenericArgs::identity_for_item(self.0.tcx, self.1).get(index as usize)
461                {
462                    ControlFlow::Break(*arg)
463                } else {
464                    ty.super_visit_with(self)
465                }
466            }
467        }
468        t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
469    }
470
471    fn closure_span_overlaps_error(
472        &self,
473        error: &traits::FulfillmentError<'tcx>,
474        span: Span,
475    ) -> bool {
476        if let traits::FulfillmentErrorCode::Select(traits::SelectionError::SignatureMismatch(
477            box traits::SignatureMismatchData { expected_trait_ref, .. },
478        )) = error.code
479            && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) =
480                expected_trait_ref.self_ty().kind()
481            && span.overlaps(self.tcx.def_span(*def_id))
482        {
483            true
484        } else {
485            false
486        }
487    }
488
489    fn point_at_field_if_possible(
490        &self,
491        def_id: DefId,
492        param_to_point_at: ty::GenericArg<'tcx>,
493        variant_def_id: DefId,
494        expr_fields: &[hir::ExprField<'tcx>],
495    ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
496        let def = self.tcx.adt_def(def_id);
497
498        let identity_args = ty::GenericArgs::identity_for_item(self.tcx, def_id);
499        let fields_referencing_param: Vec<_> = def
500            .variant_with_id(variant_def_id)
501            .fields
502            .iter()
503            .filter(|field| {
504                let field_ty = field.ty(self.tcx, identity_args);
505                find_param_in_ty(field_ty.into(), param_to_point_at)
506            })
507            .collect();
508
509        if let [field] = fields_referencing_param.as_slice() {
510            for expr_field in expr_fields {
511                // Look for the ExprField that matches the field, using the
512                // same rules that check_expr_struct uses for macro hygiene.
513                if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
514                {
515                    return Some((
516                        expr_field.expr,
517                        self.tcx.type_of(field.did).instantiate_identity(),
518                    ));
519                }
520            }
521        }
522
523        None
524    }
525
526    /// - `blame_specific_*` means that the function will recursively traverse the expression,
527    /// looking for the most-specific-possible span to blame.
528    ///
529    /// - `point_at_*` means that the function will only go "one level", pointing at the specific
530    /// expression mentioned.
531    ///
532    /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
533    /// the provided function call expression, and mark it as responsible for the fulfillment
534    /// error.
535    fn blame_specific_arg_if_possible(
536        &self,
537        error: &mut traits::FulfillmentError<'tcx>,
538        def_id: DefId,
539        param_to_point_at: ty::GenericArg<'tcx>,
540        call_hir_id: hir::HirId,
541        callee_span: Span,
542        receiver: Option<&'tcx hir::Expr<'tcx>>,
543        args: &'tcx [hir::Expr<'tcx>],
544    ) -> bool {
545        let ty = self.tcx.type_of(def_id).instantiate_identity();
546        if !ty.is_fn() {
547            return false;
548        }
549        let sig = ty.fn_sig(self.tcx).skip_binder();
550        let args_referencing_param: Vec<_> = sig
551            .inputs()
552            .iter()
553            .enumerate()
554            .filter(|(_, ty)| find_param_in_ty((**ty).into(), param_to_point_at))
555            .collect();
556        // If there's one field that references the given generic, great!
557        if let [(idx, _)] = args_referencing_param.as_slice()
558            && let Some(arg) = receiver.map_or(args.get(*idx), |rcvr| {
559                if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }
560            })
561        {
562            error.obligation.cause.span = arg
563                .span
564                .find_ancestor_in_same_ctxt(error.obligation.cause.span)
565                .unwrap_or(arg.span);
566
567            if let hir::Node::Expr(arg_expr) = self.tcx.hir_node(arg.hir_id) {
568                // This is more specific than pointing at the entire argument.
569                self.blame_specific_expr_if_possible(error, arg_expr)
570            }
571
572            error.obligation.cause.map_code(|parent_code| ObligationCauseCode::FunctionArg {
573                arg_hir_id: arg.hir_id,
574                call_hir_id,
575                parent_code,
576            });
577            return true;
578        } else if args_referencing_param.len() > 0 {
579            // If more than one argument applies, then point to the callee span at least...
580            // We have chance to fix this up further in `point_at_generics_if_possible`
581            error.obligation.cause.span = callee_span;
582        }
583
584        false
585    }
586
587    /**
588     * Recursively searches for the most-specific blameable expression.
589     * For example, if you have a chain of constraints like:
590     * - want `Vec<i32>: Copy`
591     * - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
592     * - because `(Option<Vec<i32>, bool)` needs `Option<Vec<i32>>: Copy` because `impl <A: Copy, B: Copy> Copy for (A, B)`
593     * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible`
594     * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint.
595     *
596     * This function only updates the error span.
597     */
598    pub(crate) fn blame_specific_expr_if_possible(
599        &self,
600        error: &mut traits::FulfillmentError<'tcx>,
601        expr: &'tcx hir::Expr<'tcx>,
602    ) {
603        // Whether it succeeded or failed, it likely made some amount of progress.
604        // In the very worst case, it's just the same `expr` we originally passed in.
605        let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
606            error.obligation.cause.code(),
607            expr,
608        ) {
609            Ok(expr) => expr,
610            Err(expr) => expr,
611        };
612
613        // Either way, use this expression to update the error span.
614        // If it doesn't overlap the existing span at all, use the original span.
615        // FIXME: It would possibly be better to do this more continuously, at each level...
616        error.obligation.cause.span = expr
617            .span
618            .find_ancestor_in_same_ctxt(error.obligation.cause.span)
619            .unwrap_or(error.obligation.cause.span);
620    }
621
622    fn blame_specific_expr_if_possible_for_obligation_cause_code(
623        &self,
624        obligation_cause_code: &traits::ObligationCauseCode<'tcx>,
625        expr: &'tcx hir::Expr<'tcx>,
626    ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
627        match obligation_cause_code {
628            traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _)
629            | ObligationCauseCode::HostEffectInExpr(..) => {
630                // This is the "root"; we assume that the `expr` is already pointing here.
631                // Therefore, we return `Ok` so that this `expr` can be refined further.
632                Ok(expr)
633            }
634            traits::ObligationCauseCode::ImplDerived(impl_derived) => self
635                .blame_specific_expr_if_possible_for_derived_predicate_obligation(
636                    impl_derived,
637                    expr,
638                ),
639            _ => {
640                // We don't recognize this kind of constraint, so we cannot refine the expression
641                // any further.
642                Err(expr)
643            }
644        }
645    }
646
647    /// We want to achieve the error span in the following example:
648    ///
649    /// ```ignore (just for demonstration)
650    /// struct Burrito<Filling> {
651    ///   filling: Filling,
652    /// }
653    /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
654    /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
655    ///
656    /// fn will_type_error() {
657    ///   eat_delicious_food(Burrito { filling: Kale });
658    /// } //                                    ^--- The trait bound `Kale: Delicious`
659    ///   //                                         is not satisfied
660    /// ```
661    ///
662    /// Without calling this function, the error span will cover the entire argument expression.
663    ///
664    /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
665    /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
666    ///
667    /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
668    /// reported as an error. If it is `Ok`, then it means it refined successful. If it is `Err`, then it may be
669    /// only a partial success - but it cannot be refined even further.
670    fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
671        &self,
672        obligation: &traits::ImplDerivedCause<'tcx>,
673        expr: &'tcx hir::Expr<'tcx>,
674    ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
675        // First, we attempt to refine the `expr` for our span using the parent obligation.
676        // If this cannot be done, then we are already stuck, so we stop early (hence the use
677        // of the `?` try operator here).
678        let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code(
679            &*obligation.derived.parent_code,
680            expr,
681        )?;
682
683        // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
684        // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
685        // that struct type.
686        let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) {
687            ty::TraitRef::new_from_args(
688                self.tcx,
689                obligation.impl_or_alias_def_id,
690                ty::GenericArgs::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
691            )
692        } else {
693            self.tcx
694                .impl_trait_ref(obligation.impl_or_alias_def_id)
695                .map(|impl_def| impl_def.skip_binder())
696                // It is possible that this is absent. In this case, we make no progress.
697                .ok_or(expr)?
698        };
699
700        // We only really care about the `Self` type itself, which we extract from the ref.
701        let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
702
703        let impl_predicates: ty::GenericPredicates<'tcx> =
704            self.tcx.predicates_of(obligation.impl_or_alias_def_id);
705        let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
706            // We don't have the index, so we can only guess.
707            return Err(expr);
708        };
709
710        if impl_predicate_index >= impl_predicates.predicates.len() {
711            // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
712            return Err(expr);
713        }
714
715        match impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder() {
716            ty::ClauseKind::Trait(broken_trait) => {
717                // ...
718                self.blame_specific_part_of_expr_corresponding_to_generic_param(
719                    broken_trait.trait_ref.self_ty().into(),
720                    expr,
721                    impl_self_ty.into(),
722                )
723            }
724            _ => Err(expr),
725        }
726    }
727
728    /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`.
729    /// For example, given
730    /// - expr: `(Some(vec![1, 2, 3]), false)`
731    /// - param: `T`
732    /// - in_ty: `(Option<Vec<T>, bool)`
733    /// we would drill until we arrive at `vec![1, 2, 3]`.
734    ///
735    /// If successful, we return `Ok(refined_expr)`. If unsuccessful, we return `Err(partially_refined_expr`),
736    /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
737    /// `foo()` and then return `Err("foo()")`.
738    ///
739    /// This means that you can (and should) use the `?` try operator to chain multiple calls to this
740    /// function with different types, since you can only continue drilling the second time if you
741    /// succeeded the first time.
742    fn blame_specific_part_of_expr_corresponding_to_generic_param(
743        &self,
744        param: ty::GenericArg<'tcx>,
745        expr: &'tcx hir::Expr<'tcx>,
746        in_ty: ty::GenericArg<'tcx>,
747    ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
748        if param == in_ty {
749            // The types match exactly, so we have drilled as far as we can.
750            return Ok(expr);
751        }
752
753        let ty::GenericArgKind::Type(in_ty) = in_ty.kind() else {
754            return Err(expr);
755        };
756
757        if let (
758            hir::ExprKind::AddrOf(_borrow_kind, _borrow_mutability, borrowed_expr),
759            ty::Ref(_ty_region, ty_ref_type, _ty_mutability),
760        ) = (&expr.kind, in_ty.kind())
761        {
762            // We can "drill into" the borrowed expression.
763            return self.blame_specific_part_of_expr_corresponding_to_generic_param(
764                param,
765                borrowed_expr,
766                (*ty_ref_type).into(),
767            );
768        }
769
770        if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
771            (&expr.kind, in_ty.kind())
772        {
773            if in_ty_elements.len() != expr_elements.len() {
774                return Err(expr);
775            }
776            // Find out which of `in_ty_elements` refer to `param`.
777            // FIXME: It may be better to take the first if there are multiple,
778            // just so that the error points to a smaller expression.
779            let Some((drill_expr, drill_ty)) =
780                is_iterator_singleton(expr_elements.iter().zip(in_ty_elements.iter()).filter(
781                    |(_expr_elem, in_ty_elem)| find_param_in_ty((*in_ty_elem).into(), param),
782                ))
783            else {
784                // The param is not mentioned, or it is mentioned in multiple indexes.
785                return Err(expr);
786            };
787
788            return self.blame_specific_part_of_expr_corresponding_to_generic_param(
789                param,
790                drill_expr,
791                drill_ty.into(),
792            );
793        }
794
795        if let (
796            hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest),
797            ty::Adt(in_ty_adt, in_ty_adt_generic_args),
798        ) = (&expr.kind, in_ty.kind())
799        {
800            // First, confirm that this struct is the same one as in the types, and if so,
801            // find the right variant.
802            let Res::Def(expr_struct_def_kind, expr_struct_def_id) =
803                self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id)
804            else {
805                return Err(expr);
806            };
807
808            let variant_def_id = match expr_struct_def_kind {
809                DefKind::Struct => {
810                    if in_ty_adt.did() != expr_struct_def_id {
811                        // FIXME: Deal with type aliases?
812                        return Err(expr);
813                    }
814                    expr_struct_def_id
815                }
816                DefKind::Variant => {
817                    // If this is a variant, its parent is the type definition.
818                    if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
819                        // FIXME: Deal with type aliases?
820                        return Err(expr);
821                    }
822                    expr_struct_def_id
823                }
824                _ => {
825                    return Err(expr);
826                }
827            };
828
829            // We need to know which of the generic parameters mentions our target param.
830            // We expect that at least one of them does, since it is expected to be mentioned.
831            let Some((drill_generic_index, generic_argument_type)) = is_iterator_singleton(
832                in_ty_adt_generic_args
833                    .iter()
834                    .enumerate()
835                    .filter(|(_index, in_ty_generic)| find_param_in_ty(*in_ty_generic, param)),
836            ) else {
837                return Err(expr);
838            };
839
840            let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
841            if drill_generic_index >= struct_generic_parameters.own_params.len() {
842                return Err(expr);
843            }
844
845            let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
846                struct_generic_parameters.param_at(drill_generic_index, self.tcx),
847            );
848
849            // We make 3 steps:
850            // Suppose we have a type like
851            // ```ignore (just for demonstration)
852            // struct ExampleStruct<T> {
853            //   enabled: bool,
854            //   item: Option<(usize, T, bool)>,
855            // }
856            //
857            // f(ExampleStruct {
858            //   enabled: false,
859            //   item: Some((0, Box::new(String::new()), 1) }, true)),
860            // });
861            // ```
862            // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
863            // for `String: Copy`, which isn't true here.
864            //
865            // (1) First, we drill into `.item` and highlight that expression
866            // (2) Then we use the template type `Option<(usize, T, bool)>` to
867            //     drill into the `T`, arriving at a `Box<String>` expression.
868            // (3) Then we keep going, drilling into this expression using our
869            //     outer contextual information.
870
871            // (1) Find the (unique) field which mentions the type in our constraint:
872            let (field_expr, field_type) = self
873                .point_at_field_if_possible(
874                    in_ty_adt.did(),
875                    param_to_point_at_in_struct,
876                    variant_def_id,
877                    expr_struct_fields,
878                )
879                .ok_or(expr)?;
880
881            // (2) Continue drilling into the struct, ignoring the struct's
882            // generic argument types.
883            let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
884                param_to_point_at_in_struct,
885                field_expr,
886                field_type.into(),
887            )?;
888
889            // (3) Continue drilling into the expression, having "passed
890            // through" the struct entirely.
891            return self.blame_specific_part_of_expr_corresponding_to_generic_param(
892                param,
893                expr,
894                generic_argument_type,
895            );
896        }
897
898        if let (
899            hir::ExprKind::Call(expr_callee, expr_args),
900            ty::Adt(in_ty_adt, in_ty_adt_generic_args),
901        ) = (&expr.kind, in_ty.kind())
902        {
903            let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else {
904                // FIXME: This case overlaps with another one worth handling,
905                // which should happen above since it applies to non-ADTs:
906                // we can drill down into regular generic functions.
907                return Err(expr);
908            };
909            // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
910
911            let Res::Def(expr_struct_def_kind, expr_ctor_def_id) =
912                self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id)
913            else {
914                return Err(expr);
915            };
916
917            let variant_def_id = match expr_struct_def_kind {
918                DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
919                    if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
920                        // FIXME: Deal with type aliases?
921                        return Err(expr);
922                    }
923                    self.tcx.parent(expr_ctor_def_id)
924                }
925                DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
926                    // For a typical enum like
927                    // `enum Blah<T> { Variant(T) }`
928                    // we get the following resolutions:
929                    // - expr_ctor_def_id :::                                   DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
930                    // - self.tcx.parent(expr_ctor_def_id) :::                  DefId(0:28 ~ source_file[b442]::Blah::Variant)
931                    // - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
932
933                    // Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
934                    // Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
935                    // together; this resolution is handled automatically by `qpath_res`.
936
937                    // FIXME: Deal with type aliases?
938                    if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
939                        // The constructor definition refers to the "constructor" of the variant:
940                        // For example, `Some(5)` triggers this case.
941                        self.tcx.parent(expr_ctor_def_id)
942                    } else {
943                        // FIXME: Deal with type aliases?
944                        return Err(expr);
945                    }
946                }
947                _ => {
948                    return Err(expr);
949                }
950            };
951
952            // We need to know which of the generic parameters mentions our target param.
953            // We expect that at least one of them does, since it is expected to be mentioned.
954            let Some((drill_generic_index, generic_argument_type)) = is_iterator_singleton(
955                in_ty_adt_generic_args
956                    .iter()
957                    .enumerate()
958                    .filter(|(_index, in_ty_generic)| find_param_in_ty(*in_ty_generic, param)),
959            ) else {
960                return Err(expr);
961            };
962
963            let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
964            if drill_generic_index >= struct_generic_parameters.own_params.len() {
965                return Err(expr);
966            }
967
968            let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
969                struct_generic_parameters.param_at(drill_generic_index, self.tcx),
970            );
971
972            // We make 3 steps:
973            // Suppose we have a type like
974            // ```ignore (just for demonstration)
975            // struct ExampleStruct<T> {
976            //   enabled: bool,
977            //   item: Option<(usize, T, bool)>,
978            // }
979            //
980            // f(ExampleStruct {
981            //   enabled: false,
982            //   item: Some((0, Box::new(String::new()), 1) }, true)),
983            // });
984            // ```
985            // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
986            // for `String: Copy`, which isn't true here.
987            //
988            // (1) First, we drill into `.item` and highlight that expression
989            // (2) Then we use the template type `Option<(usize, T, bool)>` to
990            //     drill into the `T`, arriving at a `Box<String>` expression.
991            // (3) Then we keep going, drilling into this expression using our
992            //     outer contextual information.
993
994            // (1) Find the (unique) field index which mentions the type in our constraint:
995            let Some((field_index, field_type)) = is_iterator_singleton(
996                in_ty_adt
997                    .variant_with_id(variant_def_id)
998                    .fields
999                    .iter()
1000                    .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
1001                    .enumerate()
1002                    .filter(|(_index, field_type)| find_param_in_ty((*field_type).into(), param)),
1003            ) else {
1004                return Err(expr);
1005            };
1006
1007            if field_index >= expr_args.len() {
1008                return Err(expr);
1009            }
1010
1011            // (2) Continue drilling into the struct, ignoring the struct's
1012            // generic argument types.
1013            let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
1014                param_to_point_at_in_struct,
1015                &expr_args[field_index],
1016                field_type.into(),
1017            )?;
1018
1019            // (3) Continue drilling into the expression, having "passed
1020            // through" the struct entirely.
1021            return self.blame_specific_part_of_expr_corresponding_to_generic_param(
1022                param,
1023                expr,
1024                generic_argument_type,
1025            );
1026        }
1027
1028        // At this point, none of the basic patterns matched.
1029        // One major possibility which remains is that we have a function call.
1030        // In this case, it's often possible to dive deeper into the call to find something to blame,
1031        // but this is not always possible.
1032
1033        Err(expr)
1034    }
1035}
1036
1037/// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
1038/// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
1039fn find_param_in_ty<'tcx>(
1040    ty: ty::GenericArg<'tcx>,
1041    param_to_point_at: ty::GenericArg<'tcx>,
1042) -> bool {
1043    let mut walk = ty.walk();
1044    while let Some(arg) = walk.next() {
1045        if arg == param_to_point_at {
1046            return true;
1047        }
1048        if let ty::GenericArgKind::Type(ty) = arg.kind()
1049            && let ty::Alias(ty::Projection | ty::Inherent, ..) = ty.kind()
1050        {
1051            // This logic may seem a bit strange, but typically when
1052            // we have a projection type in a function signature, the
1053            // argument that's being passed into that signature is
1054            // not actually constraining that projection's args in
1055            // a meaningful way. So we skip it, and see improvements
1056            // in some UI tests.
1057            walk.skip_current_subtree();
1058        }
1059    }
1060    false
1061}
1062
1063/// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
1064fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
1065    match (iterator.next(), iterator.next()) {
1066        (_, Some(_)) => None,
1067        (first, _) => first,
1068    }
1069}