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, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
7 use rustc_middle::traits::ObligationCauseCode;
8 use rustc_middle::ty::error::TypeError;
9 use rustc_middle::ty::{self, Region};
11 use super::ObligationCauseAsDiagArg;
13 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
14 pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
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),
21 .add_to_diagnostic(err),
22 infer::Reborrow(span) => {
23 RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
25 infer::ReborrowUpvar(span, ref upvar_id) => {
26 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
27 RegionOriginNote::WithName {
29 msg: fluent::infer_reborrow,
30 name: &var_name.to_string(),
33 .add_to_diagnostic(err);
35 infer::RelateObjectBound(span) => {
36 RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
37 .add_to_diagnostic(err);
39 infer::DataBorrowed(ty, span) => {
40 RegionOriginNote::WithName {
42 msg: fluent::infer_data_borrowed,
43 name: &self.ty_to_string(ty),
46 .add_to_diagnostic(err);
48 infer::ReferenceOutlivesReferent(ty, span) => {
49 RegionOriginNote::WithName {
51 msg: fluent::infer_reference_outlives_referent,
52 name: &self.ty_to_string(ty),
55 .add_to_diagnostic(err);
57 infer::RelateParamBound(span, ty, opt_span) => {
58 RegionOriginNote::WithName {
60 msg: fluent::infer_relate_param_bound,
61 name: &self.ty_to_string(ty),
62 continues: opt_span.is_some(),
64 .add_to_diagnostic(err);
65 if let Some(span) = opt_span {
66 RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
67 .add_to_diagnostic(err);
70 infer::RelateRegionParamBound(span) => {
71 RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
72 .add_to_diagnostic(err);
74 infer::CompareImplItemObligation { span, .. } => {
75 RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
76 .add_to_diagnostic(err);
78 infer::CheckAssociatedTypeBounds { ref parent, .. } => {
79 self.note_region_origin(err, &parent);
81 infer::AscribeUserTypeProvePredicate(span) => {
82 RegionOriginNote::Plain {
84 msg: fluent::infer_ascribe_user_type_prove_predicate,
86 .add_to_diagnostic(err);
91 pub(super) fn report_concrete_failure(
93 origin: SubregionOrigin<'tcx>,
96 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
98 infer::Subtype(box trace) => {
99 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
100 let mut err = self.report_and_explain_type_error(trace, terr);
102 (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
103 (ty::RePlaceholder(_), _) => {
104 note_and_explain_region(
109 " doesn't meet the lifetime requirements",
113 (_, ty::RePlaceholder(_)) => {
114 note_and_explain_region(
117 "the required lifetime does not necessarily outlive ",
124 note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
125 note_and_explain_region(
128 "...does not necessarily outlive ",
137 infer::Reborrow(span) => {
138 let mut err = struct_span_err!(
142 "lifetime of reference outlives lifetime of borrowed content..."
144 note_and_explain_region(
147 "...the reference is valid for ",
152 note_and_explain_region(
155 "...but the borrowed content is only valid for ",
162 infer::ReborrowUpvar(span, ref upvar_id) => {
163 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
164 let mut err = struct_span_err!(
168 "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
171 note_and_explain_region(
174 "...the borrowed pointer is valid for ",
179 note_and_explain_region(
182 &format!("...but `{}` is only valid for ", var_name),
189 infer::RelateObjectBound(span) => {
190 let mut err = struct_span_err!(
194 "lifetime of the source pointer does not outlive lifetime bound of the \
197 note_and_explain_region(
200 "object type is valid for ",
205 note_and_explain_region(
208 "source pointer is only valid for ",
215 infer::RelateParamBound(span, ty, opt_span) => {
216 let mut err = struct_span_err!(
220 "the type `{}` does not fulfill the required lifetime",
221 self.ty_to_string(ty)
224 ty::ReStatic => note_and_explain_region(
227 "type must satisfy ",
229 if opt_span.is_some() { " as required by this binding" } else { "" },
232 _ => note_and_explain_region(
235 "type must outlive ",
237 if opt_span.is_some() { " as required by this binding" } else { "" },
243 infer::RelateRegionParamBound(span) => {
245 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
246 note_and_explain_region(
249 "lifetime parameter instantiated with ",
254 note_and_explain_region(
257 "but lifetime parameter must outlive ",
264 infer::DataBorrowed(ty, span) => {
265 let mut err = struct_span_err!(
269 "a value of type `{}` is borrowed for too long",
270 self.ty_to_string(ty)
272 note_and_explain_region(
275 "the type is valid for ",
280 note_and_explain_region(
283 "but the borrow lasts for ",
290 infer::ReferenceOutlivesReferent(ty, span) => {
291 let mut err = struct_span_err!(
295 "in type `{}`, reference has a longer lifetime than the data it references",
296 self.ty_to_string(ty)
298 note_and_explain_region(
301 "the pointer is valid for ",
306 note_and_explain_region(
309 "but the referenced data is only valid for ",
316 infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
317 .report_extra_impl_obligation(
321 &format!("`{}: {}`", sup, sub),
323 infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
324 let mut err = self.report_concrete_failure(*parent, sub, sup);
326 let trait_item_span = self.tcx.def_span(trait_item_def_id);
327 let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
330 format!("definition of `{}` from trait", item_name),
333 let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
334 let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
336 let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
337 impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
338 let clauses: Vec<_> = trait_predicates
341 .filter(|&(pred, _)| !impl_predicates.contains(pred))
342 .map(|(pred, _)| format!("{}", pred))
345 if !clauses.is_empty() {
346 let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
347 let where_clause_span = generics.tail_span_for_predicate_suggestion();
349 let suggestion = format!(
351 generics.add_where_or_trailing_comma(),
357 "try copying {} from the trait",
358 if clauses.len() > 1 { "these clauses" } else { "this clause" }
361 rustc_errors::Applicability::MaybeIncorrect,
367 infer::AscribeUserTypeProvePredicate(span) => {
369 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
370 note_and_explain_region(
373 "lifetime instantiated with ",
378 note_and_explain_region(
381 "but lifetime must outlive ",
391 pub(super) fn report_placeholder_failure(
393 placeholder_origin: SubregionOrigin<'tcx>,
396 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
397 // I can't think how to do better than this right now. -nikomatsakis
398 debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
399 match placeholder_origin {
400 infer::Subtype(box ref trace)
402 &trace.cause.code().peel_derives(),
403 ObligationCauseCode::BindingObligation(..)
404 | ObligationCauseCode::ExprBindingObligation(..)
407 // Hack to get around the borrow checker because trace.cause has an `Rc`.
408 if let ObligationCauseCode::BindingObligation(_, span)
409 | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
410 &trace.cause.code().peel_derives()
413 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
414 err.span_note(span, "the lifetime requirement is introduced here");
420 infer::Subtype(box trace) => {
421 let terr = TypeError::RegionsPlaceholderMismatch;
422 return self.report_and_explain_type_error(trace, terr);
424 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),