]>
Commit | Line | Data |
---|---|---|
9c376795 FG |
1 | use crate::errors::{ |
2 | ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes, | |
3 | TraitPlaceholderMismatch, TyOrSig, | |
4 | }; | |
9fa01778 XL |
5 | use crate::infer::error_reporting::nice_region_error::NiceRegionError; |
6 | use crate::infer::lexical_region_resolve::RegionResolutionError; | |
7 | use crate::infer::ValuePairs; | |
8 | use crate::infer::{SubregionOrigin, TypeTrace}; | |
9 | use crate::traits::{ObligationCause, ObligationCauseCode}; | |
5099ac24 | 10 | use rustc_data_structures::intern::Interned; |
9c376795 | 11 | use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; |
dfeec247 XL |
12 | use rustc_hir::def::Namespace; |
13 | use rustc_hir::def_id::DefId; | |
ba9703b0 XL |
14 | use rustc_middle::ty::error::ExpectedFound; |
15 | use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode}; | |
16 | use rustc_middle::ty::subst::SubstsRef; | |
9ffffee4 | 17 | use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt}; |
532ac7d7 | 18 | |
9c376795 FG |
19 | use std::fmt; |
20 | ||
21 | // HACK(eddyb) maybe move this in a more central location. | |
22 | #[derive(Copy, Clone)] | |
23 | pub struct Highlighted<'tcx, T> { | |
24 | tcx: TyCtxt<'tcx>, | |
25 | highlight: RegionHighlightMode<'tcx>, | |
26 | value: T, | |
27 | } | |
28 | ||
29 | impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> | |
30 | where | |
31 | T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, | |
32 | { | |
33 | fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { | |
34 | rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) | |
35 | } | |
36 | } | |
37 | ||
38 | impl<'tcx, T> Highlighted<'tcx, T> { | |
39 | fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> { | |
40 | Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) } | |
41 | } | |
42 | } | |
43 | ||
44 | impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> | |
45 | where | |
46 | T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, | |
47 | { | |
48 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
49 | let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); | |
50 | printer.region_highlight_mode = self.highlight; | |
51 | ||
52 | let s = self.value.print(printer)?.into_buffer(); | |
53 | f.write_str(&s) | |
54 | } | |
55 | } | |
0731742a | 56 | |
a2a8927a | 57 | impl<'tcx> NiceRegionError<'_, 'tcx> { |
0731742a | 58 | /// When given a `ConcreteFailure` for a function with arguments containing a named region and |
9fa01778 | 59 | /// an anonymous region, emit a descriptive diagnostic error. |
5e7ed085 FG |
60 | pub(super) fn try_report_placeholder_conflict( |
61 | &self, | |
62 | ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { | |
0731742a XL |
63 | match &self.error { |
64 | /////////////////////////////////////////////////////////////////////////// | |
65 | // NB. The ordering of cases in this match is very | |
66 | // sensitive, because we are often matching against | |
67 | // specific cases and then using an `_` to match all | |
68 | // others. | |
69 | ||
70 | /////////////////////////////////////////////////////////////////////////// | |
71 | // Check for errors from comparing trait failures -- first | |
72 | // with two placeholders, then with one. | |
73 | Some(RegionResolutionError::SubSupConflict( | |
74 | vid, | |
75 | _, | |
6a06907d | 76 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
5099ac24 | 77 | sub_placeholder @ Region(Interned(RePlaceholder(_), _)), |
0731742a | 78 | _, |
5099ac24 | 79 | sup_placeholder @ Region(Interned(RePlaceholder(_), _)), |
a2a8927a | 80 | _, |
6a06907d | 81 | )) => self.try_report_trait_placeholder_mismatch( |
9ffffee4 | 82 | Some(self.tcx().mk_re_var(*vid)), |
9fa01778 | 83 | cause, |
5099ac24 FG |
84 | Some(*sub_placeholder), |
85 | Some(*sup_placeholder), | |
6a06907d XL |
86 | values, |
87 | ), | |
0731742a XL |
88 | |
89 | Some(RegionResolutionError::SubSupConflict( | |
90 | vid, | |
91 | _, | |
6a06907d | 92 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
5099ac24 | 93 | sub_placeholder @ Region(Interned(RePlaceholder(_), _)), |
0731742a XL |
94 | _, |
95 | _, | |
a2a8927a | 96 | _, |
6a06907d | 97 | )) => self.try_report_trait_placeholder_mismatch( |
9ffffee4 | 98 | Some(self.tcx().mk_re_var(*vid)), |
9fa01778 | 99 | cause, |
5099ac24 | 100 | Some(*sub_placeholder), |
9fa01778 | 101 | None, |
6a06907d XL |
102 | values, |
103 | ), | |
0731742a XL |
104 | |
105 | Some(RegionResolutionError::SubSupConflict( | |
106 | vid, | |
107 | _, | |
6a06907d | 108 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
0731742a XL |
109 | _, |
110 | _, | |
5099ac24 | 111 | sup_placeholder @ Region(Interned(RePlaceholder(_), _)), |
a2a8927a | 112 | _, |
6a06907d | 113 | )) => self.try_report_trait_placeholder_mismatch( |
9ffffee4 | 114 | Some(self.tcx().mk_re_var(*vid)), |
9fa01778 XL |
115 | cause, |
116 | None, | |
117 | Some(*sup_placeholder), | |
6a06907d XL |
118 | values, |
119 | ), | |
9fa01778 XL |
120 | |
121 | Some(RegionResolutionError::SubSupConflict( | |
122 | vid, | |
123 | _, | |
124 | _, | |
125 | _, | |
6a06907d | 126 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
5099ac24 | 127 | sup_placeholder @ Region(Interned(RePlaceholder(_), _)), |
a2a8927a | 128 | _, |
6a06907d | 129 | )) => self.try_report_trait_placeholder_mismatch( |
9ffffee4 | 130 | Some(self.tcx().mk_re_var(*vid)), |
9fa01778 XL |
131 | cause, |
132 | None, | |
133 | Some(*sup_placeholder), | |
6a06907d XL |
134 | values, |
135 | ), | |
0731742a | 136 | |
74b04a01 XL |
137 | Some(RegionResolutionError::UpperBoundUniverseConflict( |
138 | vid, | |
139 | _, | |
140 | _, | |
6a06907d | 141 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
5099ac24 | 142 | sup_placeholder @ Region(Interned(RePlaceholder(_), _)), |
6a06907d | 143 | )) => self.try_report_trait_placeholder_mismatch( |
9ffffee4 | 144 | Some(self.tcx().mk_re_var(*vid)), |
74b04a01 XL |
145 | cause, |
146 | None, | |
147 | Some(*sup_placeholder), | |
6a06907d XL |
148 | values, |
149 | ), | |
74b04a01 | 150 | |
0731742a | 151 | Some(RegionResolutionError::ConcreteFailure( |
6a06907d | 152 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
5099ac24 FG |
153 | sub_region @ Region(Interned(RePlaceholder(_), _)), |
154 | sup_region @ Region(Interned(RePlaceholder(_), _)), | |
6a06907d | 155 | )) => self.try_report_trait_placeholder_mismatch( |
9fa01778 XL |
156 | None, |
157 | cause, | |
158 | Some(*sub_region), | |
159 | Some(*sup_region), | |
6a06907d XL |
160 | values, |
161 | ), | |
0731742a XL |
162 | |
163 | Some(RegionResolutionError::ConcreteFailure( | |
6a06907d | 164 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
5099ac24 | 165 | sub_region @ Region(Interned(RePlaceholder(_), _)), |
0731742a | 166 | sup_region, |
6a06907d | 167 | )) => self.try_report_trait_placeholder_mismatch( |
5099ac24 | 168 | (!sup_region.has_name()).then_some(*sup_region), |
9fa01778 | 169 | cause, |
5099ac24 | 170 | Some(*sub_region), |
9fa01778 | 171 | None, |
6a06907d XL |
172 | values, |
173 | ), | |
0731742a XL |
174 | |
175 | Some(RegionResolutionError::ConcreteFailure( | |
6a06907d | 176 | SubregionOrigin::Subtype(box TypeTrace { cause, values }), |
0731742a | 177 | sub_region, |
5099ac24 | 178 | sup_region @ Region(Interned(RePlaceholder(_), _)), |
6a06907d | 179 | )) => self.try_report_trait_placeholder_mismatch( |
5099ac24 | 180 | (!sub_region.has_name()).then_some(*sub_region), |
9fa01778 XL |
181 | cause, |
182 | None, | |
5099ac24 | 183 | Some(*sup_region), |
6a06907d XL |
184 | values, |
185 | ), | |
0731742a XL |
186 | |
187 | _ => None, | |
188 | } | |
189 | } | |
190 | ||
6a06907d XL |
191 | fn try_report_trait_placeholder_mismatch( |
192 | &self, | |
5099ac24 | 193 | vid: Option<Region<'tcx>>, |
6a06907d | 194 | cause: &ObligationCause<'tcx>, |
5099ac24 FG |
195 | sub_placeholder: Option<Region<'tcx>>, |
196 | sup_placeholder: Option<Region<'tcx>>, | |
6a06907d | 197 | value_pairs: &ValuePairs<'tcx>, |
5e7ed085 | 198 | ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { |
6a06907d XL |
199 | let (expected_substs, found_substs, trait_def_id) = match value_pairs { |
200 | ValuePairs::TraitRefs(ExpectedFound { expected, found }) | |
201 | if expected.def_id == found.def_id => | |
202 | { | |
203 | (expected.substs, found.substs, expected.def_id) | |
204 | } | |
205 | ValuePairs::PolyTraitRefs(ExpectedFound { expected, found }) | |
206 | if expected.def_id() == found.def_id() => | |
207 | { | |
208 | // It's possible that the placeholders come from a binder | |
209 | // outside of this value pair. Use `no_bound_vars` as a | |
210 | // simple heuristic for that. | |
211 | (expected.no_bound_vars()?.substs, found.no_bound_vars()?.substs, expected.def_id()) | |
212 | } | |
213 | _ => return None, | |
214 | }; | |
215 | ||
216 | Some(self.report_trait_placeholder_mismatch( | |
217 | vid, | |
218 | cause, | |
219 | sub_placeholder, | |
220 | sup_placeholder, | |
221 | trait_def_id, | |
222 | expected_substs, | |
223 | found_substs, | |
224 | )) | |
225 | } | |
226 | ||
0731742a XL |
227 | // error[E0308]: implementation of `Foo` does not apply to enough lifetimes |
228 | // --> /home/nmatsakis/tmp/foo.rs:12:5 | |
229 | // | | |
230 | // 12 | all::<&'static u32>(); | |
231 | // | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch | |
232 | // | | |
233 | // = note: Due to a where-clause on the function `all`, | |
234 | // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`. | |
235 | // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. | |
6a06907d XL |
236 | #[instrument(level = "debug", skip(self))] |
237 | fn report_trait_placeholder_mismatch( | |
0731742a | 238 | &self, |
5099ac24 | 239 | vid: Option<Region<'tcx>>, |
0731742a | 240 | cause: &ObligationCause<'tcx>, |
5099ac24 FG |
241 | sub_placeholder: Option<Region<'tcx>>, |
242 | sup_placeholder: Option<Region<'tcx>>, | |
0731742a | 243 | trait_def_id: DefId, |
532ac7d7 XL |
244 | expected_substs: SubstsRef<'tcx>, |
245 | actual_substs: SubstsRef<'tcx>, | |
5e7ed085 | 246 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
064997fb | 247 | let span = cause.span(); |
0731742a | 248 | |
9c376795 FG |
249 | let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = |
250 | if let ObligationCauseCode::ItemObligation(def_id) | |
251 | | ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code() | |
252 | { | |
253 | ( | |
254 | true, | |
255 | Some(span), | |
256 | Some(self.tcx().def_span(def_id)), | |
257 | None, | |
258 | self.tcx().def_path_str(def_id), | |
259 | ) | |
260 | } else { | |
261 | (false, None, None, Some(span), String::new()) | |
262 | }; | |
263 | ||
49aad941 FG |
264 | let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new( |
265 | self.cx.tcx, | |
266 | trait_def_id, | |
267 | expected_substs, | |
268 | )); | |
269 | let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new( | |
270 | self.cx.tcx, | |
271 | trait_def_id, | |
272 | actual_substs, | |
273 | )); | |
0731742a XL |
274 | |
275 | // Search the expected and actual trait references to see (a) | |
276 | // whether the sub/sup placeholders appear in them (sometimes | |
277 | // you have a trait ref like `T: Foo<fn(&u8)>`, where the | |
278 | // placeholder was created as part of an inner type) and (b) | |
279 | // whether the inference variable appears. In each case, | |
280 | // assign a counter value in each case if so. | |
281 | let mut counter = 0; | |
282 | let mut has_sub = None; | |
283 | let mut has_sup = None; | |
0731742a | 284 | |
9fa01778 XL |
285 | let mut actual_has_vid = None; |
286 | let mut expected_has_vid = None; | |
287 | ||
288 | self.tcx().for_each_free_region(&expected_trait_ref, |r| { | |
0731742a XL |
289 | if Some(r) == sub_placeholder && has_sub.is_none() { |
290 | has_sub = Some(counter); | |
291 | counter += 1; | |
292 | } else if Some(r) == sup_placeholder && has_sup.is_none() { | |
293 | has_sup = Some(counter); | |
294 | counter += 1; | |
295 | } | |
9fa01778 XL |
296 | |
297 | if Some(r) == vid && expected_has_vid.is_none() { | |
298 | expected_has_vid = Some(counter); | |
299 | counter += 1; | |
300 | } | |
0731742a XL |
301 | }); |
302 | ||
9fa01778 XL |
303 | self.tcx().for_each_free_region(&actual_trait_ref, |r| { |
304 | if Some(r) == vid && actual_has_vid.is_none() { | |
305 | actual_has_vid = Some(counter); | |
0731742a XL |
306 | counter += 1; |
307 | } | |
308 | }); | |
309 | ||
dfeec247 XL |
310 | let actual_self_ty_has_vid = |
311 | self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); | |
0731742a | 312 | |
dfeec247 XL |
313 | let expected_self_ty_has_vid = |
314 | self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid); | |
9fa01778 XL |
315 | |
316 | let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid; | |
317 | ||
9fa01778 | 318 | debug!( |
6a06907d XL |
319 | ?actual_has_vid, |
320 | ?expected_has_vid, | |
321 | ?has_sub, | |
322 | ?has_sup, | |
323 | ?actual_self_ty_has_vid, | |
324 | ?expected_self_ty_has_vid, | |
9fa01778 XL |
325 | ); |
326 | ||
9c376795 | 327 | let actual_impl_expl_notes = self.explain_actual_impl_that_was_found( |
9fa01778 XL |
328 | sub_placeholder, |
329 | sup_placeholder, | |
330 | has_sub, | |
331 | has_sup, | |
332 | expected_trait_ref, | |
333 | actual_trait_ref, | |
334 | vid, | |
335 | expected_has_vid, | |
336 | actual_has_vid, | |
337 | any_self_ty_has_vid, | |
e1599b0c | 338 | leading_ellipsis, |
9fa01778 XL |
339 | ); |
340 | ||
9c376795 FG |
341 | self.tcx().sess.create_err(TraitPlaceholderMismatch { |
342 | span, | |
343 | satisfy_span, | |
344 | where_span, | |
345 | dup_span, | |
346 | def_id, | |
347 | trait_def_id: self.tcx().def_path_str(trait_def_id), | |
348 | actual_impl_expl_notes, | |
349 | }) | |
9fa01778 XL |
350 | } |
351 | ||
352 | /// Add notes with details about the expected and actual trait refs, with attention to cases | |
353 | /// when placeholder regions are involved: either the trait or the self type containing | |
354 | /// them needs to be mentioned the closest to the placeholders. | |
355 | /// This makes the error messages read better, however at the cost of some complexity | |
356 | /// due to the number of combinations we have to deal with. | |
357 | fn explain_actual_impl_that_was_found( | |
358 | &self, | |
5099ac24 FG |
359 | sub_placeholder: Option<Region<'tcx>>, |
360 | sup_placeholder: Option<Region<'tcx>>, | |
9fa01778 XL |
361 | has_sub: Option<usize>, |
362 | has_sup: Option<usize>, | |
532ac7d7 XL |
363 | expected_trait_ref: ty::TraitRef<'tcx>, |
364 | actual_trait_ref: ty::TraitRef<'tcx>, | |
5099ac24 | 365 | vid: Option<Region<'tcx>>, |
9fa01778 XL |
366 | expected_has_vid: Option<usize>, |
367 | actual_has_vid: Option<usize>, | |
368 | any_self_ty_has_vid: bool, | |
e1599b0c | 369 | leading_ellipsis: bool, |
9c376795 | 370 | ) -> Vec<ActualImplExplNotes<'tcx>> { |
9fa01778 XL |
371 | // The weird thing here with the `maybe_highlighting_region` calls and the |
372 | // the match inside is meant to be like this: | |
373 | // | |
374 | // - The match checks whether the given things (placeholders, etc) appear | |
375 | // in the types are about to print | |
376 | // - Meanwhile, the `maybe_highlighting_region` calls set up | |
377 | // highlights so that, if they do appear, we will replace | |
9c376795 | 378 | // them `'0` and whatever. (This replacement takes place |
9fa01778 XL |
379 | // inside the closure given to `maybe_highlighting_region`.) |
380 | // | |
381 | // There is some duplication between the calls -- i.e., the | |
382 | // `maybe_highlighting_region` checks if (e.g.) `has_sub` is | |
383 | // None, an then we check again inside the closure, but this | |
384 | // setup sort of minimized the number of calls and so form. | |
385 | ||
532ac7d7 XL |
386 | let highlight_trait_ref = |trait_ref| Highlighted { |
387 | tcx: self.tcx(), | |
5099ac24 | 388 | highlight: RegionHighlightMode::new(self.tcx()), |
532ac7d7 XL |
389 | value: trait_ref, |
390 | }; | |
9fa01778 | 391 | |
6a06907d XL |
392 | let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty(); |
393 | ||
532ac7d7 XL |
394 | let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref); |
395 | expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub); | |
396 | expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup); | |
0731742a | 397 | |
9c376795 FG |
398 | let passive_voice = match (has_sub, has_sup) { |
399 | (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid, | |
400 | (None, None) => { | |
401 | expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid); | |
402 | match expected_has_vid { | |
403 | Some(_) => true, | |
404 | None => any_self_ty_has_vid, | |
6a06907d | 405 | } |
9c376795 FG |
406 | } |
407 | }; | |
408 | ||
409 | let (kind, ty_or_sig, trait_path) = if same_self_type { | |
410 | let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); | |
411 | self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); | |
412 | ||
413 | if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) | |
414 | { | |
415 | let closure_sig = self_ty.map(|closure| { | |
416 | if let ty::Closure(_, substs) = closure.kind() { | |
417 | self.tcx().signature_unclosure( | |
418 | substs.as_closure().sig(), | |
419 | rustc_hir::Unsafety::Normal, | |
420 | ) | |
421 | } else { | |
422 | bug!("type is not longer closure"); | |
423 | } | |
424 | }); | |
425 | ( | |
426 | ActualImplExpectedKind::Signature, | |
427 | TyOrSig::ClosureSig(closure_sig), | |
60c5eb7d | 428 | expected_trait_ref.map(|tr| tr.print_only_trait_path()), |
532ac7d7 XL |
429 | ) |
430 | } else { | |
9c376795 FG |
431 | ( |
432 | ActualImplExpectedKind::Other, | |
433 | TyOrSig::Ty(self_ty), | |
60c5eb7d | 434 | expected_trait_ref.map(|tr| tr.print_only_trait_path()), |
532ac7d7 | 435 | ) |
9c376795 FG |
436 | } |
437 | } else if passive_voice { | |
438 | ( | |
439 | ActualImplExpectedKind::Passive, | |
440 | TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())), | |
441 | expected_trait_ref.map(|tr| tr.print_only_trait_path()), | |
442 | ) | |
443 | } else { | |
444 | ( | |
445 | ActualImplExpectedKind::Other, | |
446 | TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())), | |
447 | expected_trait_ref.map(|tr| tr.print_only_trait_path()), | |
448 | ) | |
449 | }; | |
532ac7d7 | 450 | |
9c376795 FG |
451 | let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) { |
452 | (Some(n1), Some(n2)) => { | |
453 | (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2)) | |
454 | } | |
455 | (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0), | |
456 | (None, None) => { | |
457 | if let Some(n) = expected_has_vid { | |
458 | (ActualImplExpectedLifetimeKind::Some, n, 0) | |
459 | } else { | |
460 | (ActualImplExpectedLifetimeKind::Nothing, 0, 0) | |
532ac7d7 | 461 | } |
532ac7d7 | 462 | } |
9c376795 | 463 | }; |
532ac7d7 | 464 | |
9c376795 FG |
465 | let note_1 = ActualImplExplNotes::new_expected( |
466 | kind, | |
467 | lt_kind, | |
468 | leading_ellipsis, | |
469 | ty_or_sig, | |
470 | trait_path, | |
471 | lifetime_1, | |
472 | lifetime_2, | |
473 | ); | |
532ac7d7 XL |
474 | |
475 | let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); | |
476 | actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid); | |
532ac7d7 | 477 | |
9c376795 FG |
478 | let passive_voice = match actual_has_vid { |
479 | Some(_) => any_self_ty_has_vid, | |
480 | None => true, | |
481 | }; | |
532ac7d7 | 482 | |
9c376795 FG |
483 | let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()); |
484 | let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); | |
485 | let has_lifetime = actual_has_vid.is_some(); | |
486 | let lifetime = actual_has_vid.unwrap_or_default(); | |
487 | ||
488 | let note_2 = if same_self_type { | |
489 | ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime } | |
490 | } else if passive_voice { | |
491 | ActualImplExplNotes::ButActuallyImplementedForTy { | |
492 | trait_path, | |
493 | ty, | |
494 | has_lifetime, | |
495 | lifetime, | |
532ac7d7 | 496 | } |
9c376795 FG |
497 | } else { |
498 | ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime } | |
499 | }; | |
532ac7d7 | 500 | |
9c376795 | 501 | vec![note_1, note_2] |
0731742a XL |
502 | } |
503 | } |