]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/error_reporting/note.rs
Stabilize File::options()
[rust.git] / compiler / rustc_infer / src / infer / error_reporting / note.rs
1 use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
2 use crate::infer::{self, InferCtxt, SubregionOrigin};
3 use rustc_errors::{struct_span_err, DiagnosticBuilder};
4 use rustc_middle::traits::ObligationCauseCode;
5 use rustc_middle::ty::error::TypeError;
6 use rustc_middle::ty::{self, Region};
7
8 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9     pub(super) fn note_region_origin(
10         &self,
11         err: &mut DiagnosticBuilder<'_>,
12         origin: &SubregionOrigin<'tcx>,
13     ) {
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         };
26         match *origin {
27             infer::Subtype(ref trace) => {
28                 if let Some((expected, found)) = self.values_str(trace.values) {
29                     label_or_note(
30                         trace.cause.span,
31                         &format!("...so that the {}", trace.cause.as_requirement_str()),
32                     );
33
34                     err.note_expected_found(&"", expected, &"", found);
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
40                     label_or_note(
41                         trace.cause.span,
42                         &format!("...so that {}", trace.cause.as_requirement_str()),
43                     );
44                 }
45             }
46             infer::Reborrow(span) => {
47                 label_or_note(span, "...so that reference does not outlive borrowed content");
48             }
49             infer::ReborrowUpvar(span, ref upvar_id) => {
50                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
51                 label_or_note(span, &format!("...so that closure can access `{}`", var_name));
52             }
53             infer::RelateObjectBound(span) => {
54                 label_or_note(span, "...so that it can be closed over into an object");
55             }
56             infer::DataBorrowed(ty, span) => {
57                 label_or_note(
58                     span,
59                     &format!(
60                         "...so that the type `{}` is not borrowed for too long",
61                         self.ty_to_string(ty)
62                     ),
63                 );
64             }
65             infer::ReferenceOutlivesReferent(ty, span) => {
66                 label_or_note(
67                     span,
68                     &format!(
69                         "...so that the reference type `{}` does not outlive the data it points at",
70                         self.ty_to_string(ty)
71                     ),
72                 );
73             }
74             infer::RelateParamBound(span, t, opt_span) => {
75                 label_or_note(
76                     span,
77                     &format!(
78                         "...so that the type `{}` will meet its required lifetime bounds{}",
79                         self.ty_to_string(t),
80                         if opt_span.is_some() { "..." } else { "" },
81                     ),
82                 );
83                 if let Some(span) = opt_span {
84                     err.span_note(span, "...that is required by this bound");
85                 }
86             }
87             infer::RelateRegionParamBound(span) => {
88                 label_or_note(
89                     span,
90                     "...so that the declared lifetime parameter bounds are satisfied",
91                 );
92             }
93             infer::CompareImplMethodObligation { span, .. } => {
94                 label_or_note(
95                     span,
96                     "...so that the definition in impl matches the definition from the trait",
97                 );
98             }
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             }
105         }
106     }
107
108     pub(super) fn report_concrete_failure(
109         &self,
110         origin: SubregionOrigin<'tcx>,
111         sub: Region<'tcx>,
112         sup: Region<'tcx>,
113     ) -> DiagnosticBuilder<'tcx> {
114         match origin {
115             infer::Subtype(box trace) => {
116                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
117                 let mut err = self.report_and_explain_type_error(trace, &terr);
118                 match (sub, sup) {
119                     (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
120                     (ty::RePlaceholder(_), _) => {
121                         note_and_explain_region(
122                             self.tcx,
123                             &mut err,
124                             "",
125                             sup,
126                             " doesn't meet the lifetime requirements",
127                             None,
128                         );
129                     }
130                     (_, ty::RePlaceholder(_)) => {
131                         note_and_explain_region(
132                             self.tcx,
133                             &mut err,
134                             "the required lifetime does not necessarily outlive ",
135                             sub,
136                             "",
137                             None,
138                         );
139                     }
140                     _ => {
141                         note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
142                         note_and_explain_region(
143                             self.tcx,
144                             &mut err,
145                             "...does not necessarily outlive ",
146                             sub,
147                             "",
148                             None,
149                         );
150                     }
151                 }
152                 err
153             }
154             infer::Reborrow(span) => {
155                 let mut err = struct_span_err!(
156                     self.tcx.sess,
157                     span,
158                     E0312,
159                     "lifetime of reference outlives lifetime of borrowed content..."
160                 );
161                 note_and_explain_region(
162                     self.tcx,
163                     &mut err,
164                     "...the reference is valid for ",
165                     sub,
166                     "...",
167                     None,
168                 );
169                 note_and_explain_region(
170                     self.tcx,
171                     &mut err,
172                     "...but the borrowed content is only valid for ",
173                     sup,
174                     "",
175                     None,
176                 );
177                 err
178             }
179             infer::ReborrowUpvar(span, ref upvar_id) => {
180                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
181                 let mut err = struct_span_err!(
182                     self.tcx.sess,
183                     span,
184                     E0313,
185                     "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
186                     var_name
187                 );
188                 note_and_explain_region(
189                     self.tcx,
190                     &mut err,
191                     "...the borrowed pointer is valid for ",
192                     sub,
193                     "...",
194                     None,
195                 );
196                 note_and_explain_region(
197                     self.tcx,
198                     &mut err,
199                     &format!("...but `{}` is only valid for ", var_name),
200                     sup,
201                     "",
202                     None,
203                 );
204                 err
205             }
206             infer::RelateObjectBound(span) => {
207                 let mut err = struct_span_err!(
208                     self.tcx.sess,
209                     span,
210                     E0476,
211                     "lifetime of the source pointer does not outlive lifetime bound of the \
212                      object type"
213                 );
214                 note_and_explain_region(
215                     self.tcx,
216                     &mut err,
217                     "object type is valid for ",
218                     sub,
219                     "",
220                     None,
221                 );
222                 note_and_explain_region(
223                     self.tcx,
224                     &mut err,
225                     "source pointer is only valid for ",
226                     sup,
227                     "",
228                     None,
229                 );
230                 err
231             }
232             infer::RelateParamBound(span, ty, opt_span) => {
233                 let mut err = struct_span_err!(
234                     self.tcx.sess,
235                     span,
236                     E0477,
237                     "the type `{}` does not fulfill the required lifetime",
238                     self.ty_to_string(ty)
239                 );
240                 match *sub {
241                     ty::ReStatic => note_and_explain_region(
242                         self.tcx,
243                         &mut err,
244                         "type must satisfy ",
245                         sub,
246                         if opt_span.is_some() { " as required by this binding" } else { "" },
247                         opt_span,
248                     ),
249                     _ => note_and_explain_region(
250                         self.tcx,
251                         &mut err,
252                         "type must outlive ",
253                         sub,
254                         if opt_span.is_some() { " as required by this binding" } else { "" },
255                         opt_span,
256                     ),
257                 }
258                 err
259             }
260             infer::RelateRegionParamBound(span) => {
261                 let mut err =
262                     struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
263                 note_and_explain_region(
264                     self.tcx,
265                     &mut err,
266                     "lifetime parameter instantiated with ",
267                     sup,
268                     "",
269                     None,
270                 );
271                 note_and_explain_region(
272                     self.tcx,
273                     &mut err,
274                     "but lifetime parameter must outlive ",
275                     sub,
276                     "",
277                     None,
278                 );
279                 err
280             }
281             infer::DataBorrowed(ty, span) => {
282                 let mut err = struct_span_err!(
283                     self.tcx.sess,
284                     span,
285                     E0490,
286                     "a value of type `{}` is borrowed for too long",
287                     self.ty_to_string(ty)
288                 );
289                 note_and_explain_region(
290                     self.tcx,
291                     &mut err,
292                     "the type is valid for ",
293                     sub,
294                     "",
295                     None,
296                 );
297                 note_and_explain_region(
298                     self.tcx,
299                     &mut err,
300                     "but the borrow lasts for ",
301                     sup,
302                     "",
303                     None,
304                 );
305                 err
306             }
307             infer::ReferenceOutlivesReferent(ty, span) => {
308                 let mut err = struct_span_err!(
309                     self.tcx.sess,
310                     span,
311                     E0491,
312                     "in type `{}`, reference has a longer lifetime than the data it references",
313                     self.ty_to_string(ty)
314                 );
315                 note_and_explain_region(
316                     self.tcx,
317                     &mut err,
318                     "the pointer is valid for ",
319                     sub,
320                     "",
321                     None,
322                 );
323                 note_and_explain_region(
324                     self.tcx,
325                     &mut err,
326                     "but the referenced data is only valid for ",
327                     sup,
328                     "",
329                     None,
330                 );
331                 err
332             }
333             infer::CompareImplMethodObligation {
334                 span,
335                 item_name,
336                 impl_item_def_id,
337                 trait_item_def_id,
338             } => self.report_extra_impl_obligation(
339                 span,
340                 item_name,
341                 impl_item_def_id,
342                 trait_item_def_id,
343                 &format!("`{}: {}`", sup, sub),
344             ),
345             infer::CompareImplTypeObligation {
346                 span,
347                 item_name,
348                 impl_item_def_id,
349                 trait_item_def_id,
350             } => self.report_extra_impl_obligation(
351                 span,
352                 item_name,
353                 impl_item_def_id,
354                 trait_item_def_id,
355                 &format!("`{}: {}`", sup, sub),
356             ),
357         }
358     }
359
360     pub(super) fn report_placeholder_failure(
361         &self,
362         placeholder_origin: SubregionOrigin<'tcx>,
363         sub: Region<'tcx>,
364         sup: Region<'tcx>,
365     ) -> DiagnosticBuilder<'tcx> {
366         // I can't think how to do better than this right now. -nikomatsakis
367         debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
368         match placeholder_origin {
369             infer::Subtype(box ref trace)
370                 if matches!(
371                     &trace.cause.code.peel_derives(),
372                     ObligationCauseCode::BindingObligation(..)
373                 ) =>
374             {
375                 // Hack to get around the borrow checker because trace.cause has an `Rc`.
376                 if let ObligationCauseCode::BindingObligation(_, span) =
377                     &trace.cause.code.peel_derives()
378                 {
379                     let span = *span;
380                     let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
381                     err.span_note(span, "the lifetime requirement is introduced here");
382                     err
383                 } else {
384                     unreachable!()
385                 }
386             }
387             infer::Subtype(box trace) => {
388                 let terr = TypeError::RegionsPlaceholderMismatch;
389                 return self.report_and_explain_type_error(trace, &terr);
390             }
391             _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
392         }
393     }
394 }