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