]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
2eab68050d43043d6395205cbb863cb908445677
[rust.git] / compiler / rustc_hir_typeck / src / fn_ctxt / adjust_fulfillment_errors.rs
1 use crate::FnCtxt;
2 use rustc_hir as hir;
3 use rustc_hir::def::Res;
4 use rustc_middle::ty::{self, DefIdTree, Ty};
5 use rustc_trait_selection::traits;
6
7 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8     /**
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.
16      *
17      * This function only updates the error span.
18      */
19     pub fn blame_specific_expr_if_possible(
20         &self,
21         error: &mut traits::FulfillmentError<'tcx>,
22         expr: &'tcx hir::Expr<'tcx>,
23     ) {
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(),
28             expr,
29         ) {
30             Ok(expr) => expr,
31             Err(expr) => expr,
32         };
33
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
38             .span
39             .find_ancestor_in_same_ctxt(error.obligation.cause.span)
40             .unwrap_or(error.obligation.cause.span);
41     }
42
43     fn blame_specific_expr_if_possible_for_obligation_cause_code(
44         &self,
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.
52                 Ok(expr)
53             }
54             traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
55                 .blame_specific_expr_if_possible_for_derived_predicate_obligation(
56                     impl_derived,
57                     expr,
58                 ),
59             _ => {
60                 // We don't recognize this kind of constraint, so we cannot refine the expression
61                 // any further.
62                 Err(expr)
63             }
64         }
65     }
66
67     /// We want to achieve the error span in the following example:
68     ///
69     /// ```ignore (just for demonstration)
70     /// struct Burrito<Filling> {
71     ///   filling: Filling,
72     /// }
73     /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
74     /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
75     ///
76     /// fn will_type_error() {
77     ///   eat_delicious_food(Burrito { filling: Kale });
78     /// } //                                    ^--- The trait bound `Kale: Delicious`
79     ///   //                                         is not satisfied
80     /// ```
81     ///
82     /// Without calling this function, the error span will cover the entire argument expression.
83     ///
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.
86     ///
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(
91         &self,
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,
100             expr,
101         )?;
102
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
105         // that struct type.
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());
108
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.
111             return Err(expr);
112         };
113
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();
116
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.
121             return Err(expr);
122         };
123
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.
126             return Err(expr);
127         }
128         let relevant_broken_predicate: ty::PredicateKind<'tcx> =
129             impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
130
131         match relevant_broken_predicate {
132             ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
133                 // ...
134                 self.blame_specific_part_of_expr_corresponding_to_generic_param(
135                     broken_trait.trait_ref.self_ty().into(),
136                     expr,
137                     impl_self_ty.into(),
138                 )
139             }
140             _ => Err(expr),
141         }
142     }
143
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)`
147     /// - param: `T`
148     /// - in_ty: `(Option<Vec<T>, bool)`
149     /// we would drill until we arrive at `vec![1, 2, 3]`.
150     ///
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()")`.
154     ///
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(
159         &self,
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>> {
164         if param == in_ty {
165             // The types match exactly, so we have drilled as far as we can.
166             return Ok(expr);
167         }
168
169         let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
170             return Err(expr);
171         };
172
173         if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
174             (&expr.kind, in_ty.kind())
175         {
176             if in_ty_elements.len() != expr_elements.len() {
177                 return Err(expr);
178             }
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)
184             })) else {
185                 // The param is not mentioned, or it is mentioned in multiple indexes.
186                 return Err(expr);
187             };
188
189             return self.blame_specific_part_of_expr_corresponding_to_generic_param(
190                 param,
191                 drill_expr,
192                 drill_ty.into(),
193             );
194         }
195
196         if let (
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())
200         {
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 {
204                 return Err(expr);
205             };
206
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?
211                         return Err(expr);
212                     }
213                     expr_struct_def_id
214                 }
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?
219                         return Err(expr);
220                     }
221                     expr_struct_def_id
222                 }
223                 _ => {
224                     return Err(expr);
225                 }
226             };
227
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)
235                         },
236                     ),
237                 ) else {
238                     return Err(expr);
239                 };
240
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() {
243                 return Err(expr);
244             }
245
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),
248             );
249
250             // We make 3 steps:
251             // Suppose we have a type like
252             // ```ignore (just for demonstration)
253             // struct ExampleStruct<T> {
254             //   enabled: bool,
255             //   item: Option<(usize, T, bool)>,
256             // }
257             //
258             // f(ExampleStruct {
259             //   enabled: false,
260             //   item: Some((0, Box::new(String::new()), 1) }, true)),
261             // });
262             // ```
263             // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
264             // for `String: Copy`, which isn't true here.
265             //
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.
271
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(
275                     in_ty_adt.did(),
276                     param_to_point_at_in_struct,
277                     variant_def_id,
278                     expr_struct_fields,
279                 )
280                 .ok_or(expr)?;
281
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,
286                 field_expr,
287                 field_type.into(),
288             )?;
289
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(
293                 param,
294                 expr,
295                 generic_argument_type,
296             );
297         }
298
299         if let (
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())
303         {
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.
308                 return Err(expr);
309             };
310             // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
311
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 {
313                 return Err(expr);
314             };
315
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?
320                         return Err(expr);
321                     }
322                     self.tcx.parent(expr_ctor_def_id)
323                 }
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?
328                         return Err(expr);
329                     }
330                     expr_ctor_def_id
331                 }
332                 _ => {
333                     return Err(expr);
334                 }
335             };
336
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)
344                         },
345                     ),
346                 ) else {
347                     return Err(expr);
348                 };
349
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() {
352                 return Err(expr);
353             }
354
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),
357             );
358
359             // We make 3 steps:
360             // Suppose we have a type like
361             // ```ignore (just for demonstration)
362             // struct ExampleStruct<T> {
363             //   enabled: bool,
364             //   item: Option<(usize, T, bool)>,
365             // }
366             //
367             // f(ExampleStruct {
368             //   enabled: false,
369             //   item: Some((0, Box::new(String::new()), 1) }, true)),
370             // });
371             // ```
372             // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
373             // for `String: Copy`, which isn't true here.
374             //
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.
380
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(
383                 in_ty_adt
384                     .variant_with_id(variant_def_id)
385                     .fields
386                     .iter()
387                     .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
388                     .enumerate()
389                     .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param))
390             ) else {
391                 return Err(expr);
392             };
393
394             if field_index >= expr_args.len() {
395                 return Err(expr);
396             }
397
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],
403                 field_type.into(),
404             )?;
405
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(
409                 param,
410                 expr,
411                 generic_argument_type,
412             );
413         }
414
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.
419
420         Err(expr)
421     }
422
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>,
429     ) -> bool {
430         let mut walk = ty.walk();
431         while let Some(arg) = walk.next() {
432             if arg == param_to_point_at {
433             return true;
434         } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
435             && let ty::Alias(ty::Projection, ..) = ty.kind()
436         {
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
442             // in some UI tests.
443             walk.skip_current_subtree();
444         }
445         }
446         false
447     }
448
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,
454             (first, _) => first,
455         }
456     }
457 }