1 use crate::errors::RegionOriginNote;
2 use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
3 use crate::infer::{self, SubregionOrigin};
5 fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
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;
14 use super::ObligationCauseAsDiagArg;
16 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
17 pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
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)),
24 .add_to_diagnostic(err),
25 infer::Reborrow(span) => {
26 RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
28 infer::RelateObjectBound(span) => {
29 RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
30 .add_to_diagnostic(err);
32 infer::ReferenceOutlivesReferent(ty, span) => {
33 RegionOriginNote::WithName {
35 msg: fluent::infer_reference_outlives_referent,
36 name: &self.ty_to_string(ty),
39 .add_to_diagnostic(err);
41 infer::RelateParamBound(span, ty, opt_span) => {
42 RegionOriginNote::WithName {
44 msg: fluent::infer_relate_param_bound,
45 name: &self.ty_to_string(ty),
46 continues: opt_span.is_some(),
48 .add_to_diagnostic(err);
49 if let Some(span) = opt_span {
50 RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
51 .add_to_diagnostic(err);
54 infer::RelateRegionParamBound(span) => {
55 RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
56 .add_to_diagnostic(err);
58 infer::CompareImplItemObligation { span, .. } => {
59 RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
60 .add_to_diagnostic(err);
62 infer::CheckAssociatedTypeBounds { ref parent, .. } => {
63 self.note_region_origin(err, &parent);
65 infer::AscribeUserTypeProvePredicate(span) => {
66 RegionOriginNote::Plain {
68 msg: fluent::infer_ascribe_user_type_prove_predicate,
70 .add_to_diagnostic(err);
75 pub(super) fn report_concrete_failure(
77 origin: SubregionOrigin<'tcx>,
80 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
82 infer::Subtype(box trace) => {
83 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
84 let mut err = self.report_and_explain_type_error(trace, terr);
86 (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
87 (ty::RePlaceholder(_), _) => {
88 note_and_explain_region(
93 " doesn't meet the lifetime requirements",
97 (_, ty::RePlaceholder(_)) => {
98 note_and_explain_region(
101 "the required lifetime does not necessarily outlive ",
108 note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
109 note_and_explain_region(
112 "...does not necessarily outlive ",
121 infer::Reborrow(span) => {
122 let mut err = struct_span_err!(
126 "lifetime of reference outlives lifetime of borrowed content..."
128 note_and_explain_region(
131 "...the reference is valid for ",
136 note_and_explain_region(
139 "...but the borrowed content is only valid for ",
146 infer::RelateObjectBound(span) => {
147 let mut err = struct_span_err!(
151 "lifetime of the source pointer does not outlive lifetime bound of the \
154 note_and_explain_region(
157 "object type is valid for ",
162 note_and_explain_region(
165 "source pointer is only valid for ",
172 infer::RelateParamBound(span, ty, opt_span) => {
173 let mut err = struct_span_err!(
177 "the type `{}` does not fulfill the required lifetime",
178 self.ty_to_string(ty)
181 ty::ReStatic => note_and_explain_region(
184 "type must satisfy ",
186 if opt_span.is_some() { " as required by this binding" } else { "" },
189 _ => note_and_explain_region(
192 "type must outlive ",
194 if opt_span.is_some() { " as required by this binding" } else { "" },
200 infer::RelateRegionParamBound(span) => {
202 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
203 note_and_explain_region(
206 "lifetime parameter instantiated with ",
211 note_and_explain_region(
214 "but lifetime parameter must outlive ",
221 infer::ReferenceOutlivesReferent(ty, span) => {
222 let mut err = struct_span_err!(
226 "in type `{}`, reference has a longer lifetime than the data it references",
227 self.ty_to_string(ty)
229 note_and_explain_region(
232 "the pointer is valid for ",
237 note_and_explain_region(
240 "but the referenced data is only valid for ",
247 infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
248 let mut err = self.report_extra_impl_obligation(
252 &format!("`{}: {}`", sup, sub),
254 // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
255 if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id)
256 && generics.where_clause_span.contains(span)
258 self.suggest_copy_trait_method_bounds(
266 infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
267 let mut err = self.report_concrete_failure(*parent, sub, sup);
268 let trait_item_span = self.tcx.def_span(trait_item_def_id);
269 let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
272 format!("definition of `{}` from trait", item_name),
274 self.suggest_copy_trait_method_bounds(
281 infer::AscribeUserTypeProvePredicate(span) => {
283 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
284 note_and_explain_region(
287 "lifetime instantiated with ",
292 note_and_explain_region(
295 "but lifetime must outlive ",
305 pub fn suggest_copy_trait_method_bounds(
307 trait_item_def_id: DefId,
308 impl_item_def_id: LocalDefId,
309 err: &mut Diagnostic,
311 // FIXME(compiler-errors): Right now this is only being used for region
312 // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
313 // but right now it's not really very smart when it comes to implicit `Sized`
314 // predicates and bounds on the trait itself.
316 let Some(impl_def_id) =
317 self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; };
318 let Some(trait_ref) = self
320 .impl_trait_ref(impl_def_id)
322 let trait_substs = trait_ref
324 // Replace the explicit self type with `Self` for better suggestion rendering
325 .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper))
327 let trait_item_substs =
328 ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id.to_def_id())
329 .rebase_onto(self.tcx, impl_def_id, trait_substs);
331 let Ok(trait_predicates) = self
333 .explicit_predicates_of(trait_item_def_id)
334 .instantiate_own(self.tcx, trait_item_substs)
336 if pred.is_suggestable(self.tcx, false) {
342 .collect::<Result<Vec<_>, ()>>() else { return; };
344 let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
346 if trait_predicates.is_empty() {
347 err.span_suggestion_verbose(
348 generics.where_clause_span,
349 "remove the `where` clause",
351 Applicability::MachineApplicable,
354 let space = if generics.where_clause_span.is_empty() { " " } else { "" };
355 err.span_suggestion_verbose(
356 generics.where_clause_span,
357 "copy the `where` clause predicates from the trait",
358 format!("{space}where {}", trait_predicates.join(", ")),
359 Applicability::MachineApplicable,
364 pub(super) fn report_placeholder_failure(
366 placeholder_origin: SubregionOrigin<'tcx>,
369 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
370 // I can't think how to do better than this right now. -nikomatsakis
371 debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
372 match placeholder_origin {
373 infer::Subtype(box ref trace)
375 &trace.cause.code().peel_derives(),
376 ObligationCauseCode::BindingObligation(..)
377 | ObligationCauseCode::ExprBindingObligation(..)
380 // Hack to get around the borrow checker because trace.cause has an `Rc`.
381 if let ObligationCauseCode::BindingObligation(_, span)
382 | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
383 &trace.cause.code().peel_derives()
386 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
387 err.span_note(span, "the lifetime requirement is introduced here");
393 infer::Subtype(box trace) => {
394 let terr = TypeError::RegionsPlaceholderMismatch;
395 return self.report_and_explain_type_error(trace, terr);
397 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),