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::CallReturn(span) => {
57 label_or_note(span, "...so that return value is valid for the call");
59 infer::DataBorrowed(ty, span) => {
63 "...so that the type `{}` is not borrowed for too long",
68 infer::ReferenceOutlivesReferent(ty, span) => {
72 "...so that the reference type `{}` does not outlive the data it points at",
77 infer::RelateParamBound(span, t) => {
81 "...so that the type `{}` will meet its required lifetime bounds",
86 infer::RelateRegionParamBound(span) => {
89 "...so that the declared lifetime parameter bounds are satisfied",
92 infer::CompareImplMethodObligation { span, .. } => {
95 "...so that the definition in impl matches the definition from the trait",
101 pub(super) fn report_concrete_failure(
103 origin: SubregionOrigin<'tcx>,
106 ) -> DiagnosticBuilder<'tcx> {
108 infer::Subtype(box trace) => {
109 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
110 let mut err = self.report_and_explain_type_error(trace, &terr);
112 (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
113 (ty::RePlaceholder(_), _) => {
114 note_and_explain_region(
119 " doesn't meet the lifetime requirements",
122 (_, ty::RePlaceholder(_)) => {
123 note_and_explain_region(
126 "the required lifetime does not necessarily outlive ",
132 note_and_explain_region(self.tcx, &mut err, "", sup, "...");
133 note_and_explain_region(
136 "...does not necessarily outlive ",
144 infer::Reborrow(span) => {
145 let mut err = struct_span_err!(
149 "lifetime of reference outlives lifetime of borrowed content..."
151 note_and_explain_region(
154 "...the reference is valid for ",
158 note_and_explain_region(
161 "...but the borrowed content is only valid for ",
167 infer::ReborrowUpvar(span, ref upvar_id) => {
168 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
169 let mut err = struct_span_err!(
173 "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
176 note_and_explain_region(
179 "...the borrowed pointer is valid for ",
183 note_and_explain_region(
186 &format!("...but `{}` is only valid for ", var_name),
192 infer::RelateObjectBound(span) => {
193 let mut err = struct_span_err!(
197 "lifetime of the source pointer does not outlive lifetime bound of the \
200 note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
201 note_and_explain_region(
204 "source pointer is only valid for ",
210 infer::RelateParamBound(span, ty) => {
211 let mut err = struct_span_err!(
215 "the type `{}` does not fulfill the required lifetime",
216 self.ty_to_string(ty)
220 note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
222 _ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
226 infer::RelateRegionParamBound(span) => {
228 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
229 note_and_explain_region(
232 "lifetime parameter instantiated with ",
236 note_and_explain_region(
239 "but lifetime parameter must outlive ",
245 infer::CallReturn(span) => {
246 let mut err = struct_span_err!(
250 "lifetime of return value does not outlive the function call"
252 note_and_explain_region(
255 "the return value is only valid for ",
261 infer::DataBorrowed(ty, span) => {
262 let mut err = struct_span_err!(
266 "a value of type `{}` is borrowed for too long",
267 self.ty_to_string(ty)
269 note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
270 note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
273 infer::ReferenceOutlivesReferent(ty, span) => {
274 let mut err = struct_span_err!(
278 "in type `{}`, reference has a longer lifetime than the data it references",
279 self.ty_to_string(ty)
281 note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
282 note_and_explain_region(
285 "but the referenced data is only valid for ",
291 infer::CompareImplMethodObligation {
296 } => self.report_extra_impl_obligation(
301 &format!("`{}: {}`", sup, sub),
306 pub(super) fn report_placeholder_failure(
308 placeholder_origin: SubregionOrigin<'tcx>,
311 ) -> DiagnosticBuilder<'tcx> {
312 // I can't think how to do better than this right now. -nikomatsakis
313 debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
314 match placeholder_origin {
315 infer::Subtype(box ref trace)
317 &trace.cause.code.peel_derives(),
318 ObligationCauseCode::BindingObligation(..)
321 // Hack to get around the borrow checker because trace.cause has an `Rc`.
322 if let ObligationCauseCode::BindingObligation(_, span) =
323 &trace.cause.code.peel_derives()
326 let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
327 err.span_note(span, "the lifetime requirement is introduced here");
333 infer::Subtype(box trace) => {
334 let terr = TypeError::RegionsPlaceholderMismatch;
335 return self.report_and_explain_type_error(trace, &terr);
337 _ => return self.report_concrete_failure(placeholder_origin, sub, sup),