3 use rustc_hir::def::Res;
4 use rustc_middle::ty::{self, DefIdTree, Ty};
5 use rustc_trait_selection::traits;
7 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9 * Recursively searches for the most-specific blamable expression.
10 * For example, if you have a chain of constraints like:
11 * - want `Vec<i32>: Copy`
12 * - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
13 * - because `(Option<Vec<i32>, bool)` needs `Option<Vec<i32>>: Copy` because `impl <A: Copy, B: Copy> Copy for (A, B)`
14 * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible`
15 * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint.
17 * This function only updates the error span.
19 pub fn blame_specific_expr_if_possible(
21 error: &mut traits::FulfillmentError<'tcx>,
22 expr: &'tcx hir::Expr<'tcx>,
24 // Whether it succeeded or failed, it likely made some amount of progress.
25 // In the very worst case, it's just the same `expr` we originally passed in.
26 let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
27 &error.obligation.cause.code(),
34 // Either way, use this expression to update the error span.
35 // If it doesn't overlap the existing span at all, use the original span.
36 // FIXME: It would possibly be better to do this more continuously, at each level...
37 error.obligation.cause.span = expr
39 .find_ancestor_in_same_ctxt(error.obligation.cause.span)
40 .unwrap_or(error.obligation.cause.span);
43 fn blame_specific_expr_if_possible_for_obligation_cause_code(
45 obligation_cause_code: &traits::ObligationCauseCode<'tcx>,
46 expr: &'tcx hir::Expr<'tcx>,
47 ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
48 match obligation_cause_code {
49 traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => {
50 // This is the "root"; we assume that the `expr` is already pointing here.
51 // Therefore, we return `Ok` so that this `expr` can be refined further.
54 traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
55 .blame_specific_expr_if_possible_for_derived_predicate_obligation(
60 // We don't recognize this kind of constraint, so we cannot refine the expression
67 /// We want to achieve the error span in the following example:
69 /// ```ignore (just for demonstration)
70 /// struct Burrito<Filling> {
73 /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
74 /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
76 /// fn will_type_error() {
77 /// eat_delicious_food(Burrito { filling: Kale });
78 /// } // ^--- The trait bound `Kale: Delicious`
79 /// // is not satisfied
82 /// Without calling this function, the error span will cover the entire argument expression.
84 /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
85 /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
87 /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
88 /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
89 /// only a partial success - but it cannot be refined even further.
90 fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
92 obligation: &traits::ImplDerivedObligationCause<'tcx>,
93 expr: &'tcx hir::Expr<'tcx>,
94 ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
95 // First, we attempt to refine the `expr` for our span using the parent obligation.
96 // If this cannot be done, then we are already stuck, so we stop early (hence the use
97 // of the `?` try operator here).
98 let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code(
99 &*obligation.derived.parent_code,
103 // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
104 // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
106 let impl_trait_self_ref: Option<ty::TraitRef<'tcx>> =
107 self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder());
109 let Some(impl_trait_self_ref) = impl_trait_self_ref else {
110 // It is possible that this is absent. In this case, we make no progress.
114 // We only really care about the `Self` type itself, which we extract from the ref.
115 let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
117 let impl_predicates: ty::GenericPredicates<'tcx> =
118 self.tcx.predicates_of(obligation.impl_def_id);
119 let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
120 // We don't have the index, so we can only guess.
124 if impl_predicate_index >= impl_predicates.predicates.len() {
125 // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
128 let relevant_broken_predicate: ty::PredicateKind<'tcx> =
129 impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
131 match relevant_broken_predicate {
132 ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
134 self.blame_specific_part_of_expr_corresponding_to_generic_param(
135 broken_trait.trait_ref.self_ty().into(),
144 /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`.
145 /// For example, given
146 /// - expr: `(Some(vec![1, 2, 3]), false)`
148 /// - in_ty: `(Option<Vec<T>, bool)`
149 /// we would drill until we arrive at `vec![1, 2, 3]`.
151 /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`),
152 /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
153 /// `foo()` and then return `Err("foo()")`.
155 /// This means that you can (and should) use the `?` try operator to chain multiple calls to this
156 /// function with different types, since you can only continue drilling the second time if you
157 /// succeeded the first time.
158 fn blame_specific_part_of_expr_corresponding_to_generic_param(
160 param: ty::GenericArg<'tcx>,
161 expr: &'tcx hir::Expr<'tcx>,
162 in_ty: ty::GenericArg<'tcx>,
163 ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
165 // The types match exactly, so we have drilled as far as we can.
169 let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
173 if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
174 (&expr.kind, in_ty.kind())
176 if in_ty_elements.len() != expr_elements.len() {
179 // Find out which of `in_ty_elements` refer to `param`.
180 // FIXME: It may be better to take the first if there are multiple,
181 // just so that the error points to a smaller expression.
182 let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
183 Self::find_param_in_ty((*in_ty_elem).into(), param)
185 // The param is not mentioned, or it is mentioned in multiple indexes.
189 return self.blame_specific_part_of_expr_corresponding_to_generic_param(
197 hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest),
198 ty::Adt(in_ty_adt, in_ty_adt_generic_args),
199 ) = (&expr.kind, in_ty.kind())
201 // First, confirm that this struct is the same one as in the types, and if so,
202 // find the right variant.
203 let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else {
207 let variant_def_id = match expr_struct_def_kind {
208 hir::def::DefKind::Struct => {
209 if in_ty_adt.did() != expr_struct_def_id {
210 // FIXME: Deal with type aliases?
215 hir::def::DefKind::Variant => {
216 // If this is a variant, its parent is the type definition.
217 if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
218 // FIXME: Deal with type aliases?
228 // We need to know which of the generic parameters mentions our target param.
229 // We expect that at least one of them does, since it is expected to be mentioned.
230 let Some((drill_generic_index, generic_argument_type)) =
231 Self::is_iterator_singleton(
232 in_ty_adt_generic_args.iter().enumerate().filter(
233 |(_index, in_ty_generic)| {
234 Self::find_param_in_ty(*in_ty_generic, param)
241 let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
242 if drill_generic_index >= struct_generic_parameters.params.len() {
246 let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
247 struct_generic_parameters.param_at(drill_generic_index, self.tcx),
251 // Suppose we have a type like
252 // ```ignore (just for demonstration)
253 // struct ExampleStruct<T> {
255 // item: Option<(usize, T, bool)>,
260 // item: Some((0, Box::new(String::new()), 1) }, true)),
263 // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
264 // for `String: Copy`, which isn't true here.
266 // (1) First, we drill into `.item` and highlight that expression
267 // (2) Then we use the template type `Option<(usize, T, bool)>` to
268 // drill into the `T`, arriving at a `Box<String>` expression.
269 // (3) Then we keep going, drilling into this expression using our
270 // outer contextual information.
272 // (1) Find the (unique) field which mentions the type in our constraint:
273 let (field_expr, field_type) = self
274 .point_at_field_if_possible(
276 param_to_point_at_in_struct,
282 // (2) Continue drilling into the struct, ignoring the struct's
283 // generic argument types.
284 let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
285 param_to_point_at_in_struct,
290 // (3) Continue drilling into the expression, having "passed
291 // through" the struct entirely.
292 return self.blame_specific_part_of_expr_corresponding_to_generic_param(
295 generic_argument_type,
300 hir::ExprKind::Call(expr_callee, expr_args),
301 ty::Adt(in_ty_adt, in_ty_adt_generic_args),
302 ) = (&expr.kind, in_ty.kind())
304 let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else {
305 // FIXME: This case overlaps with another one worth handling,
306 // which should happen above since it applies to non-ADTs:
307 // we can drill down into regular generic functions.
310 // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
312 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 {
316 let variant_def_id = match expr_struct_def_kind {
317 hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
318 if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
319 // FIXME: Deal with type aliases?
322 self.tcx.parent(expr_ctor_def_id)
324 hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
325 // If this is a variant, its parent is the type definition.
326 if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
327 // FIXME: Deal with type aliases?
337 // We need to know which of the generic parameters mentions our target param.
338 // We expect that at least one of them does, since it is expected to be mentioned.
339 let Some((drill_generic_index, generic_argument_type)) =
340 Self::is_iterator_singleton(
341 in_ty_adt_generic_args.iter().enumerate().filter(
342 |(_index, in_ty_generic)| {
343 Self::find_param_in_ty(*in_ty_generic, param)
350 let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
351 if drill_generic_index >= struct_generic_parameters.params.len() {
355 let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
356 struct_generic_parameters.param_at(drill_generic_index, self.tcx),
360 // Suppose we have a type like
361 // ```ignore (just for demonstration)
362 // struct ExampleStruct<T> {
364 // item: Option<(usize, T, bool)>,
369 // item: Some((0, Box::new(String::new()), 1) }, true)),
372 // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
373 // for `String: Copy`, which isn't true here.
375 // (1) First, we drill into `.item` and highlight that expression
376 // (2) Then we use the template type `Option<(usize, T, bool)>` to
377 // drill into the `T`, arriving at a `Box<String>` expression.
378 // (3) Then we keep going, drilling into this expression using our
379 // outer contextual information.
381 // (1) Find the (unique) field index which mentions the type in our constraint:
382 let Some((field_index, field_type)) = Self::is_iterator_singleton(
384 .variant_with_id(variant_def_id)
387 .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
389 .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param))
394 if field_index >= expr_args.len() {
398 // (2) Continue drilling into the struct, ignoring the struct's
399 // generic argument types.
400 let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
401 param_to_point_at_in_struct,
402 &expr_args[field_index],
406 // (3) Continue drilling into the expression, having "passed
407 // through" the struct entirely.
408 return self.blame_specific_part_of_expr_corresponding_to_generic_param(
411 generic_argument_type,
415 // At this point, none of the basic patterns matched.
416 // One major possibility which remains is that we have a function call.
417 // In this case, it's often possible to dive deeper into the call to find something to blame,
418 // but this is not always possible.
423 // FIXME: This can be made into a private, non-impl function later.
424 /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
425 /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
426 pub fn find_param_in_ty(
427 ty: ty::GenericArg<'tcx>,
428 param_to_point_at: ty::GenericArg<'tcx>,
430 let mut walk = ty.walk();
431 while let Some(arg) = walk.next() {
432 if arg == param_to_point_at {
434 } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
435 && let ty::Alias(ty::Projection, ..) = ty.kind()
437 // This logic may seem a bit strange, but typically when
438 // we have a projection type in a function signature, the
439 // argument that's being passed into that signature is
440 // not actually constraining that projection's substs in
441 // a meaningful way. So we skip it, and see improvements
443 walk.skip_current_subtree();
449 // FIXME: This can be made into a private, non-impl function later.
450 /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
451 pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
452 match (iterator.next(), iterator.next()) {
453 (_, Some(_)) => None,