From 7286e35c6b840763012db2ca4b0655b8344f02ba Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Feb 2014 14:43:48 -0500 Subject: [PATCH] error_reporting -- explain reborrowed upvar constraints in a hopefully useful way --- .../middle/typeck/infer/error_reporting.rs | 41 ++++++++++++++++--- src/librustc/middle/typeck/infer/mod.rs | 17 ++++++-- .../typeck/infer/region_inference/mod.rs | 6 ++- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 657b75a44ed3..3a3f24a2e2d8 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -237,6 +237,24 @@ impl ErrorReporting for InferCtxt { sup, ""); } + infer::ReborrowUpvar(span, ref upvar_id) => { + self.tcx.sess.span_err( + span, + format!("lifetime of borrowed pointer outlives \ + lifetime of captured variable `{}`...", + ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_str())); + note_and_explain_region( + self.tcx, + "...the borrowed pointer is valid for ", + sub, + "..."); + note_and_explain_region( + self.tcx, + format!("...but `{}` is only valid for ", + ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_str()), + sup, + ""); + } infer::InfStackClosure(span) => { self.tcx.sess.span_err( span, @@ -272,10 +290,12 @@ impl ErrorReporting for InferCtxt { sup, ""); } - infer::FreeVariable(span) => { + infer::FreeVariable(span, id) => { self.tcx.sess.span_err( span, - "captured variable does not outlive the enclosing closure"); + format!("captured variable `{}` does not \ + outlive the enclosing closure", + ty::local_var_name_str(self.tcx, id).get().to_str())); note_and_explain_region( self.tcx, "captured variable is valid for ", @@ -473,6 +493,10 @@ impl ErrorReportingHelpers for InferCtxt { infer::BoundRegionInCoherence(..) => { format!(" for coherence check") } + infer::UpvarRegion(ref upvar_id, _) => { + format!(" for capture of `{}` by closure", + ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_str()) + } }; self.tcx.sess.span_err( @@ -533,6 +557,12 @@ impl ErrorReportingHelpers for InferCtxt { "...so that reference does not outlive \ borrowed content"); } + infer::ReborrowUpvar(span, ref upvar_id) => { + self.tcx.sess.span_note( + span, + format!("...so that closure can access `{}`", + ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_str())) + } infer::InfStackClosure(span) => { self.tcx.sess.span_note( span, @@ -549,11 +579,12 @@ impl ErrorReportingHelpers for InferCtxt { "...so that pointer is not dereferenced \ outside its lifetime"); } - infer::FreeVariable(span) => { + infer::FreeVariable(span, id) => { self.tcx.sess.span_note( span, - "...so that captured variable does not outlive the \ - enclosing closure"); + format!("...so that captured variable `{}` \ + does not outlive the enclosing closure", + ty::local_var_name_str(self.tcx, id).get().to_str())); } infer::IndexSlice(span) => { self.tcx.sess.span_note( diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 496170c3e47e..deec41006174 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -160,7 +160,7 @@ pub enum SubregionOrigin { DerefPointer(Span), // Closure bound must not outlive captured free variables - FreeVariable(Span), + FreeVariable(Span, ast::NodeId), // Index into slice must be within its lifetime IndexSlice(Span), @@ -172,6 +172,9 @@ pub enum SubregionOrigin { // Creating a pointer `b` to contents of another reference Reborrow(Span), + // Creating a pointer `b` to contents of an upvar + ReborrowUpvar(Span, ty::UpvarId), + // (&'a &'b T) where a >= b ReferenceOutlivesReferent(ty::t, Span), @@ -225,6 +228,8 @@ pub enum RegionVariableOrigin { // when doing subtyping/lub/glb computations BoundRegionInFnType(Span, ty::BoundRegion), + UpvarRegion(ty::UpvarId, Span), + BoundRegionInTypeOrImpl(Span), BoundRegionInCoherence, @@ -876,10 +881,11 @@ impl SubregionOrigin { InfStackClosure(a) => a, InvokeClosure(a) => a, DerefPointer(a) => a, - FreeVariable(a) => a, + FreeVariable(a, _) => a, IndexSlice(a) => a, RelateObjectBound(a) => a, Reborrow(a) => a, + ReborrowUpvar(a, _) => a, ReferenceOutlivesReferent(_, a) => a, BindingTypeIsNotValidAtDecl(a) => a, CallRcvr(a) => a, @@ -898,10 +904,11 @@ impl Repr for SubregionOrigin { InfStackClosure(a) => format!("InfStackClosure({})", a.repr(tcx)), InvokeClosure(a) => format!("InvokeClosure({})", a.repr(tcx)), DerefPointer(a) => format!("DerefPointer({})", a.repr(tcx)), - FreeVariable(a) => format!("FreeVariable({})", a.repr(tcx)), + FreeVariable(a, b) => format!("FreeVariable({}, {})", a.repr(tcx), b), IndexSlice(a) => format!("IndexSlice({})", a.repr(tcx)), RelateObjectBound(a) => format!("RelateObjectBound({})", a.repr(tcx)), Reborrow(a) => format!("Reborrow({})", a.repr(tcx)), + ReborrowUpvar(a, b) => format!("ReborrowUpvar({},{:?})", a.repr(tcx), b), ReferenceOutlivesReferent(_, a) => format!("ReferenceOutlivesReferent({})", a.repr(tcx)), BindingTypeIsNotValidAtDecl(a) => @@ -928,6 +935,7 @@ impl RegionVariableOrigin { BoundRegionInFnType(a, _) => a, BoundRegionInTypeOrImpl(a) => a, BoundRegionInCoherence => codemap::DUMMY_SP, + UpvarRegion(_, a) => a } } } @@ -948,6 +956,9 @@ impl Repr for RegionVariableOrigin { BoundRegionInTypeOrImpl(a) => format!("bound_regionInTypeOrImpl({})", a.repr(tcx)), BoundRegionInCoherence => format!("bound_regionInCoherence"), + UpvarRegion(a, b) => format!("UpvarRegion({}, {})", + a.repr(tcx), + b.repr(tcx)), } } } diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 2bc0d7d64195..bbd9d8e1c4dc 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -270,7 +270,11 @@ impl RegionVarBindings { // cannot add constraints once regions are resolved assert!(self.values_are_none()); - debug!("RegionVarBindings: make_subregion({:?}, {:?})", sub, sup); + debug!("RegionVarBindings: make_subregion({}, {}) due to {}", + sub.repr(self.tcx), + sup.repr(self.tcx), + origin.repr(self.tcx)); + match (sub, sup) { (ReEarlyBound(..), _) | (ReLateBound(..), _) |