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