1 //! Error Reporting for Anonymous Region Lifetime Errors
2 //! where one region is named and the other is anonymous.
3 use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
4 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
8 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
9 /// When given a `ConcreteFailure` for a function with parameters containing a named region and
10 /// an anonymous region, emit an descriptive diagnostic error.
11 pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> {
12 let (span, sub, sup) = self.regions()?;
15 "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
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
24 // with the named one.
25 let (named, anon, anon_param_info, region_info) = if sub.has_name()
26 && self.tcx().is_suitable_region(sup).is_some()
27 && self.find_param_with_region(sup, sub).is_some()
32 self.find_param_with_region(sup, sub).unwrap(),
33 self.tcx().is_suitable_region(sup).unwrap(),
35 } else if sup.has_name()
36 && self.tcx().is_suitable_region(sub).is_some()
37 && self.find_param_with_region(sub, sup).is_some()
42 self.find_param_with_region(sub, sup).unwrap(),
43 self.tcx().is_suitable_region(sub).unwrap(),
46 return None; // inapplicable
49 // Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect,
50 // and can steer users down the wrong path.
51 if named.is_static() {
55 debug!("try_report_named_anon_conflict: named = {:?}", named);
56 debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
57 debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
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;
70 /* not an anonymous region */
71 debug!("try_report_named_anon_conflict: not an anonymous region");
77 debug!("try_report_named_anon_conflict: impl item, bail out");
81 if find_anon_type(self.tcx(), anon, &br).is_some()
82 && self.is_self_anon(is_first, scope_def_id)
87 let (error_var, span_label_var) = match param.pat.simple_ident() {
88 Some(simple_ident) => (
89 format!("the type of `{}`", simple_ident),
90 format!("the type of `{}`", simple_ident),
92 None => ("parameter type".to_owned(), "type".to_owned()),
95 let mut diag = struct_span_err!(
99 "explicit lifetime required in {}",
103 diag.span_label(span, format!("lifetime `{}` required", named));
104 diag.span_suggestion(
106 &format!("add explicit lifetime `{}` to {}", named, span_label_var),
108 Applicability::Unspecified,