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, ErrorGuaranteed}
;
7 use rustc_span
::symbol
::kw
;
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(
14 ) -> Option
<DiagnosticBuilder
<'tcx
, ErrorGuaranteed
>> {
15 let (span
, sub
, sup
) = self.regions()?
;
18 "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
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
27 // with the named one.
28 let (named
, anon
, anon_param_info
, region_info
) = if sub
.has_name()
29 && self.tcx().is_suitable_region(sup
).is_some()
30 && self.find_param_with_region(sup
, sub
).is_some()
35 self.find_param_with_region(sup
, sub
).unwrap(),
36 self.tcx().is_suitable_region(sup
).unwrap(),
38 } else if sup
.has_name()
39 && self.tcx().is_suitable_region(sub
).is_some()
40 && self.find_param_with_region(sub
, sup
).is_some()
45 self.find_param_with_region(sub
, sup
).unwrap(),
46 self.tcx().is_suitable_region(sub
).unwrap(),
49 return None
; // inapplicable
52 // Suggesting to add a `'static` lifetime to a parameter is nearly always incorrect,
53 // and can steer users down the wrong path.
54 if named
.is_static() {
58 debug
!("try_report_named_anon_conflict: named = {:?}", named
);
59 debug
!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info
);
60 debug
!("try_report_named_anon_conflict: region_info = {:?}", region_info
);
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
;
71 ty
::BrNamed(_
, kw
::UnderscoreLifetime
) | ty
::BrAnon(_
) => {}
73 /* not an anonymous region */
74 debug
!("try_report_named_anon_conflict: not an anonymous region");
80 debug
!("try_report_named_anon_conflict: impl item, bail out");
84 if find_anon_type(self.tcx(), anon
, &br
).is_some()
85 && self.is_self_anon(is_first
, scope_def_id
)
90 let (error_var
, span_label_var
) = match param
.pat
.simple_ident() {
91 Some(simple_ident
) => (
92 format
!("the type of `{}`", simple_ident
),
93 format
!("the type of `{}`", simple_ident
),
95 None
=> ("parameter type".to_owned(), "type".to_owned()),
98 let mut diag
= struct_span_err
!(
102 "explicit lifetime required in {}",
106 diag
.span_label(span
, format
!("lifetime `{}` required", named
));
107 diag
.span_suggestion(
109 &format
!("add explicit lifetime `{}` to {}", named
, span_label_var
),
111 Applicability
::Unspecified
,