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::NiceRegionError;
4 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
5 use rustc_hir::intravisit::Visitor;
6 use rustc_hir::FnRetTy;
9 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
10 /// When given a `ConcreteFailure` for a function with parameters containing a named region and
11 /// an anonymous region, emit an descriptive diagnostic error.
12 pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
13 let (span, sub, sup) = self.regions()?;
16 "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
20 // Determine whether the sub and sup consist of one named region ('a)
21 // and one anonymous (elided) region. If so, find the parameter arg
22 // where the anonymous region appears (there must always be one; we
23 // only introduced anonymous regions in parameters) as well as a
24 // version new_ty of its type where the anonymous region is replaced
25 // with the named one.
26 let (named, anon, anon_param_info, region_info) = if sub.has_name()
27 && self.tcx().is_suitable_region(sup).is_some()
28 && self.find_param_with_region(sup, sub).is_some()
33 self.find_param_with_region(sup, sub).unwrap(),
34 self.tcx().is_suitable_region(sup).unwrap(),
36 } else if sup.has_name()
37 && self.tcx().is_suitable_region(sub).is_some()
38 && self.find_param_with_region(sub, sup).is_some()
43 self.find_param_with_region(sub, sup).unwrap(),
44 self.tcx().is_suitable_region(sub).unwrap(),
47 return None; // inapplicable
50 debug!("try_report_named_anon_conflict: named = {:?}", named);
51 debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
52 debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
54 let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = (
55 anon_param_info.param,
56 anon_param_info.param_ty,
57 anon_param_info.param_ty_span,
58 anon_param_info.bound_region,
59 anon_param_info.is_first,
61 region_info.is_impl_item,
66 /* not an anonymous region */
67 debug!("try_report_named_anon_conflict: not an anonymous region");
73 debug!("try_report_named_anon_conflict: impl item, bail out");
77 if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
78 if self.is_self_anon(is_first, scope_def_id) {
82 if let FnRetTy::Return(ty) = &fndecl.output {
83 let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir());
86 debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
87 if sub == &ty::ReStatic
90 .filter(|t| t.span.desugaring_kind().is_none())
94 // If the failure is due to a `'static` requirement coming from a `dyn` or
95 // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case
96 // better in `static_impl_trait`.
97 debug!("try_report_named_anon_conflict: impl Trait + 'static");
103 let (error_var, span_label_var) = match param.pat.simple_ident() {
104 Some(simple_ident) => (
105 format!("the type of `{}`", simple_ident),
106 format!("the type of `{}`", simple_ident),
108 None => ("parameter type".to_owned(), "type".to_owned()),
111 let mut diag = struct_span_err!(
115 "explicit lifetime required in {}",
119 diag.span_label(span, format!("lifetime `{}` required", named));
120 diag.span_suggestion(
122 &format!("add explicit lifetime `{}` to {}", named, span_label_var),
124 Applicability::Unspecified,