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