]>
Commit | Line | Data |
---|---|---|
74b04a01 | 1 | use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; |
9fa01778 | 2 | use crate::infer::{self, InferCtxt, SubregionOrigin}; |
dfeec247 | 3 | use rustc_errors::{struct_span_err, DiagnosticBuilder}; |
ba9703b0 XL |
4 | use rustc_middle::ty::error::TypeError; |
5 | use rustc_middle::ty::{self, Region}; | |
60c5eb7d | 6 | |
dc9dc135 | 7 | impl<'a, 'tcx> InferCtxt<'a, 'tcx> { |
dfeec247 XL |
8 | pub(super) fn note_region_origin( |
9 | &self, | |
10 | err: &mut DiagnosticBuilder<'_>, | |
11 | origin: &SubregionOrigin<'tcx>, | |
12 | ) { | |
f9f354fc XL |
13 | let mut label_or_note = |span, msg| { |
14 | let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); | |
15 | let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); | |
16 | let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span); | |
17 | if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { | |
18 | err.span_label(span, msg); | |
19 | } else if span_is_primary && expanded_sub_count == 0 { | |
20 | err.note(msg); | |
21 | } else { | |
22 | err.span_note(span, msg); | |
23 | } | |
24 | }; | |
8bb4bdeb XL |
25 | match *origin { |
26 | infer::Subtype(ref trace) => { | |
27 | if let Some((expected, found)) = self.values_str(&trace.values) { | |
f9f354fc | 28 | label_or_note( |
60c5eb7d | 29 | trace.cause.span, |
dfeec247 | 30 | &format!("...so that the {}", trace.cause.as_requirement_str()), |
60c5eb7d XL |
31 | ); |
32 | ||
dfeec247 | 33 | err.note_expected_found(&"", expected, &"", found); |
8bb4bdeb XL |
34 | } else { |
35 | // FIXME: this really should be handled at some earlier stage. Our | |
36 | // handling of region checking when type errors are present is | |
37 | // *terrible*. | |
38 | ||
f9f354fc | 39 | label_or_note( |
dfeec247 XL |
40 | trace.cause.span, |
41 | &format!("...so that {}", trace.cause.as_requirement_str()), | |
42 | ); | |
8bb4bdeb XL |
43 | } |
44 | } | |
45 | infer::Reborrow(span) => { | |
f9f354fc | 46 | label_or_note(span, "...so that reference does not outlive borrowed content"); |
8bb4bdeb XL |
47 | } |
48 | infer::ReborrowUpvar(span, ref upvar_id) => { | |
dc9dc135 | 49 | let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); |
f9f354fc | 50 | label_or_note(span, &format!("...so that closure can access `{}`", var_name)); |
8bb4bdeb XL |
51 | } |
52 | infer::RelateObjectBound(span) => { | |
f9f354fc | 53 | label_or_note(span, "...so that it can be closed over into an object"); |
8bb4bdeb XL |
54 | } |
55 | infer::CallReturn(span) => { | |
f9f354fc | 56 | label_or_note(span, "...so that return value is valid for the call"); |
8bb4bdeb XL |
57 | } |
58 | infer::DataBorrowed(ty, span) => { | |
f9f354fc | 59 | label_or_note( |
dfeec247 XL |
60 | span, |
61 | &format!( | |
62 | "...so that the type `{}` is not borrowed for too long", | |
63 | self.ty_to_string(ty) | |
64 | ), | |
65 | ); | |
8bb4bdeb XL |
66 | } |
67 | infer::ReferenceOutlivesReferent(ty, span) => { | |
f9f354fc | 68 | label_or_note( |
dfeec247 XL |
69 | span, |
70 | &format!( | |
f9f354fc | 71 | "...so that the reference type `{}` does not outlive the data it points at", |
dfeec247 XL |
72 | self.ty_to_string(ty) |
73 | ), | |
74 | ); | |
8bb4bdeb XL |
75 | } |
76 | infer::RelateParamBound(span, t) => { | |
f9f354fc | 77 | label_or_note( |
dfeec247 XL |
78 | span, |
79 | &format!( | |
f9f354fc | 80 | "...so that the type `{}` will meet its required lifetime bounds", |
dfeec247 XL |
81 | self.ty_to_string(t) |
82 | ), | |
83 | ); | |
8bb4bdeb XL |
84 | } |
85 | infer::RelateRegionParamBound(span) => { | |
f9f354fc | 86 | label_or_note( |
dfeec247 XL |
87 | span, |
88 | "...so that the declared lifetime parameter bounds are satisfied", | |
89 | ); | |
8bb4bdeb | 90 | } |
8bb4bdeb | 91 | infer::CompareImplMethodObligation { span, .. } => { |
f9f354fc | 92 | label_or_note( |
dfeec247 | 93 | span, |
f9f354fc | 94 | "...so that the definition in impl matches the definition from the trait", |
dfeec247 | 95 | ); |
8bb4bdeb XL |
96 | } |
97 | } | |
98 | } | |
99 | ||
dfeec247 XL |
100 | pub(super) fn report_concrete_failure( |
101 | &self, | |
dfeec247 XL |
102 | origin: SubregionOrigin<'tcx>, |
103 | sub: Region<'tcx>, | |
104 | sup: Region<'tcx>, | |
105 | ) -> DiagnosticBuilder<'tcx> { | |
8bb4bdeb | 106 | match origin { |
e1599b0c | 107 | infer::Subtype(box trace) => { |
8bb4bdeb | 108 | let terr = TypeError::RegionsDoesNotOutlive(sup, sub); |
ea8adc8c | 109 | let mut err = self.report_and_explain_type_error(trace, &terr); |
f9f354fc | 110 | note_and_explain_region(self.tcx, &mut err, "", sup, "..."); |
dfeec247 XL |
111 | note_and_explain_region( |
112 | self.tcx, | |
dfeec247 XL |
113 | &mut err, |
114 | "...does not necessarily outlive ", | |
115 | sub, | |
116 | "", | |
117 | ); | |
ea8adc8c | 118 | err |
8bb4bdeb XL |
119 | } |
120 | infer::Reborrow(span) => { | |
dfeec247 XL |
121 | let mut err = struct_span_err!( |
122 | self.tcx.sess, | |
123 | span, | |
124 | E0312, | |
f9f354fc | 125 | "lifetime of reference outlives lifetime of borrowed content..." |
dfeec247 XL |
126 | ); |
127 | note_and_explain_region( | |
128 | self.tcx, | |
dfeec247 XL |
129 | &mut err, |
130 | "...the reference is valid for ", | |
131 | sub, | |
132 | "...", | |
133 | ); | |
134 | note_and_explain_region( | |
135 | self.tcx, | |
dfeec247 XL |
136 | &mut err, |
137 | "...but the borrowed content is only valid for ", | |
138 | sup, | |
139 | "", | |
140 | ); | |
8bb4bdeb XL |
141 | err |
142 | } | |
143 | infer::ReborrowUpvar(span, ref upvar_id) => { | |
dc9dc135 | 144 | let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); |
dfeec247 XL |
145 | let mut err = struct_span_err!( |
146 | self.tcx.sess, | |
147 | span, | |
148 | E0313, | |
f9f354fc | 149 | "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", |
dfeec247 XL |
150 | var_name |
151 | ); | |
152 | note_and_explain_region( | |
153 | self.tcx, | |
dfeec247 XL |
154 | &mut err, |
155 | "...the borrowed pointer is valid for ", | |
156 | sub, | |
157 | "...", | |
158 | ); | |
159 | note_and_explain_region( | |
160 | self.tcx, | |
ea8adc8c XL |
161 | &mut err, |
162 | &format!("...but `{}` is only valid for ", var_name), | |
163 | sup, | |
dfeec247 XL |
164 | "", |
165 | ); | |
8bb4bdeb XL |
166 | err |
167 | } | |
8bb4bdeb | 168 | infer::RelateObjectBound(span) => { |
dfeec247 XL |
169 | let mut err = struct_span_err!( |
170 | self.tcx.sess, | |
171 | span, | |
172 | E0476, | |
f9f354fc XL |
173 | "lifetime of the source pointer does not outlive lifetime bound of the \ |
174 | object type" | |
dfeec247 | 175 | ); |
f9f354fc | 176 | note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, ""); |
dfeec247 XL |
177 | note_and_explain_region( |
178 | self.tcx, | |
dfeec247 XL |
179 | &mut err, |
180 | "source pointer is only valid for ", | |
181 | sup, | |
182 | "", | |
183 | ); | |
8bb4bdeb XL |
184 | err |
185 | } | |
186 | infer::RelateParamBound(span, ty) => { | |
dfeec247 XL |
187 | let mut err = struct_span_err!( |
188 | self.tcx.sess, | |
189 | span, | |
190 | E0477, | |
f9f354fc | 191 | "the type `{}` does not fulfill the required lifetime", |
dfeec247 XL |
192 | self.ty_to_string(ty) |
193 | ); | |
7cac9316 | 194 | match *sub { |
f9f354fc XL |
195 | ty::ReStatic => { |
196 | note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "") | |
197 | } | |
198 | _ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""), | |
7cac9316 | 199 | } |
8bb4bdeb XL |
200 | err |
201 | } | |
202 | infer::RelateRegionParamBound(span) => { | |
203 | let mut err = | |
204 | struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); | |
dfeec247 XL |
205 | note_and_explain_region( |
206 | self.tcx, | |
dfeec247 XL |
207 | &mut err, |
208 | "lifetime parameter instantiated with ", | |
209 | sup, | |
210 | "", | |
211 | ); | |
212 | note_and_explain_region( | |
213 | self.tcx, | |
dfeec247 XL |
214 | &mut err, |
215 | "but lifetime parameter must outlive ", | |
216 | sub, | |
217 | "", | |
218 | ); | |
8bb4bdeb XL |
219 | err |
220 | } | |
8bb4bdeb | 221 | infer::CallReturn(span) => { |
dfeec247 XL |
222 | let mut err = struct_span_err!( |
223 | self.tcx.sess, | |
224 | span, | |
225 | E0482, | |
f9f354fc | 226 | "lifetime of return value does not outlive the function call" |
dfeec247 XL |
227 | ); |
228 | note_and_explain_region( | |
229 | self.tcx, | |
dfeec247 XL |
230 | &mut err, |
231 | "the return value is only valid for ", | |
232 | sup, | |
233 | "", | |
234 | ); | |
8bb4bdeb XL |
235 | err |
236 | } | |
8bb4bdeb | 237 | infer::DataBorrowed(ty, span) => { |
dfeec247 XL |
238 | let mut err = struct_span_err!( |
239 | self.tcx.sess, | |
240 | span, | |
241 | E0490, | |
242 | "a value of type `{}` is borrowed for too long", | |
243 | self.ty_to_string(ty) | |
244 | ); | |
f9f354fc XL |
245 | note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, ""); |
246 | note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, ""); | |
8bb4bdeb XL |
247 | err |
248 | } | |
249 | infer::ReferenceOutlivesReferent(ty, span) => { | |
dfeec247 XL |
250 | let mut err = struct_span_err!( |
251 | self.tcx.sess, | |
252 | span, | |
253 | E0491, | |
74b04a01 | 254 | "in type `{}`, reference has a longer lifetime than the data it references", |
dfeec247 XL |
255 | self.ty_to_string(ty) |
256 | ); | |
f9f354fc | 257 | note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, ""); |
dfeec247 XL |
258 | note_and_explain_region( |
259 | self.tcx, | |
dfeec247 XL |
260 | &mut err, |
261 | "but the referenced data is only valid for ", | |
262 | sup, | |
263 | "", | |
264 | ); | |
8bb4bdeb XL |
265 | err |
266 | } | |
dfeec247 XL |
267 | infer::CompareImplMethodObligation { |
268 | span, | |
269 | item_name, | |
270 | impl_item_def_id, | |
271 | trait_item_def_id, | |
272 | } => self.report_extra_impl_obligation( | |
273 | span, | |
274 | item_name, | |
275 | impl_item_def_id, | |
276 | trait_item_def_id, | |
277 | &format!("`{}: {}`", sup, sub), | |
278 | ), | |
8bb4bdeb XL |
279 | } |
280 | } | |
0731742a XL |
281 | |
282 | pub(super) fn report_placeholder_failure( | |
283 | &self, | |
0731742a XL |
284 | placeholder_origin: SubregionOrigin<'tcx>, |
285 | sub: Region<'tcx>, | |
286 | sup: Region<'tcx>, | |
287 | ) -> DiagnosticBuilder<'tcx> { | |
288 | // I can't think how to do better than this right now. -nikomatsakis | |
289 | match placeholder_origin { | |
e1599b0c | 290 | infer::Subtype(box trace) => { |
0731742a XL |
291 | let terr = TypeError::RegionsPlaceholderMismatch; |
292 | self.report_and_explain_type_error(trace, &terr) | |
293 | } | |
294 | ||
f9f354fc | 295 | _ => self.report_concrete_failure(placeholder_origin, sub, sup), |
0731742a XL |
296 | } |
297 | } | |
8bb4bdeb | 298 | } |