]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/note.rs
New upstream version 1.64.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};
5e7ed085 3use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
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> {
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}