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