]> git.proxmox.com Git - rustc.git/blob - src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc / infer / error_reporting / nice_region_error / different_lifetimes.rs
1 //! Error Reporting for Anonymous Region Lifetime Errors
2 //! where both the regions are anonymous.
3
4 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
5 use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
6 use crate::util::common::ErrorReported;
7
8 use rustc_error_codes::*;
9
10 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
11 /// Print the error message for lifetime errors when both the concerned regions are anonymous.
12 ///
13 /// Consider a case where we have
14 ///
15 /// ```no_run
16 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
17 /// x.push(y);
18 /// }
19 /// ```
20 ///
21 /// The example gives
22 ///
23 /// ```text
24 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
25 /// --- --- these references are declared with different lifetimes...
26 /// x.push(y);
27 /// ^ ...but data from `y` flows into `x` here
28 /// ```
29 ///
30 /// It has been extended for the case of structs too.
31 ///
32 /// Consider the example
33 ///
34 /// ```no_run
35 /// struct Ref<'a> { x: &'a u32 }
36 /// ```
37 ///
38 /// ```text
39 /// fn foo(mut x: Vec<Ref>, y: Ref) {
40 /// --- --- these structs are declared with different lifetimes...
41 /// x.push(y);
42 /// ^ ...but data from `y` flows into `x` here
43 /// }
44 /// ```
45 ///
46 /// It will later be extended to trait objects.
47 pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
48 let (span, sub, sup) = self.regions();
49
50 // Determine whether the sub and sup consist of both anonymous (elided) regions.
51 let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
52
53 let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
54 let scope_def_id_sup = anon_reg_sup.def_id;
55 let bregion_sup = anon_reg_sup.boundregion;
56 let scope_def_id_sub = anon_reg_sub.def_id;
57 let bregion_sub = anon_reg_sub.boundregion;
58
59 let ty_sup = self.find_anon_type(sup, &bregion_sup)?;
60
61 let ty_sub = self.find_anon_type(sub, &bregion_sub)?;
62
63 debug!(
64 "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
65 ty_sub,
66 sup,
67 bregion_sup
68 );
69 debug!(
70 "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
71 ty_sup,
72 sub,
73 bregion_sub
74 );
75
76 let (ty_sup, ty_fndecl_sup) = ty_sup;
77 let (ty_sub, ty_fndecl_sub) = ty_sub;
78
79 let AnonymousParamInfo {
80 param: anon_param_sup, ..
81 } = self.find_param_with_region(sup, sup)?;
82 let AnonymousParamInfo {
83 param: anon_param_sub, ..
84 } = self.find_param_with_region(sub, sub)?;
85
86 let sup_is_ret_type =
87 self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
88 let sub_is_ret_type =
89 self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
90
91 let span_label_var1 = match anon_param_sup.pat.simple_ident() {
92 Some(simple_ident) => format!(" from `{}`", simple_ident),
93 None => String::new(),
94 };
95
96 let span_label_var2 = match anon_param_sub.pat.simple_ident() {
97 Some(simple_ident) => format!(" into `{}`", simple_ident),
98 None => String::new(),
99 };
100
101 let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
102 (None, None) => {
103 let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
104 (
105 "this type is declared with multiple lifetimes...".to_owned(),
106 "...but data with one lifetime flows into the other here".to_owned()
107 )
108 } else {
109 (
110 "these two types are declared with different lifetimes...".to_owned(),
111 format!(
112 "...but data{} flows{} here",
113 span_label_var1,
114 span_label_var2
115 ),
116 )
117 };
118 (ty_sup.span, ty_sub.span, main_label_1, span_label_1)
119 }
120
121 (Some(ret_span), _) => (
122 ty_sub.span,
123 ret_span,
124 "this parameter and the return type are declared \
125 with different lifetimes...".to_owned()
126 ,
127 format!("...but data{} is returned here", span_label_var1),
128 ),
129 (_, Some(ret_span)) => (
130 ty_sup.span,
131 ret_span,
132 "this parameter and the return type are declared \
133 with different lifetimes...".to_owned()
134 ,
135 format!("...but data{} is returned here", span_label_var1),
136 ),
137 };
138
139
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)
144 .emit();
145 return Some(ErrorReported);
146 }
147 }