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