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