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