Skip to main content

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