]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / different_lifetimes.rs
CommitLineData
ff7c6d11
XL
1//! Error Reporting for Anonymous Region Lifetime Errors
2//! where both the regions are anonymous.
3
6a06907d 4use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
e1599b0c 5use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
dfeec247 6use crate::infer::error_reporting::nice_region_error::NiceRegionError;
ba9703b0
XL
7use crate::infer::lexical_region_resolve::RegionResolutionError;
8use crate::infer::SubregionOrigin;
ff7c6d11 9
ba9703b0 10use rustc_errors::{struct_span_err, ErrorReported};
60c5eb7d 11
dc9dc135 12impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
ff7c6d11
XL
13 /// Print the error message for lifetime errors when both the concerned regions are anonymous.
14 ///
15 /// Consider a case where we have
16 ///
17 /// ```no_run
18 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
19 /// x.push(y);
20 /// }
21 /// ```
22 ///
23 /// The example gives
24 ///
25 /// ```text
26 /// fn foo(x: &mut Vec<&u8>, y: &u8) {
27 /// --- --- these references are declared with different lifetimes...
28 /// x.push(y);
29 /// ^ ...but data from `y` flows into `x` here
30 /// ```
31 ///
32 /// It has been extended for the case of structs too.
33 ///
34 /// Consider the example
35 ///
36 /// ```no_run
37 /// struct Ref<'a> { x: &'a u32 }
38 /// ```
39 ///
40 /// ```text
41 /// fn foo(mut x: Vec<Ref>, y: Ref) {
42 /// --- --- these structs are declared with different lifetimes...
43 /// x.push(y);
44 /// ^ ...but data from `y` flows into `x` here
45 /// }
9fa01778 46 /// ```
ff7c6d11
XL
47 ///
48 /// It will later be extended to trait objects.
49 pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
74b04a01 50 let (span, sub, sup) = self.regions()?;
ff7c6d11 51
ba9703b0
XL
52 if let Some(RegionResolutionError::ConcreteFailure(
53 SubregionOrigin::ReferenceOutlivesReferent(..),
54 ..,
55 )) = self.error
56 {
57 // This error doesn't make much sense in this case.
58 return None;
59 }
60
ff7c6d11 61 // Determine whether the sub and sup consist of both anonymous (elided) regions.
9fa01778 62 let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
ff7c6d11 63
9fa01778 64 let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
ff7c6d11
XL
65 let scope_def_id_sup = anon_reg_sup.def_id;
66 let bregion_sup = anon_reg_sup.boundregion;
67 let scope_def_id_sub = anon_reg_sub.def_id;
68 let bregion_sub = anon_reg_sub.boundregion;
69
6a06907d 70 let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?;
ff7c6d11 71
6a06907d 72 let ty_sub = find_anon_type(self.tcx(), sub, &bregion_sub)?;
ff7c6d11
XL
73
74 debug!(
e1599b0c 75 "try_report_anon_anon_conflict: found_param1={:?} sup={:?} br1={:?}",
dfeec247 76 ty_sub, sup, bregion_sup
ff7c6d11
XL
77 );
78 debug!(
e1599b0c 79 "try_report_anon_anon_conflict: found_param2={:?} sub={:?} br2={:?}",
dfeec247 80 ty_sup, sub, bregion_sub
ff7c6d11
XL
81 );
82
83 let (ty_sup, ty_fndecl_sup) = ty_sup;
84 let (ty_sub, ty_fndecl_sub) = ty_sub;
85
dfeec247
XL
86 let AnonymousParamInfo { param: anon_param_sup, .. } =
87 self.find_param_with_region(sup, sup)?;
88 let AnonymousParamInfo { param: anon_param_sub, .. } =
89 self.find_param_with_region(sub, sub)?;
ff7c6d11
XL
90
91 let sup_is_ret_type =
92 self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
93 let sub_is_ret_type =
94 self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
95
e1599b0c 96 let span_label_var1 = match anon_param_sup.pat.simple_ident() {
48663c56
XL
97 Some(simple_ident) => format!(" from `{}`", simple_ident),
98 None => String::new(),
ff7c6d11
XL
99 };
100
e1599b0c 101 let span_label_var2 = match anon_param_sub.pat.simple_ident() {
48663c56
XL
102 Some(simple_ident) => format!(" into `{}`", simple_ident),
103 None => String::new(),
ff7c6d11
XL
104 };
105
29967ef6
XL
106 let (span_1, span_2, main_label, span_label, future_return_type) =
107 match (sup_is_ret_type, sub_is_ret_type) {
108 (None, None) => {
109 let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
110 (
111 "this type is declared with multiple lifetimes...".to_owned(),
112 "...but data with one lifetime flows into the other here".to_owned(),
113 )
114 } else {
115 (
116 "these two types are declared with different lifetimes...".to_owned(),
117 format!("...but data{} flows{} here", span_label_var1, span_label_var2),
118 )
119 };
120 (ty_sup.span, ty_sub.span, main_label_1, span_label_1, None)
121 }
122
123 (Some(ret_span), _) => {
124 let sup_future = self.future_return_type(scope_def_id_sup);
fc512014 125 let (return_type, action) = if sup_future.is_some() {
29967ef6
XL
126 ("returned future", "held across an await point")
127 } else {
128 ("return type", "returned")
129 };
130
ff7c6d11 131 (
29967ef6
XL
132 ty_sub.span,
133 ret_span,
134 format!(
135 "this parameter and the {} are declared with different lifetimes...",
136 return_type
137 ),
138 format!("...but data{} is {} here", span_label_var1, action),
139 sup_future,
ff7c6d11 140 )
29967ef6
XL
141 }
142 (_, Some(ret_span)) => {
143 let sub_future = self.future_return_type(scope_def_id_sub);
fc512014 144 let (return_type, action) = if sub_future.is_some() {
29967ef6
XL
145 ("returned future", "held across an await point")
146 } else {
147 ("return type", "returned")
148 };
149
ff7c6d11 150 (
29967ef6
XL
151 ty_sup.span,
152 ret_span,
153 format!(
154 "this parameter and the {} are declared with different lifetimes...",
155 return_type
156 ),
157 format!("...but data{} is {} here", span_label_var1, action),
158 sub_future,
ff7c6d11 159 )
29967ef6
XL
160 }
161 };
162
163 let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
164
165 e.span_label(span_1, main_label);
166 e.span_label(span_2, String::new());
167 e.span_label(span, span_label);
168
169 if let Some(t) = future_return_type {
170 let snip = self
171 .tcx()
172 .sess
173 .source_map()
174 .span_to_snippet(t.span)
175 .ok()
176 .and_then(|s| match (&t.kind, s.as_str()) {
177 (rustc_hir::TyKind::Tup(&[]), "") => Some("()".to_string()),
178 (_, "") => None,
179 _ => Some(s),
180 })
181 .unwrap_or("{unnamed_type}".to_string());
182
183 e.span_label(
184 t.span,
185 &format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
186 );
187 }
188 e.emit();
ba9703b0 189 Some(ErrorReported)
ff7c6d11
XL
190 }
191}