1 use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
2 use crate::infer::{self, InferCtxt, SubregionOrigin};
3 use rustc_errors::{struct_span_err, DiagnosticBuilder};
4 use rustc_middle::traits::ObligationCauseCode;
5 use rustc_middle::ty::error::TypeError;
6 use rustc_middle::ty::{self, Region};
8 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9 pub(super) fn note_region_origin(
11 err: &mut DiagnosticBuilder<'_>,
12 origin: &SubregionOrigin<'tcx>,
14 let mut label_or_note = |span, msg| {
15 let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count();
16 let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count();
17 let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span);
18 if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
19 err.span_label(span, msg);
20 } else if span_is_primary && expanded_sub_count == 0 {
23 err.span_note(span, msg);
27 infer::Subtype(ref trace) => {
28 if let Some((expected, found)) = self.values_str(trace.values) {
31 &format!("...so that the {}", trace.cause.as_requirement_str()),
34 err.note_expected_found(&"", expected, &"", found);
36 // FIXME: this really should be handled at some earlier stage. Our
37 // handling of region checking when type errors are present is
42 &format!("...so that {}", trace.cause.as_requirement_str()),
46 infer::Reborrow(span) => {
47 label_or_note(span, "...so that reference does not outlive borrowed content");
49 infer::ReborrowUpvar(span, ref upvar_id) => {
50 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
51 label_or_note(span, &format!("...so that closure can access `{}`", var_name));
53 infer::RelateObjectBound(span) => {
54 label_or_note(span, "...so that it can be closed over into an object");
56 infer::DataBorrowed(ty, span) => {
60 "...so that the type `{}` is not borrowed for too long",
65 infer::ReferenceOutlivesReferent(ty, span) => {
69 "...so that the reference type `{}` does not outlive the data it points at",
74 infer::RelateParamBound(span, t, opt_span) => {
78 "...so that the type `{}` will meet its required lifetime bounds{}",
80 if opt_span.is_some() { "..." } else { "" },
83 if let Some(span) = opt_span {
84 err.span_note(span, "...that is required by this bound");
87 infer::RelateRegionParamBound(span) => {
90 "...so that the declared lifetime parameter bounds are satisfied",
93 infer::CompareImplMethodObligation { span, .. } => {
96 "...so that the definition in impl matches the definition from the trait",
99 infer::CompareImplTypeObligation { span, .. } => {
102 "...so that the definition in impl matches the definition from the trait",
108 pub(super) fn report_concrete_failure(
110 origin: SubregionOrigin<'tcx>,
113 ) -> DiagnosticBuilder<'tcx> {
115 infer::Subtype(box trace) => {
116 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
117 let mut err = self.report_and_explain_type_error(trace, &terr);
119 (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
120 (ty::RePlaceholder(_), _) => {
121 note_and_explain_region(
126 " doesn't meet the lifetime requirements",
130 (_, ty::RePlaceholder(_)) => {
131 note_and_explain_region(
134 "the required lifetime does not necessarily outlive ",
141 note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
142 note_and_explain_region(
145 "...does not necessarily outlive ",
154 infer::Reborrow(span) => {
155 let mut err = struct_span_err!(
159 "lifetime of reference outlives lifetime of borrowed content..."
161 note_and_explain_region(
164 "...the reference is valid for ",
169 note_and_explain_region(
172 "...but the borrowed content is only valid for ",
179 infer::ReborrowUpvar(span, ref upvar_id) => {
180 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
181 let mut err = struct_span_err!(
185 "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
188 note_and_explain_region(
191 "...the borrowed pointer is valid for ",
196 note_and_explain_region(
199 &format!("...but `{}` is only valid for ", var_name),
206 infer::RelateObjectBound(span) => {
207 let mut err = struct_span_err!(
211 "lifetime of the source pointer does not outlive lifetime bound of the \
214 note_and_explain_region(
217 "object type is valid for ",
222 note_and_explain_region(
225 "source pointer is only valid for ",
232 infer::RelateParamBound(span, ty, opt_span) => {
233 let mut err = struct_span_err!(
237 "the type `{}` does not fulfill the required lifetime",
238 self.ty_to_string(ty)
241 ty::ReStatic => note_and_explain_region(
244 "type must satisfy ",
246 if opt_span.is_some() { " as required by this binding" } else { "" },
249 _ => note_and_explain_region(
252 "type must outlive ",
254 if opt_span.is_some() { " as required by this binding" } else { "" },
260 infer::RelateRegionParamBound(span) => {
262 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
263 note_and_explain_region(
266 "lifetime parameter instantiated with ",
271 note_and_explain_region(
274 "but lifetime parameter must outlive ",
281 infer::DataBorrowed(ty, span) => {
282 let mut err = struct_span_err!(
286 "a value of type `{}` is borrowed for too long",
287 self.ty_to_string(ty)
289 note_and_explain_region(
292 "the type is valid for ",
297 note_and_explain_region(
300 "but the borrow lasts for ",
307 infer::ReferenceOutlivesReferent(ty, span) => {
308 let mut err = struct_span_err!(
312 "in type `{}`, reference has a longer lifetime than the data it references",
313 self.ty_to_string(ty)
315 note_and_explain_region(
318 "the pointer is valid for ",
323 note_and_explain_region(
326 "but the referenced data is only valid for ",
333 infer::CompareImplMethodObligation {
338 } => self.report_extra_impl_obligation(
343 &format!("`{}: {}`", sup, sub),
345 infer::CompareImplTypeObligation {
350 } => self.report_extra_impl_obligation(
355 &format!("`{}: {}`", sup, sub),
360 pub(super) fn report_placeholder_failure(
362 placeholder_origin: SubregionOrigin<'tcx>,
365 ) -> DiagnosticBuilder<'tcx> {
366 // I can't think how to do better than this right now. -nikomatsakis
367 debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
368 match placeholder_origin {
369 infer::Subtype(box ref trace)
371 &trace.cause.code.peel_derives(),
372 ObligationCauseCode::BindingObligation(..)
375 // Hack to get around the borrow checker because trace.cause has an `Rc`.
376 if let ObligationCauseCode::BindingObligation(_, span) =
377 &trace.cause.code.peel_derives()
380 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
381 err.span_note(span, "the lifetime requirement is introduced here");
387 infer::Subtype(box trace) => {
388 let terr = TypeError::RegionsPlaceholderMismatch;
389 return self.report_and_explain_type_error(trace, &terr);
391 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),