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