1 //! Error Reporting for Anonymous Region Lifetime Errors
2 //! where both the regions are anonymous.
4 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5 use crate::infer::error_reporting::nice_region_error::util::AnonymousArgInfo;
6 use crate::util::common::ErrorReported;
8 impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
9 /// Print the error message for lifetime errors when both the concerned regions are anonymous.
11 /// Consider a case where we have
14 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
22 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
23 /// --- --- these references are declared with different lifetimes...
25 /// ^ ...but data from `y` flows into `x` here
28 /// It has been extended for the case of structs too.
30 /// Consider the example
33 /// struct Ref<'a> { x: &'a u32 }
37 /// fn foo(mut x: Vec<Ref>, y: Ref) {
38 /// --- --- these structs are declared with different lifetimes...
40 /// ^ ...but data from `y` flows into `x` here
44 /// It will later be extended to trait objects.
45 pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
46 let (span, sub, sup) = self.get_regions();
48 // Determine whether the sub and sup consist of both anonymous (elided) regions.
49 let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
51 let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
52 let scope_def_id_sup = anon_reg_sup.def_id;
53 let bregion_sup = anon_reg_sup.boundregion;
54 let scope_def_id_sub = anon_reg_sub.def_id;
55 let bregion_sub = anon_reg_sub.boundregion;
57 let ty_sup = self.find_anon_type(sup, &bregion_sup)?;
59 let ty_sub = self.find_anon_type(sub, &bregion_sub)?;
62 "try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}",
68 "try_report_anon_anon_conflict: found_arg2={:?} sub={:?} br2={:?}",
74 let (ty_sup, ty_fndecl_sup) = ty_sup;
75 let (ty_sub, ty_fndecl_sub) = ty_sub;
77 let AnonymousArgInfo {
79 } = self.find_arg_with_region(sup, sup)?;
80 let AnonymousArgInfo {
82 } = self.find_arg_with_region(sub, sub)?;
85 self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
87 self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
89 let arg_sup_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sup);
90 let span_label_var1 = match arg_sup_pat.simple_ident() {
91 Some(simple_ident) => format!(" from `{}`", simple_ident),
92 None => String::new(),
95 let arg_sub_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sub);
96 let span_label_var2 = match arg_sub_pat.simple_ident() {
97 Some(simple_ident) => format!(" into `{}`", simple_ident),
98 None => String::new(),
101 let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
103 let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
105 "this type is declared with multiple lifetimes...".to_owned(),
106 "...but data with one lifetime flows into the other here".to_owned()
110 "these two types are declared with different lifetimes...".to_owned(),
112 "...but data{} flows{} here",
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...".to_owned()
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...".to_owned()
135 format!("...but data{} is returned here", span_label_var1),
140 struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch")
141 .span_label(span_1, main_label)
142 .span_label(span_2, String::new())
143 .span_label(span, span_label)
145 return Some(ErrorReported);