]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/error_reporting/note.rs
Rollup merge of #80935 - pierwill:rustc_middle-levelandsource, r=petrochenkov
[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::CallReturn(span) => {
57                 label_or_note(span, "...so that return value is valid for the call");
58             }
59             infer::DataBorrowed(ty, span) => {
60                 label_or_note(
61                     span,
62                     &format!(
63                         "...so that the type `{}` is not borrowed for too long",
64                         self.ty_to_string(ty)
65                     ),
66                 );
67             }
68             infer::ReferenceOutlivesReferent(ty, span) => {
69                 label_or_note(
70                     span,
71                     &format!(
72                         "...so that the reference type `{}` does not outlive the data it points at",
73                         self.ty_to_string(ty)
74                     ),
75                 );
76             }
77             infer::RelateParamBound(span, t) => {
78                 label_or_note(
79                     span,
80                     &format!(
81                         "...so that the type `{}` will meet its required lifetime bounds",
82                         self.ty_to_string(t)
83                     ),
84                 );
85             }
86             infer::RelateRegionParamBound(span) => {
87                 label_or_note(
88                     span,
89                     "...so that the declared lifetime parameter bounds are satisfied",
90                 );
91             }
92             infer::CompareImplMethodObligation { span, .. } => {
93                 label_or_note(
94                     span,
95                     "...so that the definition in impl matches the definition from the trait",
96                 );
97             }
98         }
99     }
100
101     pub(super) fn report_concrete_failure(
102         &self,
103         origin: SubregionOrigin<'tcx>,
104         sub: Region<'tcx>,
105         sup: Region<'tcx>,
106     ) -> DiagnosticBuilder<'tcx> {
107         match origin {
108             infer::Subtype(box trace) => {
109                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
110                 let mut err = self.report_and_explain_type_error(trace, &terr);
111                 match (sub, sup) {
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",
120                         );
121                     }
122                     (_, ty::RePlaceholder(_)) => {
123                         note_and_explain_region(
124                             self.tcx,
125                             &mut err,
126                             "the required lifetime does not necessarily outlive ",
127                             sub,
128                             "",
129                         );
130                     }
131                     _ => {
132                         note_and_explain_region(self.tcx, &mut err, "", sup, "...");
133                         note_and_explain_region(
134                             self.tcx,
135                             &mut err,
136                             "...does not necessarily outlive ",
137                             sub,
138                             "",
139                         );
140                     }
141                 }
142                 err
143             }
144             infer::Reborrow(span) => {
145                 let mut err = struct_span_err!(
146                     self.tcx.sess,
147                     span,
148                     E0312,
149                     "lifetime of reference outlives lifetime of borrowed content..."
150                 );
151                 note_and_explain_region(
152                     self.tcx,
153                     &mut err,
154                     "...the reference is valid for ",
155                     sub,
156                     "...",
157                 );
158                 note_and_explain_region(
159                     self.tcx,
160                     &mut err,
161                     "...but the borrowed content is only valid for ",
162                     sup,
163                     "",
164                 );
165                 err
166             }
167             infer::ReborrowUpvar(span, ref upvar_id) => {
168                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
169                 let mut err = struct_span_err!(
170                     self.tcx.sess,
171                     span,
172                     E0313,
173                     "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
174                     var_name
175                 );
176                 note_and_explain_region(
177                     self.tcx,
178                     &mut err,
179                     "...the borrowed pointer is valid for ",
180                     sub,
181                     "...",
182                 );
183                 note_and_explain_region(
184                     self.tcx,
185                     &mut err,
186                     &format!("...but `{}` is only valid for ", var_name),
187                     sup,
188                     "",
189                 );
190                 err
191             }
192             infer::RelateObjectBound(span) => {
193                 let mut err = struct_span_err!(
194                     self.tcx.sess,
195                     span,
196                     E0476,
197                     "lifetime of the source pointer does not outlive lifetime bound of the \
198                      object type"
199                 );
200                 note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
201                 note_and_explain_region(
202                     self.tcx,
203                     &mut err,
204                     "source pointer is only valid for ",
205                     sup,
206                     "",
207                 );
208                 err
209             }
210             infer::RelateParamBound(span, ty) => {
211                 let mut err = struct_span_err!(
212                     self.tcx.sess,
213                     span,
214                     E0477,
215                     "the type `{}` does not fulfill the required lifetime",
216                     self.ty_to_string(ty)
217                 );
218                 match *sub {
219                     ty::ReStatic => {
220                         note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
221                     }
222                     _ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
223                 }
224                 err
225             }
226             infer::RelateRegionParamBound(span) => {
227                 let mut err =
228                     struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
229                 note_and_explain_region(
230                     self.tcx,
231                     &mut err,
232                     "lifetime parameter instantiated with ",
233                     sup,
234                     "",
235                 );
236                 note_and_explain_region(
237                     self.tcx,
238                     &mut err,
239                     "but lifetime parameter must outlive ",
240                     sub,
241                     "",
242                 );
243                 err
244             }
245             infer::CallReturn(span) => {
246                 let mut err = struct_span_err!(
247                     self.tcx.sess,
248                     span,
249                     E0482,
250                     "lifetime of return value does not outlive the function call"
251                 );
252                 note_and_explain_region(
253                     self.tcx,
254                     &mut err,
255                     "the return value is only valid for ",
256                     sup,
257                     "",
258                 );
259                 err
260             }
261             infer::DataBorrowed(ty, span) => {
262                 let mut err = struct_span_err!(
263                     self.tcx.sess,
264                     span,
265                     E0490,
266                     "a value of type `{}` is borrowed for too long",
267                     self.ty_to_string(ty)
268                 );
269                 note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
270                 note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
271                 err
272             }
273             infer::ReferenceOutlivesReferent(ty, span) => {
274                 let mut err = struct_span_err!(
275                     self.tcx.sess,
276                     span,
277                     E0491,
278                     "in type `{}`, reference has a longer lifetime than the data it references",
279                     self.ty_to_string(ty)
280                 );
281                 note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
282                 note_and_explain_region(
283                     self.tcx,
284                     &mut err,
285                     "but the referenced data is only valid for ",
286                     sup,
287                     "",
288                 );
289                 err
290             }
291             infer::CompareImplMethodObligation {
292                 span,
293                 item_name,
294                 impl_item_def_id,
295                 trait_item_def_id,
296             } => self.report_extra_impl_obligation(
297                 span,
298                 item_name,
299                 impl_item_def_id,
300                 trait_item_def_id,
301                 &format!("`{}: {}`", sup, sub),
302             ),
303         }
304     }
305
306     pub(super) fn report_placeholder_failure(
307         &self,
308         placeholder_origin: SubregionOrigin<'tcx>,
309         sub: Region<'tcx>,
310         sup: Region<'tcx>,
311     ) -> DiagnosticBuilder<'tcx> {
312         // I can't think how to do better than this right now. -nikomatsakis
313         debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
314         match placeholder_origin {
315             infer::Subtype(box ref trace)
316                 if matches!(
317                     &trace.cause.code.peel_derives(),
318                     ObligationCauseCode::BindingObligation(..)
319                 ) =>
320             {
321                 // Hack to get around the borrow checker because trace.cause has an `Rc`.
322                 if let ObligationCauseCode::BindingObligation(_, span) =
323                     &trace.cause.code.peel_derives()
324                 {
325                     let span = *span;
326                     let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
327                     err.span_note(span, "the lifetime requirement is introduced here");
328                     err
329                 } else {
330                     unreachable!()
331                 }
332             }
333             infer::Subtype(box trace) => {
334                 let terr = TypeError::RegionsPlaceholderMismatch;
335                 return self.report_and_explain_type_error(trace, &terr);
336             }
337             _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
338         }
339     }
340 }