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