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 crate::hir::{FunctionRetTy, TyKind};
6 use errors::{Applicability, DiagnosticBuilder};
8 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
9 /// When given a `ConcreteFailure` for a function with arguments 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<'a>> {
12 let (span, sub, sup) = self.get_regions();
15 "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
21 // Determine whether the sub and sup consist of one named region ('a)
22 // and one anonymous (elided) region. If so, find the parameter arg
23 // where the anonymous region appears (there must always be one; we
24 // only introduced anonymous regions in parameters) as well as a
25 // version new_ty of its type where the anonymous region is replaced
26 // with the named one.//scope_def_id
27 let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub)
28 && self.tcx().is_suitable_region(sup).is_some()
29 && self.find_arg_with_region(sup, sub).is_some()
34 self.find_arg_with_region(sup, sub).unwrap(),
35 self.tcx().is_suitable_region(sup).unwrap(),
37 } else if self.is_named_region(sup) && self.tcx().is_suitable_region(sub).is_some()
38 && self.find_arg_with_region(sub, sup).is_some()
43 self.find_arg_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);
52 "try_report_named_anon_conflict: anon_arg_info = {:?}",
56 "try_report_named_anon_conflict: region_info = {:?}",
60 let (arg, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = (
63 anon_arg_info.arg_ty_span,
64 anon_arg_info.bound_region,
65 anon_arg_info.is_first,
67 region_info.is_impl_item,
72 /* not an anonymous region */
73 debug!("try_report_named_anon_conflict: not an anonymous region");
79 debug!("try_report_named_anon_conflict: impl item, bail out");
83 if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
84 if self.is_return_type_anon(scope_def_id, br, fndecl).is_some()
85 || self.is_self_anon(is_first, scope_def_id)
89 if let FunctionRetTy::Return(ty) = &fndecl.output {
90 if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.node, sub) {
91 // This is an impl Trait return that evaluates de need of 'static.
92 // We handle this case better in `static_impl_trait`.
98 let arg_pat = self.tcx().hir().original_pat_of_argument(arg);
99 let (error_var, span_label_var) = match arg_pat.simple_ident() {
100 Some(simple_ident) => (
101 format!("the type of `{}`", simple_ident),
102 format!("the type of `{}`", simple_ident),
104 None => ("parameter type".to_owned(), "type".to_owned()),
107 let mut diag = struct_span_err!(
111 "explicit lifetime required in {}",
115 diag.span_label(span, format!("lifetime `{}` required", named));
116 diag.span_suggestion(
118 &format!("add explicit lifetime `{}` to {}", named, span_label_var),
120 Applicability::Unspecified,
126 // This method returns whether the given Region is Named
127 pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
129 ty::ReStatic => true,
130 ty::ReFree(ref free_region) => match free_region.bound_region {
131 ty::BrNamed(..) => true,
134 ty::ReEarlyBound(ebr) => ebr.has_name(),