3 use rustc_hir::def::Res;
4 use rustc_hir::def_id::DefId;
5 use rustc_infer::traits::ObligationCauseCode;
6 use rustc_middle::ty::{self, DefIdTree, Ty, TypeSuperVisitable, TypeVisitable, TypeVisitor};
7 use rustc_span::{self, Span};
8 use rustc_trait_selection::traits;
10 use std::ops::ControlFlow;
12 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13 pub fn adjust_fulfillment_error_for_expr_obligation(
15 error: &mut traits::FulfillmentError<'tcx>,
17 let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
18 = *error.obligation.cause.code().peel_derives() else { return false; };
19 let hir = self.tcx.hir();
20 let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
22 let Some(unsubstituted_pred) =
23 self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
24 else { return false; };
26 let generics = self.tcx.generics_of(def_id);
27 let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
28 ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs,
29 ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs,
30 _ => ty::List::empty(),
33 let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
34 predicate_substs.types().find_map(|ty| {
35 ty.walk().find_map(|arg| {
36 if let ty::GenericArgKind::Type(ty) = arg.unpack()
37 && let ty::Param(param_ty) = ty.kind()
48 // Prefer generics that are local to the fn item, since these are likely
49 // to be the cause of the unsatisfied predicate.
50 let mut param_to_point_at = find_param_matching(&|param_ty| {
51 self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
53 // Fall back to generic that isn't local to the fn item. This will come
54 // from a trait or impl, for example.
55 let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
56 self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
57 && param_ty.name != rustc_span::symbol::kw::SelfUpper
59 // Finally, the `Self` parameter is possibly the reason that the predicate
60 // is unsatisfied. This is less likely to be true for methods, because
61 // method probe means that we already kinda check that the predicates due
62 // to the `Self` type are true.
63 let mut self_param_to_point_at =
64 find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
66 // Finally, for ambiguity-related errors, we actually want to look
67 // for a parameter that is the source of the inference type left
68 // over in this predicate.
69 if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
70 fallback_param_to_point_at = None;
71 self_param_to_point_at = None;
73 self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
76 if self.closure_span_overlaps_error(error, expr.span) {
81 hir::ExprKind::Path(qpath) => {
82 if let hir::Node::Expr(hir::Expr {
83 kind: hir::ExprKind::Call(callee, args),
87 }) = hir.get_parent(expr.hir_id)
88 && callee.hir_id == expr.hir_id
90 if self.closure_span_overlaps_error(error, *call_span) {
95 [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
99 if self.blame_specific_arg_if_possible(
113 // Notably, we only point to params that are local to the
114 // item we're checking, since those are the ones we are able
115 // to look in the final `hir::PathSegment` for. Everything else
116 // would require a deeper search into the `qpath` than I think
118 if let Some(param_to_point_at) = param_to_point_at
119 && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
124 hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
125 for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
129 if self.blame_specific_arg_if_possible(
141 if let Some(param_to_point_at) = param_to_point_at
142 && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
147 hir::ExprKind::Struct(qpath, fields, ..) => {
149 hir::def::DefKind::Struct | hir::def::DefKind::Variant,
151 ) = self.typeck_results.borrow().qpath_res(qpath, hir_id)
154 [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
156 if let Some(param) = param {
157 let refined_expr = self.point_at_field_if_possible(
166 Some((refined_expr, _)) => {
167 error.obligation.cause.span = refined_expr
169 .find_ancestor_in_same_ctxt(error.obligation.cause.span)
170 .unwrap_or(refined_expr.span);
177 if let Some(param_to_point_at) = param_to_point_at
178 && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
189 fn point_at_path_if_possible(
191 error: &mut traits::FulfillmentError<'tcx>,
193 param: ty::GenericArg<'tcx>,
194 qpath: &hir::QPath<'tcx>,
197 hir::QPath::Resolved(_, path) => {
198 if let Some(segment) = path.segments.last()
199 && self.point_at_generic_if_possible(error, def_id, param, segment)
204 hir::QPath::TypeRelative(_, segment) => {
205 if self.point_at_generic_if_possible(error, def_id, param, segment) {
215 fn point_at_generic_if_possible(
217 error: &mut traits::FulfillmentError<'tcx>,
219 param_to_point_at: ty::GenericArg<'tcx>,
220 segment: &hir::PathSegment<'tcx>,
222 let own_substs = self
225 .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
226 let Some((index, _)) = own_substs
228 .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
230 .find(|(_, arg)| **arg == param_to_point_at) else { return false };
231 let Some(arg) = segment
235 .filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
236 .nth(index) else { return false; };
237 error.obligation.cause.span = arg
239 .find_ancestor_in_same_ctxt(error.obligation.cause.span)
240 .unwrap_or(arg.span());
244 fn find_ambiguous_parameter_in<T: TypeVisitable<'tcx>>(
248 ) -> Option<ty::GenericArg<'tcx>> {
249 struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
250 impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> {
251 type BreakTy = ty::GenericArg<'tcx>;
252 fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
253 if let Some(origin) = self.0.type_var_origin(ty)
254 && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
256 && let generics = self.0.tcx.generics_of(self.1)
257 && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
258 && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
261 ControlFlow::Break(*subst)
263 ty.super_visit_with(self)
267 t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
270 fn closure_span_overlaps_error(
272 error: &traits::FulfillmentError<'tcx>,
275 if let traits::FulfillmentErrorCode::CodeSelectionError(
276 traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
278 && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
279 && span.overlaps(self.tcx.def_span(*def_id))
287 fn point_at_field_if_possible(
290 param_to_point_at: ty::GenericArg<'tcx>,
291 variant_def_id: DefId,
292 expr_fields: &[hir::ExprField<'tcx>],
293 ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
294 let def = self.tcx.adt_def(def_id);
296 let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
297 let fields_referencing_param: Vec<_> = def
298 .variant_with_id(variant_def_id)
302 let field_ty = field.ty(self.tcx, identity_substs);
303 Self::find_param_in_ty(field_ty.into(), param_to_point_at)
307 if let [field] = fields_referencing_param.as_slice() {
308 for expr_field in expr_fields {
309 // Look for the ExprField that matches the field, using the
310 // same rules that check_expr_struct uses for macro hygiene.
311 if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
313 return Some((expr_field.expr, self.tcx.type_of(field.did)));
321 /// - `blame_specific_*` means that the function will recursively traverse the expression,
322 /// looking for the most-specific-possible span to blame.
324 /// - `point_at_*` means that the function will only go "one level", pointing at the specific
325 /// expression mentioned.
327 /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
328 /// the provided function call expression, and mark it as responsible for the fullfillment
330 fn blame_specific_arg_if_possible(
332 error: &mut traits::FulfillmentError<'tcx>,
334 param_to_point_at: ty::GenericArg<'tcx>,
335 call_hir_id: hir::HirId,
337 receiver: Option<&'tcx hir::Expr<'tcx>>,
338 args: &'tcx [hir::Expr<'tcx>],
340 let ty = self.tcx.type_of(def_id);
344 let sig = ty.fn_sig(self.tcx).skip_binder();
345 let args_referencing_param: Vec<_> = sig
349 .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at))
351 // If there's one field that references the given generic, great!
352 if let [(idx, _)] = args_referencing_param.as_slice()
353 && let Some(arg) = receiver
354 .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
356 error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
358 if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) {
359 // This is more specific than pointing at the entire argument.
360 self.blame_specific_expr_if_possible(error, arg_expr)
363 error.obligation.cause.map_code(|parent_code| {
364 ObligationCauseCode::FunctionArgumentObligation {
365 arg_hir_id: arg.hir_id,
371 } else if args_referencing_param.len() > 0 {
372 // If more than one argument applies, then point to the callee span at least...
373 // We have chance to fix this up further in `point_at_generics_if_possible`
374 error.obligation.cause.span = callee_span;
381 * Recursively searches for the most-specific blamable expression.
382 * For example, if you have a chain of constraints like:
383 * - want `Vec<i32>: Copy`
384 * - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
385 * - because `(Option<Vec<i32>, bool)` needs `Option<Vec<i32>>: Copy` because `impl <A: Copy, B: Copy> Copy for (A, B)`
386 * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible`
387 * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint.
389 * This function only updates the error span.
391 pub fn blame_specific_expr_if_possible(
393 error: &mut traits::FulfillmentError<'tcx>,
394 expr: &'tcx hir::Expr<'tcx>,
396 // Whether it succeeded or failed, it likely made some amount of progress.
397 // In the very worst case, it's just the same `expr` we originally passed in.
398 let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
399 &error.obligation.cause.code(),
406 // Either way, use this expression to update the error span.
407 // If it doesn't overlap the existing span at all, use the original span.
408 // FIXME: It would possibly be better to do this more continuously, at each level...
409 error.obligation.cause.span = expr
411 .find_ancestor_in_same_ctxt(error.obligation.cause.span)
412 .unwrap_or(error.obligation.cause.span);
415 fn blame_specific_expr_if_possible_for_obligation_cause_code(
417 obligation_cause_code: &traits::ObligationCauseCode<'tcx>,
418 expr: &'tcx hir::Expr<'tcx>,
419 ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
420 match obligation_cause_code {
421 traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => {
422 // This is the "root"; we assume that the `expr` is already pointing here.
423 // Therefore, we return `Ok` so that this `expr` can be refined further.
426 traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
427 .blame_specific_expr_if_possible_for_derived_predicate_obligation(
432 // We don't recognize this kind of constraint, so we cannot refine the expression
439 /// We want to achieve the error span in the following example:
441 /// ```ignore (just for demonstration)
442 /// struct Burrito<Filling> {
443 /// filling: Filling,
445 /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
446 /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
448 /// fn will_type_error() {
449 /// eat_delicious_food(Burrito { filling: Kale });
450 /// } // ^--- The trait bound `Kale: Delicious`
451 /// // is not satisfied
454 /// Without calling this function, the error span will cover the entire argument expression.
456 /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
457 /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
459 /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
460 /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
461 /// only a partial success - but it cannot be refined even further.
462 fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
464 obligation: &traits::ImplDerivedObligationCause<'tcx>,
465 expr: &'tcx hir::Expr<'tcx>,
466 ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
467 // First, we attempt to refine the `expr` for our span using the parent obligation.
468 // If this cannot be done, then we are already stuck, so we stop early (hence the use
469 // of the `?` try operator here).
470 let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code(
471 &*obligation.derived.parent_code,
475 // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
476 // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
478 let impl_trait_self_ref: Option<ty::TraitRef<'tcx>> =
479 self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder());
481 let Some(impl_trait_self_ref) = impl_trait_self_ref else {
482 // It is possible that this is absent. In this case, we make no progress.
486 // We only really care about the `Self` type itself, which we extract from the ref.
487 let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
489 let impl_predicates: ty::GenericPredicates<'tcx> =
490 self.tcx.predicates_of(obligation.impl_def_id);
491 let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
492 // We don't have the index, so we can only guess.
496 if impl_predicate_index >= impl_predicates.predicates.len() {
497 // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
500 let relevant_broken_predicate: ty::PredicateKind<'tcx> =
501 impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
503 match relevant_broken_predicate {
504 ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
506 self.blame_specific_part_of_expr_corresponding_to_generic_param(
507 broken_trait.trait_ref.self_ty().into(),
516 /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`.
517 /// For example, given
518 /// - expr: `(Some(vec![1, 2, 3]), false)`
520 /// - in_ty: `(Option<Vec<T>, bool)`
521 /// we would drill until we arrive at `vec![1, 2, 3]`.
523 /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`),
524 /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
525 /// `foo()` and then return `Err("foo()")`.
527 /// This means that you can (and should) use the `?` try operator to chain multiple calls to this
528 /// function with different types, since you can only continue drilling the second time if you
529 /// succeeded the first time.
530 fn blame_specific_part_of_expr_corresponding_to_generic_param(
532 param: ty::GenericArg<'tcx>,
533 expr: &'tcx hir::Expr<'tcx>,
534 in_ty: ty::GenericArg<'tcx>,
535 ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
537 // The types match exactly, so we have drilled as far as we can.
541 let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
545 if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
546 (&expr.kind, in_ty.kind())
548 if in_ty_elements.len() != expr_elements.len() {
551 // Find out which of `in_ty_elements` refer to `param`.
552 // FIXME: It may be better to take the first if there are multiple,
553 // just so that the error points to a smaller expression.
554 let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
555 Self::find_param_in_ty((*in_ty_elem).into(), param)
557 // The param is not mentioned, or it is mentioned in multiple indexes.
561 return self.blame_specific_part_of_expr_corresponding_to_generic_param(
569 hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest),
570 ty::Adt(in_ty_adt, in_ty_adt_generic_args),
571 ) = (&expr.kind, in_ty.kind())
573 // First, confirm that this struct is the same one as in the types, and if so,
574 // find the right variant.
575 let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else {
579 let variant_def_id = match expr_struct_def_kind {
580 hir::def::DefKind::Struct => {
581 if in_ty_adt.did() != expr_struct_def_id {
582 // FIXME: Deal with type aliases?
587 hir::def::DefKind::Variant => {
588 // If this is a variant, its parent is the type definition.
589 if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
590 // FIXME: Deal with type aliases?
600 // We need to know which of the generic parameters mentions our target param.
601 // We expect that at least one of them does, since it is expected to be mentioned.
602 let Some((drill_generic_index, generic_argument_type)) =
603 Self::is_iterator_singleton(
604 in_ty_adt_generic_args.iter().enumerate().filter(
605 |(_index, in_ty_generic)| {
606 Self::find_param_in_ty(*in_ty_generic, param)
613 let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
614 if drill_generic_index >= struct_generic_parameters.params.len() {
618 let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
619 struct_generic_parameters.param_at(drill_generic_index, self.tcx),
623 // Suppose we have a type like
624 // ```ignore (just for demonstration)
625 // struct ExampleStruct<T> {
627 // item: Option<(usize, T, bool)>,
632 // item: Some((0, Box::new(String::new()), 1) }, true)),
635 // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
636 // for `String: Copy`, which isn't true here.
638 // (1) First, we drill into `.item` and highlight that expression
639 // (2) Then we use the template type `Option<(usize, T, bool)>` to
640 // drill into the `T`, arriving at a `Box<String>` expression.
641 // (3) Then we keep going, drilling into this expression using our
642 // outer contextual information.
644 // (1) Find the (unique) field which mentions the type in our constraint:
645 let (field_expr, field_type) = self
646 .point_at_field_if_possible(
648 param_to_point_at_in_struct,
654 // (2) Continue drilling into the struct, ignoring the struct's
655 // generic argument types.
656 let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
657 param_to_point_at_in_struct,
662 // (3) Continue drilling into the expression, having "passed
663 // through" the struct entirely.
664 return self.blame_specific_part_of_expr_corresponding_to_generic_param(
667 generic_argument_type,
672 hir::ExprKind::Call(expr_callee, expr_args),
673 ty::Adt(in_ty_adt, in_ty_adt_generic_args),
674 ) = (&expr.kind, in_ty.kind())
676 let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else {
677 // FIXME: This case overlaps with another one worth handling,
678 // which should happen above since it applies to non-ADTs:
679 // we can drill down into regular generic functions.
682 // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
684 let Res::Def(expr_struct_def_kind, expr_ctor_def_id) = self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id) else {
688 let variant_def_id = match expr_struct_def_kind {
689 hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
690 if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
691 // FIXME: Deal with type aliases?
694 self.tcx.parent(expr_ctor_def_id)
696 hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
697 // If this is a variant, its parent is the type definition.
698 if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
699 // FIXME: Deal with type aliases?
709 // We need to know which of the generic parameters mentions our target param.
710 // We expect that at least one of them does, since it is expected to be mentioned.
711 let Some((drill_generic_index, generic_argument_type)) =
712 Self::is_iterator_singleton(
713 in_ty_adt_generic_args.iter().enumerate().filter(
714 |(_index, in_ty_generic)| {
715 Self::find_param_in_ty(*in_ty_generic, param)
722 let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
723 if drill_generic_index >= struct_generic_parameters.params.len() {
727 let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
728 struct_generic_parameters.param_at(drill_generic_index, self.tcx),
732 // Suppose we have a type like
733 // ```ignore (just for demonstration)
734 // struct ExampleStruct<T> {
736 // item: Option<(usize, T, bool)>,
741 // item: Some((0, Box::new(String::new()), 1) }, true)),
744 // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
745 // for `String: Copy`, which isn't true here.
747 // (1) First, we drill into `.item` and highlight that expression
748 // (2) Then we use the template type `Option<(usize, T, bool)>` to
749 // drill into the `T`, arriving at a `Box<String>` expression.
750 // (3) Then we keep going, drilling into this expression using our
751 // outer contextual information.
753 // (1) Find the (unique) field index which mentions the type in our constraint:
754 let Some((field_index, field_type)) = Self::is_iterator_singleton(
756 .variant_with_id(variant_def_id)
759 .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
761 .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param))
766 if field_index >= expr_args.len() {
770 // (2) Continue drilling into the struct, ignoring the struct's
771 // generic argument types.
772 let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
773 param_to_point_at_in_struct,
774 &expr_args[field_index],
778 // (3) Continue drilling into the expression, having "passed
779 // through" the struct entirely.
780 return self.blame_specific_part_of_expr_corresponding_to_generic_param(
783 generic_argument_type,
787 // At this point, none of the basic patterns matched.
788 // One major possibility which remains is that we have a function call.
789 // In this case, it's often possible to dive deeper into the call to find something to blame,
790 // but this is not always possible.
795 // FIXME: This can be made into a private, non-impl function later.
796 /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
797 /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
798 pub fn find_param_in_ty(
799 ty: ty::GenericArg<'tcx>,
800 param_to_point_at: ty::GenericArg<'tcx>,
802 let mut walk = ty.walk();
803 while let Some(arg) = walk.next() {
804 if arg == param_to_point_at {
806 } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
807 && let ty::Alias(ty::Projection, ..) = ty.kind()
809 // This logic may seem a bit strange, but typically when
810 // we have a projection type in a function signature, the
811 // argument that's being passed into that signature is
812 // not actually constraining that projection's substs in
813 // a meaningful way. So we skip it, and see improvements
815 walk.skip_current_subtree();
821 // FIXME: This can be made into a private, non-impl function later.
822 /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
823 pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
824 match (iterator.next(), iterator.next()) {
825 (_, Some(_)) => None,