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