1 use crate::errors::RegionOriginNote;
2 use crate::infer::error_reporting::note_and_explain_region;
3 use crate::infer::{self, InferCtxt, 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<'a, 'tcx> InferCtxt<'a, '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) => RegionOriginNote::Plain { span, msg: fluent::infer::reborrow }
23 .add_to_diagnostic(err),
24 infer::ReborrowUpvar(span, ref upvar_id) => {
25 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
26 RegionOriginNote::WithName {
28 msg: fluent::infer::reborrow,
29 name: &var_name.to_string(),
32 .add_to_diagnostic(err);
34 infer::RelateObjectBound(span) => {
35 RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound }
36 .add_to_diagnostic(err);
38 infer::DataBorrowed(ty, span) => {
39 RegionOriginNote::WithName {
41 msg: fluent::infer::data_borrowed,
42 name: &self.ty_to_string(ty),
45 .add_to_diagnostic(err);
47 infer::ReferenceOutlivesReferent(ty, span) => {
48 RegionOriginNote::WithName {
50 msg: fluent::infer::reference_outlives_referent,
51 name: &self.ty_to_string(ty),
54 .add_to_diagnostic(err);
56 infer::RelateParamBound(span, ty, opt_span) => {
57 RegionOriginNote::WithName {
59 msg: fluent::infer::relate_param_bound,
60 name: &self.ty_to_string(ty),
61 continues: opt_span.is_some(),
63 .add_to_diagnostic(err);
64 if let Some(span) = opt_span {
65 RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 }
66 .add_to_diagnostic(err);
69 infer::RelateRegionParamBound(span) => {
70 RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound }
71 .add_to_diagnostic(err);
73 infer::CompareImplItemObligation { span, .. } => {
74 RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation }
75 .add_to_diagnostic(err);
77 infer::CheckAssociatedTypeBounds { ref parent, .. } => {
78 self.note_region_origin(err, &parent);
80 infer::AscribeUserTypeProvePredicate(span) => {
81 RegionOriginNote::Plain {
83 msg: fluent::infer::ascribe_user_type_prove_predicate,
85 .add_to_diagnostic(err);
90 pub(super) fn report_concrete_failure(
92 origin: SubregionOrigin<'tcx>,
95 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
97 infer::Subtype(box trace) => {
98 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
99 let mut err = self.report_and_explain_type_error(trace, terr);
101 (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
102 (ty::RePlaceholder(_), _) => {
103 note_and_explain_region(
108 " doesn't meet the lifetime requirements",
112 (_, ty::RePlaceholder(_)) => {
113 note_and_explain_region(
116 "the required lifetime does not necessarily outlive ",
123 note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
124 note_and_explain_region(
127 "...does not necessarily outlive ",
136 infer::Reborrow(span) => {
137 let mut err = struct_span_err!(
141 "lifetime of reference outlives lifetime of borrowed content..."
143 note_and_explain_region(
146 "...the reference is valid for ",
151 note_and_explain_region(
154 "...but the borrowed content is only valid for ",
161 infer::ReborrowUpvar(span, ref upvar_id) => {
162 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
163 let mut err = struct_span_err!(
167 "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
170 note_and_explain_region(
173 "...the borrowed pointer is valid for ",
178 note_and_explain_region(
181 &format!("...but `{}` is only valid for ", var_name),
188 infer::RelateObjectBound(span) => {
189 let mut err = struct_span_err!(
193 "lifetime of the source pointer does not outlive lifetime bound of the \
196 note_and_explain_region(
199 "object type is valid for ",
204 note_and_explain_region(
207 "source pointer is only valid for ",
214 infer::RelateParamBound(span, ty, opt_span) => {
215 let mut err = struct_span_err!(
219 "the type `{}` does not fulfill the required lifetime",
220 self.ty_to_string(ty)
223 ty::ReStatic => note_and_explain_region(
226 "type must satisfy ",
228 if opt_span.is_some() { " as required by this binding" } else { "" },
231 _ => note_and_explain_region(
234 "type must outlive ",
236 if opt_span.is_some() { " as required by this binding" } else { "" },
242 infer::RelateRegionParamBound(span) => {
244 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
245 note_and_explain_region(
248 "lifetime parameter instantiated with ",
253 note_and_explain_region(
256 "but lifetime parameter must outlive ",
263 infer::DataBorrowed(ty, span) => {
264 let mut err = struct_span_err!(
268 "a value of type `{}` is borrowed for too long",
269 self.ty_to_string(ty)
271 note_and_explain_region(
274 "the type is valid for ",
279 note_and_explain_region(
282 "but the borrow lasts for ",
289 infer::ReferenceOutlivesReferent(ty, span) => {
290 let mut err = struct_span_err!(
294 "in type `{}`, reference has a longer lifetime than the data it references",
295 self.ty_to_string(ty)
297 note_and_explain_region(
300 "the pointer is valid for ",
305 note_and_explain_region(
308 "but the referenced data is only valid for ",
315 infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
316 .report_extra_impl_obligation(
320 &format!("`{}: {}`", sup, sub),
322 infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
323 let mut err = self.report_concrete_failure(*parent, sub, sup);
325 let trait_item_span = self.tcx.def_span(trait_item_def_id);
326 let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
329 format!("definition of `{}` from trait", item_name),
332 let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
333 let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
335 let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
336 impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
337 let clauses: Vec<_> = trait_predicates
340 .filter(|&(pred, _)| !impl_predicates.contains(pred))
341 .map(|(pred, _)| format!("{}", pred))
344 if !clauses.is_empty() {
345 let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
346 let where_clause_span = generics.tail_span_for_predicate_suggestion();
348 let suggestion = format!(
350 generics.add_where_or_trailing_comma(),
356 "try copying {} from the trait",
357 if clauses.len() > 1 { "these clauses" } else { "this clause" }
360 rustc_errors::Applicability::MaybeIncorrect,
366 infer::AscribeUserTypeProvePredicate(span) => {
368 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
369 note_and_explain_region(
372 "lifetime instantiated with ",
377 note_and_explain_region(
380 "but lifetime must outlive ",
390 pub(super) fn report_placeholder_failure(
392 placeholder_origin: SubregionOrigin<'tcx>,
395 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
396 // I can't think how to do better than this right now. -nikomatsakis
397 debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
398 match placeholder_origin {
399 infer::Subtype(box ref trace)
401 &trace.cause.code().peel_derives(),
402 ObligationCauseCode::BindingObligation(..)
403 | ObligationCauseCode::ExprBindingObligation(..)
406 // Hack to get around the borrow checker because trace.cause has an `Rc`.
407 if let ObligationCauseCode::BindingObligation(_, span)
408 | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
409 &trace.cause.code().peel_derives()
412 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
413 err.span_note(span, "the lifetime requirement is introduced here");
419 infer::Subtype(box trace) => {
420 let terr = TypeError::RegionsPlaceholderMismatch;
421 return self.report_and_explain_type_error(trace, terr);
423 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),