]>
Commit | Line | Data |
---|---|---|
ff7c6d11 XL |
1 | //! Error Reporting for Anonymous Region Lifetime Errors |
2 | //! where one region is named and the other is anonymous. | |
6a06907d | 3 | use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; |
9fa01778 | 4 | use crate::infer::error_reporting::nice_region_error::NiceRegionError; |
5e7ed085 | 5 | use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; |
ba9703b0 | 6 | use rustc_middle::ty; |
923072b8 | 7 | use rustc_span::symbol::kw; |
60c5eb7d | 8 | |
dc9dc135 | 9 | impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { |
e1599b0c | 10 | /// When given a `ConcreteFailure` for a function with parameters containing a named region and |
ff7c6d11 | 11 | /// an anonymous region, emit an descriptive diagnostic error. |
5e7ed085 FG |
12 | pub(super) fn try_report_named_anon_conflict( |
13 | &self, | |
14 | ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { | |
74b04a01 | 15 | let (span, sub, sup) = self.regions()?; |
ff7c6d11 XL |
16 | |
17 | debug!( | |
532ac7d7 | 18 | "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})", |
dfeec247 | 19 | sub, sup, self.error, |
ff7c6d11 XL |
20 | ); |
21 | ||
22 | // Determine whether the sub and sup consist of one named region ('a) | |
23 | // and one anonymous (elided) region. If so, find the parameter arg | |
24 | // where the anonymous region appears (there must always be one; we | |
25 | // only introduced anonymous regions in parameters) as well as a | |
26 | // version new_ty of its type where the anonymous region is replaced | |
f9f354fc XL |
27 | // with the named one. |
28 | let (named, anon, anon_param_info, region_info) = if sub.has_name() | |
9fa01778 | 29 | && self.tcx().is_suitable_region(sup).is_some() |
e1599b0c | 30 | && self.find_param_with_region(sup, sub).is_some() |
ff7c6d11 XL |
31 | { |
32 | ( | |
33 | sub, | |
34 | sup, | |
e1599b0c | 35 | self.find_param_with_region(sup, sub).unwrap(), |
9fa01778 | 36 | self.tcx().is_suitable_region(sup).unwrap(), |
ff7c6d11 | 37 | ) |
f9f354fc | 38 | } else if sup.has_name() |
dfeec247 | 39 | && self.tcx().is_suitable_region(sub).is_some() |
e1599b0c | 40 | && self.find_param_with_region(sub, sup).is_some() |
ff7c6d11 XL |
41 | { |
42 | ( | |
43 | sup, | |
44 | sub, | |
e1599b0c | 45 | self.find_param_with_region(sub, sup).unwrap(), |
9fa01778 | 46 | self.tcx().is_suitable_region(sub).unwrap(), |
ff7c6d11 XL |
47 | ) |
48 | } else { | |
49 | return None; // inapplicable | |
50 | }; | |
51 | ||
3c0e092e XL |
52 | // Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect, |
53 | // and can steer users down the wrong path. | |
5099ac24 | 54 | if named.is_static() { |
3c0e092e XL |
55 | return None; |
56 | } | |
57 | ||
ff7c6d11 | 58 | debug!("try_report_named_anon_conflict: named = {:?}", named); |
dfeec247 XL |
59 | debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info); |
60 | debug!("try_report_named_anon_conflict: region_info = {:?}", region_info); | |
ff7c6d11 | 61 | |
3c0e092e XL |
62 | let param = anon_param_info.param; |
63 | let new_ty = anon_param_info.param_ty; | |
64 | let new_ty_span = anon_param_info.param_ty_span; | |
65 | let br = anon_param_info.bound_region; | |
66 | let is_first = anon_param_info.is_first; | |
67 | let scope_def_id = region_info.def_id; | |
68 | let is_impl_item = region_info.is_impl_item; | |
69 | ||
ff7c6d11 | 70 | match br { |
487cf647 | 71 | ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) => {} |
ff7c6d11 XL |
72 | _ => { |
73 | /* not an anonymous region */ | |
74 | debug!("try_report_named_anon_conflict: not an anonymous region"); | |
75 | return None; | |
76 | } | |
77 | } | |
78 | ||
79 | if is_impl_item { | |
80 | debug!("try_report_named_anon_conflict: impl item, bail out"); | |
81 | return None; | |
82 | } | |
83 | ||
3c0e092e XL |
84 | if find_anon_type(self.tcx(), anon, &br).is_some() |
85 | && self.is_self_anon(is_first, scope_def_id) | |
86 | { | |
87 | return None; | |
ff7c6d11 XL |
88 | } |
89 | ||
e1599b0c | 90 | let (error_var, span_label_var) = match param.pat.simple_ident() { |
48663c56 | 91 | Some(simple_ident) => ( |
8faf50e0 XL |
92 | format!("the type of `{}`", simple_ident), |
93 | format!("the type of `{}`", simple_ident), | |
48663c56 XL |
94 | ), |
95 | None => ("parameter type".to_owned(), "type".to_owned()), | |
ff7c6d11 XL |
96 | }; |
97 | ||
9fa01778 XL |
98 | let mut diag = struct_span_err!( |
99 | self.tcx().sess, | |
ff7c6d11 XL |
100 | span, |
101 | E0621, | |
102 | "explicit lifetime required in {}", | |
103 | error_var | |
9fa01778 XL |
104 | ); |
105 | ||
532ac7d7 | 106 | diag.span_label(span, format!("lifetime `{}` required", named)); |
3c0e092e XL |
107 | diag.span_suggestion( |
108 | new_ty_span, | |
109 | &format!("add explicit lifetime `{}` to {}", named, span_label_var), | |
923072b8 | 110 | new_ty, |
3c0e092e XL |
111 | Applicability::Unspecified, |
112 | ); | |
9fa01778 XL |
113 | |
114 | Some(diag) | |
ff7c6d11 XL |
115 | } |
116 | } |