]>
Commit | Line | Data |
---|---|---|
74b04a01 | 1 | use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; |
9fa01778 | 2 | use crate::infer::{self, InferCtxt, SubregionOrigin}; |
5e7ed085 | 3 | use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; |
5869c6ff | 4 | use rustc_middle::traits::ObligationCauseCode; |
ba9703b0 XL |
5 | use rustc_middle::ty::error::TypeError; |
6 | use rustc_middle::ty::{self, Region}; | |
60c5eb7d | 7 | |
dc9dc135 | 8 | impl<'a, 'tcx> InferCtxt<'a, 'tcx> { |
5e7ed085 | 9 | pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { |
04454e1e | 10 | let mut label_or_note = |span, msg: &str| { |
f9f354fc XL |
11 | let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); |
12 | let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); | |
13 | let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span); | |
14 | if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { | |
15 | err.span_label(span, msg); | |
16 | } else if span_is_primary && expanded_sub_count == 0 { | |
17 | err.note(msg); | |
18 | } else { | |
19 | err.span_note(span, msg); | |
20 | } | |
21 | }; | |
8bb4bdeb XL |
22 | match *origin { |
23 | infer::Subtype(ref trace) => { | |
fc512014 | 24 | if let Some((expected, found)) = self.values_str(trace.values) { |
f9f354fc | 25 | label_or_note( |
60c5eb7d | 26 | trace.cause.span, |
dfeec247 | 27 | &format!("...so that the {}", trace.cause.as_requirement_str()), |
60c5eb7d XL |
28 | ); |
29 | ||
dfeec247 | 30 | err.note_expected_found(&"", expected, &"", found); |
8bb4bdeb XL |
31 | } else { |
32 | // FIXME: this really should be handled at some earlier stage. Our | |
33 | // handling of region checking when type errors are present is | |
34 | // *terrible*. | |
35 | ||
f9f354fc | 36 | label_or_note( |
dfeec247 XL |
37 | trace.cause.span, |
38 | &format!("...so that {}", trace.cause.as_requirement_str()), | |
39 | ); | |
8bb4bdeb XL |
40 | } |
41 | } | |
42 | infer::Reborrow(span) => { | |
f9f354fc | 43 | label_or_note(span, "...so that reference does not outlive borrowed content"); |
8bb4bdeb XL |
44 | } |
45 | infer::ReborrowUpvar(span, ref upvar_id) => { | |
dc9dc135 | 46 | let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); |
f9f354fc | 47 | label_or_note(span, &format!("...so that closure can access `{}`", var_name)); |
8bb4bdeb XL |
48 | } |
49 | infer::RelateObjectBound(span) => { | |
f9f354fc | 50 | label_or_note(span, "...so that it can be closed over into an object"); |
8bb4bdeb | 51 | } |
8bb4bdeb | 52 | infer::DataBorrowed(ty, span) => { |
f9f354fc | 53 | label_or_note( |
dfeec247 XL |
54 | span, |
55 | &format!( | |
56 | "...so that the type `{}` is not borrowed for too long", | |
57 | self.ty_to_string(ty) | |
58 | ), | |
59 | ); | |
8bb4bdeb XL |
60 | } |
61 | infer::ReferenceOutlivesReferent(ty, span) => { | |
f9f354fc | 62 | label_or_note( |
dfeec247 XL |
63 | span, |
64 | &format!( | |
f9f354fc | 65 | "...so that the reference type `{}` does not outlive the data it points at", |
dfeec247 XL |
66 | self.ty_to_string(ty) |
67 | ), | |
68 | ); | |
8bb4bdeb | 69 | } |
94222f64 | 70 | infer::RelateParamBound(span, t, opt_span) => { |
f9f354fc | 71 | label_or_note( |
dfeec247 XL |
72 | span, |
73 | &format!( | |
94222f64 XL |
74 | "...so that the type `{}` will meet its required lifetime bounds{}", |
75 | self.ty_to_string(t), | |
76 | if opt_span.is_some() { "..." } else { "" }, | |
dfeec247 XL |
77 | ), |
78 | ); | |
94222f64 XL |
79 | if let Some(span) = opt_span { |
80 | err.span_note(span, "...that is required by this bound"); | |
81 | } | |
8bb4bdeb XL |
82 | } |
83 | infer::RelateRegionParamBound(span) => { | |
f9f354fc | 84 | label_or_note( |
dfeec247 XL |
85 | span, |
86 | "...so that the declared lifetime parameter bounds are satisfied", | |
87 | ); | |
8bb4bdeb | 88 | } |
064997fb | 89 | infer::CompareImplItemObligation { span, .. } => { |
c295e0f8 XL |
90 | label_or_note( |
91 | span, | |
92 | "...so that the definition in impl matches the definition from the trait", | |
93 | ); | |
94 | } | |
5099ac24 FG |
95 | infer::CheckAssociatedTypeBounds { ref parent, .. } => { |
96 | self.note_region_origin(err, &parent); | |
97 | } | |
8bb4bdeb XL |
98 | } |
99 | } | |
100 | ||
dfeec247 XL |
101 | pub(super) fn report_concrete_failure( |
102 | &self, | |
dfeec247 XL |
103 | origin: SubregionOrigin<'tcx>, |
104 | sub: Region<'tcx>, | |
105 | sup: Region<'tcx>, | |
5e7ed085 | 106 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
8bb4bdeb | 107 | match origin { |
e1599b0c | 108 | infer::Subtype(box trace) => { |
8bb4bdeb | 109 | let terr = TypeError::RegionsDoesNotOutlive(sup, sub); |
ea8adc8c | 110 | let mut err = self.report_and_explain_type_error(trace, &terr); |
5099ac24 | 111 | match (*sub, *sup) { |
5869c6ff XL |
112 | (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} |
113 | (ty::RePlaceholder(_), _) => { | |
114 | note_and_explain_region( | |
115 | self.tcx, | |
116 | &mut err, | |
117 | "", | |
118 | sup, | |
119 | " doesn't meet the lifetime requirements", | |
94222f64 | 120 | None, |
5869c6ff XL |
121 | ); |
122 | } | |
123 | (_, ty::RePlaceholder(_)) => { | |
124 | note_and_explain_region( | |
125 | self.tcx, | |
126 | &mut err, | |
127 | "the required lifetime does not necessarily outlive ", | |
128 | sub, | |
129 | "", | |
94222f64 | 130 | None, |
5869c6ff XL |
131 | ); |
132 | } | |
133 | _ => { | |
94222f64 | 134 | note_and_explain_region(self.tcx, &mut err, "", sup, "...", None); |
5869c6ff XL |
135 | note_and_explain_region( |
136 | self.tcx, | |
137 | &mut err, | |
138 | "...does not necessarily outlive ", | |
139 | sub, | |
140 | "", | |
94222f64 | 141 | None, |
5869c6ff XL |
142 | ); |
143 | } | |
144 | } | |
ea8adc8c | 145 | err |
8bb4bdeb XL |
146 | } |
147 | infer::Reborrow(span) => { | |
dfeec247 XL |
148 | let mut err = struct_span_err!( |
149 | self.tcx.sess, | |
150 | span, | |
151 | E0312, | |
f9f354fc | 152 | "lifetime of reference outlives lifetime of borrowed content..." |
dfeec247 XL |
153 | ); |
154 | note_and_explain_region( | |
155 | self.tcx, | |
dfeec247 XL |
156 | &mut err, |
157 | "...the reference is valid for ", | |
158 | sub, | |
159 | "...", | |
94222f64 | 160 | None, |
dfeec247 XL |
161 | ); |
162 | note_and_explain_region( | |
163 | self.tcx, | |
dfeec247 XL |
164 | &mut err, |
165 | "...but the borrowed content is only valid for ", | |
166 | sup, | |
167 | "", | |
94222f64 | 168 | None, |
dfeec247 | 169 | ); |
8bb4bdeb XL |
170 | err |
171 | } | |
172 | infer::ReborrowUpvar(span, ref upvar_id) => { | |
dc9dc135 | 173 | let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); |
dfeec247 XL |
174 | let mut err = struct_span_err!( |
175 | self.tcx.sess, | |
176 | span, | |
177 | E0313, | |
f9f354fc | 178 | "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", |
dfeec247 XL |
179 | var_name |
180 | ); | |
181 | note_and_explain_region( | |
182 | self.tcx, | |
dfeec247 XL |
183 | &mut err, |
184 | "...the borrowed pointer is valid for ", | |
185 | sub, | |
186 | "...", | |
94222f64 | 187 | None, |
dfeec247 XL |
188 | ); |
189 | note_and_explain_region( | |
190 | self.tcx, | |
ea8adc8c XL |
191 | &mut err, |
192 | &format!("...but `{}` is only valid for ", var_name), | |
193 | sup, | |
dfeec247 | 194 | "", |
94222f64 | 195 | None, |
dfeec247 | 196 | ); |
8bb4bdeb XL |
197 | err |
198 | } | |
8bb4bdeb | 199 | infer::RelateObjectBound(span) => { |
dfeec247 XL |
200 | let mut err = struct_span_err!( |
201 | self.tcx.sess, | |
202 | span, | |
203 | E0476, | |
f9f354fc XL |
204 | "lifetime of the source pointer does not outlive lifetime bound of the \ |
205 | object type" | |
dfeec247 | 206 | ); |
94222f64 XL |
207 | note_and_explain_region( |
208 | self.tcx, | |
209 | &mut err, | |
210 | "object type is valid for ", | |
211 | sub, | |
212 | "", | |
213 | None, | |
214 | ); | |
dfeec247 XL |
215 | note_and_explain_region( |
216 | self.tcx, | |
dfeec247 XL |
217 | &mut err, |
218 | "source pointer is only valid for ", | |
219 | sup, | |
220 | "", | |
94222f64 | 221 | None, |
dfeec247 | 222 | ); |
8bb4bdeb XL |
223 | err |
224 | } | |
94222f64 | 225 | infer::RelateParamBound(span, ty, opt_span) => { |
dfeec247 XL |
226 | let mut err = struct_span_err!( |
227 | self.tcx.sess, | |
228 | span, | |
229 | E0477, | |
f9f354fc | 230 | "the type `{}` does not fulfill the required lifetime", |
dfeec247 XL |
231 | self.ty_to_string(ty) |
232 | ); | |
7cac9316 | 233 | match *sub { |
94222f64 XL |
234 | ty::ReStatic => note_and_explain_region( |
235 | self.tcx, | |
236 | &mut err, | |
237 | "type must satisfy ", | |
238 | sub, | |
239 | if opt_span.is_some() { " as required by this binding" } else { "" }, | |
240 | opt_span, | |
241 | ), | |
242 | _ => note_and_explain_region( | |
243 | self.tcx, | |
244 | &mut err, | |
245 | "type must outlive ", | |
246 | sub, | |
247 | if opt_span.is_some() { " as required by this binding" } else { "" }, | |
248 | opt_span, | |
249 | ), | |
7cac9316 | 250 | } |
8bb4bdeb XL |
251 | err |
252 | } | |
253 | infer::RelateRegionParamBound(span) => { | |
254 | let mut err = | |
255 | struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); | |
dfeec247 XL |
256 | note_and_explain_region( |
257 | self.tcx, | |
dfeec247 XL |
258 | &mut err, |
259 | "lifetime parameter instantiated with ", | |
260 | sup, | |
261 | "", | |
94222f64 | 262 | None, |
dfeec247 XL |
263 | ); |
264 | note_and_explain_region( | |
265 | self.tcx, | |
dfeec247 XL |
266 | &mut err, |
267 | "but lifetime parameter must outlive ", | |
268 | sub, | |
269 | "", | |
94222f64 | 270 | None, |
dfeec247 | 271 | ); |
8bb4bdeb XL |
272 | err |
273 | } | |
8bb4bdeb | 274 | infer::DataBorrowed(ty, span) => { |
dfeec247 XL |
275 | let mut err = struct_span_err!( |
276 | self.tcx.sess, | |
277 | span, | |
278 | E0490, | |
279 | "a value of type `{}` is borrowed for too long", | |
280 | self.ty_to_string(ty) | |
281 | ); | |
94222f64 XL |
282 | note_and_explain_region( |
283 | self.tcx, | |
284 | &mut err, | |
285 | "the type is valid for ", | |
286 | sub, | |
287 | "", | |
288 | None, | |
289 | ); | |
290 | note_and_explain_region( | |
291 | self.tcx, | |
292 | &mut err, | |
293 | "but the borrow lasts for ", | |
294 | sup, | |
295 | "", | |
296 | None, | |
297 | ); | |
8bb4bdeb XL |
298 | err |
299 | } | |
300 | infer::ReferenceOutlivesReferent(ty, span) => { | |
dfeec247 XL |
301 | let mut err = struct_span_err!( |
302 | self.tcx.sess, | |
303 | span, | |
304 | E0491, | |
74b04a01 | 305 | "in type `{}`, reference has a longer lifetime than the data it references", |
dfeec247 XL |
306 | self.ty_to_string(ty) |
307 | ); | |
94222f64 XL |
308 | note_and_explain_region( |
309 | self.tcx, | |
310 | &mut err, | |
311 | "the pointer is valid for ", | |
312 | sub, | |
313 | "", | |
314 | None, | |
315 | ); | |
dfeec247 XL |
316 | note_and_explain_region( |
317 | self.tcx, | |
dfeec247 XL |
318 | &mut err, |
319 | "but the referenced data is only valid for ", | |
320 | sup, | |
321 | "", | |
94222f64 | 322 | None, |
dfeec247 | 323 | ); |
8bb4bdeb XL |
324 | err |
325 | } | |
064997fb | 326 | infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self |
3c0e092e XL |
327 | .report_extra_impl_obligation( |
328 | span, | |
329 | impl_item_def_id, | |
330 | trait_item_def_id, | |
331 | &format!("`{}: {}`", sup, sub), | |
332 | ), | |
5099ac24 FG |
333 | infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { |
334 | let mut err = self.report_concrete_failure(*parent, sub, sup); | |
335 | ||
336 | let trait_item_span = self.tcx.def_span(trait_item_def_id); | |
5e7ed085 | 337 | let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); |
5099ac24 FG |
338 | err.span_label( |
339 | trait_item_span, | |
340 | format!("definition of `{}` from trait", item_name), | |
341 | ); | |
342 | ||
343 | let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); | |
344 | let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); | |
345 | ||
064997fb | 346 | let impl_predicates: rustc_data_structures::fx::FxHashSet<_> = |
5099ac24 FG |
347 | impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); |
348 | let clauses: Vec<_> = trait_predicates | |
349 | .predicates | |
350 | .into_iter() | |
351 | .filter(|&(pred, _)| !impl_predicates.contains(pred)) | |
352 | .map(|(pred, _)| format!("{}", pred)) | |
353 | .collect(); | |
354 | ||
355 | if !clauses.is_empty() { | |
923072b8 FG |
356 | let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); |
357 | let where_clause_span = generics.tail_span_for_predicate_suggestion(); | |
5099ac24 FG |
358 | |
359 | let suggestion = format!( | |
360 | "{} {}", | |
923072b8 | 361 | generics.add_where_or_trailing_comma(), |
5099ac24 FG |
362 | clauses.join(", "), |
363 | ); | |
364 | err.span_suggestion( | |
365 | where_clause_span, | |
366 | &format!( | |
367 | "try copying {} from the trait", | |
368 | if clauses.len() > 1 { "these clauses" } else { "this clause" } | |
369 | ), | |
370 | suggestion, | |
371 | rustc_errors::Applicability::MaybeIncorrect, | |
372 | ); | |
373 | } | |
374 | ||
375 | err | |
376 | } | |
8bb4bdeb XL |
377 | } |
378 | } | |
0731742a XL |
379 | |
380 | pub(super) fn report_placeholder_failure( | |
381 | &self, | |
0731742a XL |
382 | placeholder_origin: SubregionOrigin<'tcx>, |
383 | sub: Region<'tcx>, | |
384 | sup: Region<'tcx>, | |
5e7ed085 | 385 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
0731742a | 386 | // I can't think how to do better than this right now. -nikomatsakis |
5869c6ff | 387 | debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); |
0731742a | 388 | match placeholder_origin { |
5869c6ff XL |
389 | infer::Subtype(box ref trace) |
390 | if matches!( | |
a2a8927a | 391 | &trace.cause.code().peel_derives(), |
5869c6ff XL |
392 | ObligationCauseCode::BindingObligation(..) |
393 | ) => | |
394 | { | |
395 | // Hack to get around the borrow checker because trace.cause has an `Rc`. | |
396 | if let ObligationCauseCode::BindingObligation(_, span) = | |
a2a8927a | 397 | &trace.cause.code().peel_derives() |
5869c6ff XL |
398 | { |
399 | let span = *span; | |
400 | let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); | |
401 | err.span_note(span, "the lifetime requirement is introduced here"); | |
402 | err | |
403 | } else { | |
404 | unreachable!() | |
405 | } | |
406 | } | |
e1599b0c | 407 | infer::Subtype(box trace) => { |
0731742a | 408 | let terr = TypeError::RegionsPlaceholderMismatch; |
5869c6ff | 409 | return self.report_and_explain_type_error(trace, &terr); |
0731742a | 410 | } |
5869c6ff | 411 | _ => return self.report_concrete_failure(placeholder_origin, sub, sup), |
0731742a XL |
412 | } |
413 | } | |
8bb4bdeb | 414 | } |