error_reporting -- explain reborrowed upvar constraints in a hopefully useful way

This commit is contained in:
Niko Matsakis 2014-02-07 14:43:48 -05:00
parent 64c9b5c3ae
commit 7286e35c6b
3 changed files with 55 additions and 9 deletions

View file

@ -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(

View file

@ -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)),
}
}
}

View file

@ -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(..), _) |