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::DataBorrowed(ty, span) => {
33 RegionOriginNote::WithName {
35 msg: fluent::infer_data_borrowed,
36 name: &self.ty_to_string(ty),
39 .add_to_diagnostic(err);
41 infer::ReferenceOutlivesReferent(ty, span) => {
42 RegionOriginNote::WithName {
44 msg: fluent::infer_reference_outlives_referent,
45 name: &self.ty_to_string(ty),
48 .add_to_diagnostic(err);
50 infer::RelateParamBound(span, ty, opt_span) => {
51 RegionOriginNote::WithName {
53 msg: fluent::infer_relate_param_bound,
54 name: &self.ty_to_string(ty),
55 continues: opt_span.is_some(),
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);
63 infer::RelateRegionParamBound(span) => {
64 RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
65 .add_to_diagnostic(err);
67 infer::CompareImplItemObligation { span, .. } => {
68 RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
69 .add_to_diagnostic(err);
71 infer::CheckAssociatedTypeBounds { ref parent, .. } => {
72 self.note_region_origin(err, &parent);
74 infer::AscribeUserTypeProvePredicate(span) => {
75 RegionOriginNote::Plain {
77 msg: fluent::infer_ascribe_user_type_prove_predicate,
79 .add_to_diagnostic(err);
84 pub(super) fn report_concrete_failure(
86 origin: SubregionOrigin<'tcx>,
89 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
91 infer::Subtype(box trace) => {
92 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
93 let mut err = self.report_and_explain_type_error(trace, terr);
95 (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
96 (ty::RePlaceholder(_), _) => {
97 note_and_explain_region(
102 " doesn't meet the lifetime requirements",
106 (_, ty::RePlaceholder(_)) => {
107 note_and_explain_region(
110 "the required lifetime does not necessarily outlive ",
117 note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
118 note_and_explain_region(
121 "...does not necessarily outlive ",
130 infer::Reborrow(span) => {
131 let mut err = struct_span_err!(
135 "lifetime of reference outlives lifetime of borrowed content..."
137 note_and_explain_region(
140 "...the reference is valid for ",
145 note_and_explain_region(
148 "...but the borrowed content is only valid for ",
155 infer::RelateObjectBound(span) => {
156 let mut err = struct_span_err!(
160 "lifetime of the source pointer does not outlive lifetime bound of the \
163 note_and_explain_region(
166 "object type is valid for ",
171 note_and_explain_region(
174 "source pointer is only valid for ",
181 infer::RelateParamBound(span, ty, opt_span) => {
182 let mut err = struct_span_err!(
186 "the type `{}` does not fulfill the required lifetime",
187 self.ty_to_string(ty)
190 ty::ReStatic => note_and_explain_region(
193 "type must satisfy ",
195 if opt_span.is_some() { " as required by this binding" } else { "" },
198 _ => note_and_explain_region(
201 "type must outlive ",
203 if opt_span.is_some() { " as required by this binding" } else { "" },
209 infer::RelateRegionParamBound(span) => {
211 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
212 note_and_explain_region(
215 "lifetime parameter instantiated with ",
220 note_and_explain_region(
223 "but lifetime parameter must outlive ",
230 infer::DataBorrowed(ty, span) => {
231 let mut err = struct_span_err!(
235 "a value of type `{}` is borrowed for too long",
236 self.ty_to_string(ty)
238 note_and_explain_region(
241 "the type is valid for ",
246 note_and_explain_region(
249 "but the borrow lasts for ",
256 infer::ReferenceOutlivesReferent(ty, span) => {
257 let mut err = struct_span_err!(
261 "in type `{}`, reference has a longer lifetime than the data it references",
262 self.ty_to_string(ty)
264 note_and_explain_region(
267 "the pointer is valid for ",
272 note_and_explain_region(
275 "but the referenced data is only valid for ",
282 infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
283 let mut err = self.report_extra_impl_obligation(
287 &format!("`{}: {}`", sup, sub),
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)
293 self.suggest_copy_trait_method_bounds(
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());
307 format!("definition of `{}` from trait", item_name),
309 self.suggest_copy_trait_method_bounds(
316 infer::AscribeUserTypeProvePredicate(span) => {
318 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
319 note_and_explain_region(
322 "lifetime instantiated with ",
327 note_and_explain_region(
330 "but lifetime must outlive ",
340 pub fn suggest_copy_trait_method_bounds(
342 trait_item_def_id: DefId,
343 impl_item_def_id: LocalDefId,
344 err: &mut Diagnostic,
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.
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
355 .impl_trait_ref(impl_def_id)
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))
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);
365 let Ok(trait_predicates) = self
367 .bound_explicit_predicates_of(trait_item_def_id)
368 .map_bound(|p| p.predicates)
369 .subst_iter_copied(self.tcx, trait_item_substs)
371 if pred.is_suggestable(self.tcx, false) {
377 .collect::<Result<Vec<_>, ()>>() else { return; };
379 let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
381 if trait_predicates.is_empty() {
382 err.span_suggestion_verbose(
383 generics.where_clause_span,
384 "remove the `where` clause",
386 Applicability::MachineApplicable,
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,
399 pub(super) fn report_placeholder_failure(
401 placeholder_origin: SubregionOrigin<'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)
410 &trace.cause.code().peel_derives(),
411 ObligationCauseCode::BindingObligation(..)
412 | ObligationCauseCode::ExprBindingObligation(..)
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()
421 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
422 err.span_note(span, "the lifetime requirement is introduced here");
428 infer::Subtype(box trace) => {
429 let terr = TypeError::RegionsPlaceholderMismatch;
430 return self.report_and_explain_type_error(trace, terr);
432 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),