1 //! Error Reporting for Anonymous Region Lifetime Errors
2 //! where both the regions are anonymous.
4 use crate::infer
::error_reporting
::nice_region_error
::util
::AnonymousParamInfo
;
5 use crate::infer
::error_reporting
::nice_region_error
::NiceRegionError
;
6 use crate::infer
::lexical_region_resolve
::RegionResolutionError
;
7 use crate::infer
::SubregionOrigin
;
9 use rustc_errors
::{struct_span_err, ErrorReported}
;
11 impl<'a
, 'tcx
> NiceRegionError
<'a
, 'tcx
> {
12 /// Print the error message for lifetime errors when both the concerned regions are anonymous.
14 /// Consider a case where we have
17 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
25 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
26 /// --- --- these references are declared with different lifetimes...
28 /// ^ ...but data from `y` flows into `x` here
31 /// It has been extended for the case of structs too.
33 /// Consider the example
36 /// struct Ref<'a> { x: &'a u32 }
40 /// fn foo(mut x: Vec<Ref>, y: Ref) {
41 /// --- --- these structs are declared with different lifetimes...
43 /// ^ ...but data from `y` flows into `x` here
47 /// It will later be extended to trait objects.
48 pub(super) fn try_report_anon_anon_conflict(&self) -> Option
<ErrorReported
> {
49 let (span
, sub
, sup
) = self.regions()?
;
51 if let Some(RegionResolutionError
::ConcreteFailure(
52 SubregionOrigin
::ReferenceOutlivesReferent(..),
56 // This error doesn't make much sense in this case.
60 // Determine whether the sub and sup consist of both anonymous (elided) regions.
61 let anon_reg_sup
= self.tcx().is_suitable_region(sup
)?
;
63 let anon_reg_sub
= self.tcx().is_suitable_region(sub
)?
;
64 let scope_def_id_sup
= anon_reg_sup
.def_id
;
65 let bregion_sup
= anon_reg_sup
.boundregion
;
66 let scope_def_id_sub
= anon_reg_sub
.def_id
;
67 let bregion_sub
= anon_reg_sub
.boundregion
;
69 let ty_sup
= self.find_anon_type(sup
, &bregion_sup
)?
;
71 let ty_sub
= self.find_anon_type(sub
, &bregion_sub
)?
;
74 "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
75 ty_sub
, sup
, bregion_sup
78 "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
79 ty_sup
, sub
, bregion_sub
82 let (ty_sup
, ty_fndecl_sup
) = ty_sup
;
83 let (ty_sub
, ty_fndecl_sub
) = ty_sub
;
85 let AnonymousParamInfo { param: anon_param_sup, .. }
=
86 self.find_param_with_region(sup
, sup
)?
;
87 let AnonymousParamInfo { param: anon_param_sub, .. }
=
88 self.find_param_with_region(sub
, sub
)?
;
91 self.is_return_type_anon(scope_def_id_sup
, bregion_sup
, ty_fndecl_sup
);
93 self.is_return_type_anon(scope_def_id_sub
, bregion_sub
, ty_fndecl_sub
);
95 let span_label_var1
= match anon_param_sup
.pat
.simple_ident() {
96 Some(simple_ident
) => format
!(" from `{}`", simple_ident
),
97 None
=> String
::new(),
100 let span_label_var2
= match anon_param_sub
.pat
.simple_ident() {
101 Some(simple_ident
) => format
!(" into `{}`", simple_ident
),
102 None
=> String
::new(),
105 let (span_1
, span_2
, main_label
, span_label
) = match (sup_is_ret_type
, sub_is_ret_type
) {
107 let (main_label_1
, span_label_1
) = if ty_sup
.hir_id
== ty_sub
.hir_id
{
109 "this type is declared with multiple lifetimes...".to_owned(),
110 "...but data with one lifetime flows into the other here".to_owned(),
114 "these two types are declared with different lifetimes...".to_owned(),
115 format
!("...but data{} flows{} here", span_label_var1
, span_label_var2
),
118 (ty_sup
.span
, ty_sub
.span
, main_label_1
, span_label_1
)
121 (Some(ret_span
), _
) => (
124 "this parameter and the return type are declared \
125 with different lifetimes..."
127 format
!("...but data{} is returned here", span_label_var1
),
129 (_
, Some(ret_span
)) => (
132 "this parameter and the return type are declared \
133 with different lifetimes..."
135 format
!("...but data{} is returned here", span_label_var1
),
139 struct_span_err
!(self.tcx().sess
, span
, E0623
, "lifetime mismatch")
140 .span_label(span_1
, main_label
)
141 .span_label(span_2
, String
::new())
142 .span_label(span
, span_label
)