]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs
Rollup merge of #58273 - taiki-e:rename-dependency, r=matthewjasper
[rust.git] / src / librustc / infer / error_reporting / nice_region_error / placeholder_error.rs
1 use errors::DiagnosticBuilder;
2 use crate::hir::def_id::DefId;
3 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
4 use crate::infer::lexical_region_resolve::RegionResolutionError;
5 use crate::infer::ValuePairs;
6 use crate::infer::{SubregionOrigin, TypeTrace};
7 use crate::traits::{ObligationCause, ObligationCauseCode};
8 use crate::ty;
9 use crate::ty::error::ExpectedFound;
10 use crate::ty::subst::Substs;
11 use crate::util::common::ErrorReported;
12 use crate::util::ppaux::RegionHighlightMode;
13
14 impl NiceRegionError<'me, 'gcx, 'tcx> {
15     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
16     /// an anonymous region, emit a descriptive diagnostic error.
17     pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> {
18         match &self.error {
19             ///////////////////////////////////////////////////////////////////////////
20             // NB. The ordering of cases in this match is very
21             // sensitive, because we are often matching against
22             // specific cases and then using an `_` to match all
23             // others.
24
25             ///////////////////////////////////////////////////////////////////////////
26             // Check for errors from comparing trait failures -- first
27             // with two placeholders, then with one.
28             Some(RegionResolutionError::SubSupConflict(
29                 vid,
30                 _,
31                 SubregionOrigin::Subtype(TypeTrace {
32                     cause,
33                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
34                 }),
35                 sub_placeholder @ ty::RePlaceholder(_),
36                 _,
37                 sup_placeholder @ ty::RePlaceholder(_),
38             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
39                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
40                 cause,
41                 Some(sub_placeholder),
42                 Some(sup_placeholder),
43                 expected.def_id,
44                 expected.substs,
45                 found.substs,
46             )),
47
48             Some(RegionResolutionError::SubSupConflict(
49                 vid,
50                 _,
51                 SubregionOrigin::Subtype(TypeTrace {
52                     cause,
53                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
54                 }),
55                 sub_placeholder @ ty::RePlaceholder(_),
56                 _,
57                 _,
58             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
59                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
60                 cause,
61                 Some(sub_placeholder),
62                 None,
63                 expected.def_id,
64                 expected.substs,
65                 found.substs,
66             )),
67
68             Some(RegionResolutionError::SubSupConflict(
69                 vid,
70                 _,
71                 SubregionOrigin::Subtype(TypeTrace {
72                     cause,
73                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
74                 }),
75                 _,
76                 _,
77                 sup_placeholder @ ty::RePlaceholder(_),
78             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
79                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
80                 cause,
81                 None,
82                 Some(*sup_placeholder),
83                 expected.def_id,
84                 expected.substs,
85                 found.substs,
86             )),
87
88             Some(RegionResolutionError::SubSupConflict(
89                 vid,
90                 _,
91                 _,
92                 _,
93                 SubregionOrigin::Subtype(TypeTrace {
94                     cause,
95                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
96                 }),
97                 sup_placeholder @ ty::RePlaceholder(_),
98             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
99                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
100                 cause,
101                 None,
102                 Some(*sup_placeholder),
103                 expected.def_id,
104                 expected.substs,
105                 found.substs,
106             )),
107
108             Some(RegionResolutionError::ConcreteFailure(
109                 SubregionOrigin::Subtype(TypeTrace {
110                     cause,
111                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
112                 }),
113                 sub_region @ ty::RePlaceholder(_),
114                 sup_region @ ty::RePlaceholder(_),
115             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
116                 None,
117                 cause,
118                 Some(*sub_region),
119                 Some(*sup_region),
120                 expected.def_id,
121                 expected.substs,
122                 found.substs,
123             )),
124
125             Some(RegionResolutionError::ConcreteFailure(
126                 SubregionOrigin::Subtype(TypeTrace {
127                     cause,
128                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
129                 }),
130                 sub_region @ ty::RePlaceholder(_),
131                 sup_region,
132             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
133                 Some(sup_region),
134                 cause,
135                 Some(*sub_region),
136                 None,
137                 expected.def_id,
138                 expected.substs,
139                 found.substs,
140             )),
141
142             Some(RegionResolutionError::ConcreteFailure(
143                 SubregionOrigin::Subtype(TypeTrace {
144                     cause,
145                     values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
146                 }),
147                 sub_region,
148                 sup_region @ ty::RePlaceholder(_),
149             )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
150                 Some(sub_region),
151                 cause,
152                 None,
153                 Some(*sup_region),
154                 expected.def_id,
155                 expected.substs,
156                 found.substs,
157             )),
158
159             _ => None,
160         }
161     }
162
163     // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
164     //   --> /home/nmatsakis/tmp/foo.rs:12:5
165     //    |
166     // 12 |     all::<&'static u32>();
167     //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
168     //    |
169     //    = note: Due to a where-clause on the function `all`,
170     //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
171     //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
172     fn try_report_placeholders_trait(
173         &self,
174         vid: Option<ty::Region<'tcx>>,
175         cause: &ObligationCause<'tcx>,
176         sub_placeholder: Option<ty::Region<'tcx>>,
177         sup_placeholder: Option<ty::Region<'tcx>>,
178         trait_def_id: DefId,
179         expected_substs: &'tcx Substs<'tcx>,
180         actual_substs: &'tcx Substs<'tcx>,
181     ) -> ErrorReported {
182         debug!(
183             "try_report_placeholders_trait(\
184              vid={:?}, \
185              sub_placeholder={:?}, \
186              sup_placeholder={:?}, \
187              trait_def_id={:?}, \
188              expected_substs={:?}, \
189              actual_substs={:?})",
190             vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
191         );
192
193         let mut err = self.tcx().sess.struct_span_err(
194             cause.span(&self.tcx()),
195             &format!(
196                 "implementation of `{}` is not general enough",
197                 self.tcx().item_path_str(trait_def_id),
198             ),
199         );
200
201         match cause.code {
202             ObligationCauseCode::ItemObligation(def_id) => {
203                 err.note(&format!(
204                     "Due to a where-clause on `{}`,",
205                     self.tcx().item_path_str(def_id),
206                 ));
207             }
208             _ => (),
209         }
210
211         let expected_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
212             def_id: trait_def_id,
213             substs: expected_substs,
214         });
215         let actual_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
216             def_id: trait_def_id,
217             substs: actual_substs,
218         });
219
220         // Search the expected and actual trait references to see (a)
221         // whether the sub/sup placeholders appear in them (sometimes
222         // you have a trait ref like `T: Foo<fn(&u8)>`, where the
223         // placeholder was created as part of an inner type) and (b)
224         // whether the inference variable appears. In each case,
225         // assign a counter value in each case if so.
226         let mut counter = 0;
227         let mut has_sub = None;
228         let mut has_sup = None;
229
230         let mut actual_has_vid = None;
231         let mut expected_has_vid = None;
232
233         self.tcx().for_each_free_region(&expected_trait_ref, |r| {
234             if Some(r) == sub_placeholder && has_sub.is_none() {
235                 has_sub = Some(counter);
236                 counter += 1;
237             } else if Some(r) == sup_placeholder && has_sup.is_none() {
238                 has_sup = Some(counter);
239                 counter += 1;
240             }
241
242             if Some(r) == vid && expected_has_vid.is_none() {
243                 expected_has_vid = Some(counter);
244                 counter += 1;
245             }
246         });
247
248         self.tcx().for_each_free_region(&actual_trait_ref, |r| {
249             if Some(r) == vid && actual_has_vid.is_none() {
250                 actual_has_vid = Some(counter);
251                 counter += 1;
252             }
253         });
254
255         let actual_self_ty_has_vid = self
256             .tcx()
257             .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
258
259         let expected_self_ty_has_vid = self
260             .tcx()
261             .any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
262
263         let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
264
265         debug!(
266             "try_report_placeholders_trait: actual_has_vid={:?}",
267             actual_has_vid
268         );
269         debug!(
270             "try_report_placeholders_trait: expected_has_vid={:?}",
271             expected_has_vid
272         );
273         debug!("try_report_placeholders_trait: has_sub={:?}", has_sub);
274         debug!("try_report_placeholders_trait: has_sup={:?}", has_sup);
275         debug!(
276             "try_report_placeholders_trait: actual_self_ty_has_vid={:?}",
277             actual_self_ty_has_vid
278         );
279         debug!(
280             "try_report_placeholders_trait: expected_self_ty_has_vid={:?}",
281             expected_self_ty_has_vid
282         );
283
284         self.explain_actual_impl_that_was_found(
285             &mut err,
286             sub_placeholder,
287             sup_placeholder,
288             has_sub,
289             has_sup,
290             expected_trait_ref,
291             actual_trait_ref,
292             vid,
293             expected_has_vid,
294             actual_has_vid,
295             any_self_ty_has_vid,
296         );
297
298         err.emit();
299         ErrorReported
300     }
301
302     /// Add notes with details about the expected and actual trait refs, with attention to cases
303     /// when placeholder regions are involved: either the trait or the self type containing
304     /// them needs to be mentioned the closest to the placeholders.
305     /// This makes the error messages read better, however at the cost of some complexity
306     /// due to the number of combinations we have to deal with.
307     fn explain_actual_impl_that_was_found(
308         &self,
309         err: &mut DiagnosticBuilder<'_>,
310         sub_placeholder: Option<ty::Region<'tcx>>,
311         sup_placeholder: Option<ty::Region<'tcx>>,
312         has_sub: Option<usize>,
313         has_sup: Option<usize>,
314         expected_trait_ref: ty::TraitRef<'_>,
315         actual_trait_ref: ty::TraitRef<'_>,
316         vid: Option<ty::Region<'tcx>>,
317         expected_has_vid: Option<usize>,
318         actual_has_vid: Option<usize>,
319         any_self_ty_has_vid: bool,
320     ) {
321         // The weird thing here with the `maybe_highlighting_region` calls and the
322         // the match inside is meant to be like this:
323         //
324         // - The match checks whether the given things (placeholders, etc) appear
325         //   in the types are about to print
326         // - Meanwhile, the `maybe_highlighting_region` calls set up
327         //   highlights so that, if they do appear, we will replace
328         //   them `'0` and whatever.  (This replacement takes place
329         //   inside the closure given to `maybe_highlighting_region`.)
330         //
331         // There is some duplication between the calls -- i.e., the
332         // `maybe_highlighting_region` checks if (e.g.) `has_sub` is
333         // None, an then we check again inside the closure, but this
334         // setup sort of minimized the number of calls and so form.
335
336         RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
337             RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
338                 match (has_sub, has_sup) {
339                     (Some(n1), Some(n2)) => {
340                         if any_self_ty_has_vid {
341                             err.note(&format!(
342                                 "`{}` would have to be implemented for the type `{}`, \
343                                  for any two lifetimes `'{}` and `'{}`",
344                                 expected_trait_ref,
345                                 expected_trait_ref.self_ty(),
346                                 std::cmp::min(n1, n2),
347                                 std::cmp::max(n1, n2),
348                             ));
349                         } else {
350                             err.note(&format!(
351                                 "`{}` must implement `{}`, \
352                                  for any two lifetimes `'{}` and `'{}`",
353                                 expected_trait_ref.self_ty(),
354                                 expected_trait_ref,
355                                 std::cmp::min(n1, n2),
356                                 std::cmp::max(n1, n2),
357                             ));
358                         }
359                     }
360                     (Some(n), _) | (_, Some(n)) => {
361                         if any_self_ty_has_vid {
362                             err.note(&format!(
363                                 "`{}` would have to be implemented for the type `{}`, \
364                                  for any lifetime `'{}`",
365                                 expected_trait_ref,
366                                 expected_trait_ref.self_ty(),
367                                 n,
368                             ));
369                         } else {
370                             err.note(&format!(
371                                 "`{}` must implement `{}`, for any lifetime `'{}`",
372                                 expected_trait_ref.self_ty(),
373                                 expected_trait_ref,
374                                 n,
375                             ));
376                         }
377                     }
378                     (None, None) => RegionHighlightMode::maybe_highlighting_region(
379                         vid,
380                         expected_has_vid,
381                         || {
382                             if let Some(n) = expected_has_vid {
383                                 err.note(&format!(
384                                     "`{}` would have to be implemented for the type `{}`, \
385                                      for some specific lifetime `'{}`",
386                                     expected_trait_ref,
387                                     expected_trait_ref.self_ty(),
388                                     n,
389                                 ));
390                             } else {
391                                 if any_self_ty_has_vid {
392                                     err.note(&format!(
393                                         "`{}` would have to be implemented for the type `{}`",
394                                         expected_trait_ref,
395                                         expected_trait_ref.self_ty(),
396                                     ));
397                                 } else {
398                                     err.note(&format!(
399                                         "`{}` must implement `{}`",
400                                         expected_trait_ref.self_ty(),
401                                         expected_trait_ref,
402                                     ));
403                                 }
404                             }
405                         },
406                     ),
407                 }
408             })
409         });
410
411         RegionHighlightMode::maybe_highlighting_region(
412             vid,
413             actual_has_vid,
414             || match actual_has_vid {
415                 Some(n) => {
416                     if any_self_ty_has_vid {
417                         err.note(&format!(
418                             "but `{}` is actually implemented for the type `{}`, \
419                              for some specific lifetime `'{}`",
420                             actual_trait_ref,
421                             actual_trait_ref.self_ty(),
422                             n
423                         ));
424                     } else {
425                         err.note(&format!(
426                             "but `{}` actually implements `{}`, for some specific lifetime `'{}`",
427                             actual_trait_ref.self_ty(),
428                             actual_trait_ref,
429                             n
430                         ));
431                     }
432                 }
433
434                 _ => {
435                     err.note(&format!(
436                         "but `{}` is actually implemented for the type `{}`",
437                         actual_trait_ref,
438                         actual_trait_ref.self_ty(),
439                     ));
440                 }
441             },
442         );
443     }
444 }