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 .bound_explicit_predicates_of(trait_item_def_id)
334 .map_bound(|p| p.predicates)
335 .subst_iter_copied(self.tcx, trait_item_substs)
337 if pred.is_suggestable(self.tcx, false) {
343 .collect::<Result<Vec<_>, ()>>() else { return; };
345 let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
347 if trait_predicates.is_empty() {
348 err.span_suggestion_verbose(
349 generics.where_clause_span,
350 "remove the `where` clause",
352 Applicability::MachineApplicable,
355 let space = if generics.where_clause_span.is_empty() { " " } else { "" };
356 err.span_suggestion_verbose(
357 generics.where_clause_span,
358 "copy the `where` clause predicates from the trait",
359 format!("{space}where {}", trait_predicates.join(", ")),
360 Applicability::MachineApplicable,
365 pub(super) fn report_placeholder_failure(
367 placeholder_origin: SubregionOrigin<'tcx>,
370 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
371 // I can't think how to do better than this right now. -nikomatsakis
372 debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
373 match placeholder_origin {
374 infer::Subtype(box ref trace)
376 &trace.cause.code().peel_derives(),
377 ObligationCauseCode::BindingObligation(..)
378 | ObligationCauseCode::ExprBindingObligation(..)
381 // Hack to get around the borrow checker because trace.cause has an `Rc`.
382 if let ObligationCauseCode::BindingObligation(_, span)
383 | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
384 &trace.cause.code().peel_derives()
387 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
388 err.span_note(span, "the lifetime requirement is introduced here");
394 infer::Subtype(box trace) => {
395 let terr = TypeError::RegionsPlaceholderMismatch;
396 return self.report_and_explain_type_error(trace, terr);
398 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),