Fix regionck to consider bounds on a proc when capturing variables
This commit is contained in:
parent
b5165321e4
commit
f60a7c4798
@ -1534,6 +1534,12 @@ fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
|
||||
|
||||
fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
|
||||
cmt: mc::cmt) {
|
||||
/*!
|
||||
* Indicates that `cmt` is being directly mutated (e.g., assigned
|
||||
* to). If cmt contains any by-ref upvars, this implies that
|
||||
* those upvars must be borrowed using an `&mut` borow.
|
||||
*/
|
||||
|
||||
let mut cmt = cmt;
|
||||
loop {
|
||||
debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
|
||||
|
@ -583,6 +583,19 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
|
||||
sub,
|
||||
"");
|
||||
}
|
||||
infer::ProcCapture(span, id) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
format!("captured variable `{}` must be 'static \
|
||||
to be captured in a proc",
|
||||
ty::local_var_name_str(self.tcx, id).get())
|
||||
.as_slice());
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
"captured variable is only valid for ",
|
||||
sup,
|
||||
"");
|
||||
}
|
||||
infer::IndexSlice(span) => {
|
||||
self.tcx.sess.span_err(span,
|
||||
"index of slice outside its lifetime");
|
||||
@ -1423,11 +1436,11 @@ impl<'a> ErrorReportingHelpers for InferCtxt<'a> {
|
||||
bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
|
||||
}
|
||||
infer::EarlyBoundRegion(_, name) => {
|
||||
format!(" for lifetime parameter `{}",
|
||||
format!(" for lifetime parameter `{}`",
|
||||
token::get_name(name).get())
|
||||
}
|
||||
infer::BoundRegionInCoherence(name) => {
|
||||
format!(" for lifetime parameter `{} in coherence check",
|
||||
format!(" for lifetime parameter `{}` in coherence check",
|
||||
token::get_name(name).get())
|
||||
}
|
||||
infer::UpvarRegion(ref upvar_id, _) => {
|
||||
@ -1528,6 +1541,15 @@ impl<'a> ErrorReportingHelpers for InferCtxt<'a> {
|
||||
self.tcx,
|
||||
id).get().to_string()).as_slice());
|
||||
}
|
||||
infer::ProcCapture(span, id) => {
|
||||
self.tcx.sess.span_note(
|
||||
span,
|
||||
format!("...so that captured variable `{}` \
|
||||
is 'static",
|
||||
ty::local_var_name_str(
|
||||
self.tcx,
|
||||
id).get()).as_slice());
|
||||
}
|
||||
infer::IndexSlice(span) => {
|
||||
self.tcx.sess.span_note(
|
||||
span,
|
||||
@ -1571,8 +1593,8 @@ impl<'a> ErrorReportingHelpers for InferCtxt<'a> {
|
||||
infer::AutoBorrow(span) => {
|
||||
self.tcx.sess.span_note(
|
||||
span,
|
||||
"...so that reference is valid \
|
||||
at the time of implicit borrow");
|
||||
"...so that auto-reference is valid \
|
||||
at the time of borrow");
|
||||
}
|
||||
infer::ExprTypeIsNotInScope(t, span) => {
|
||||
self.tcx.sess.span_note(
|
||||
|
@ -161,6 +161,9 @@ pub enum SubregionOrigin {
|
||||
// Closure bound must not outlive captured free variables
|
||||
FreeVariable(Span, ast::NodeId),
|
||||
|
||||
// Proc upvars must be 'static
|
||||
ProcCapture(Span, ast::NodeId),
|
||||
|
||||
// Index into slice must be within its lifetime
|
||||
IndexSlice(Span),
|
||||
|
||||
@ -933,6 +936,7 @@ impl SubregionOrigin {
|
||||
InvokeClosure(a) => a,
|
||||
DerefPointer(a) => a,
|
||||
FreeVariable(a, _) => a,
|
||||
ProcCapture(a, _) => a,
|
||||
IndexSlice(a) => a,
|
||||
RelateObjectBound(a) => a,
|
||||
RelateProcBound(a, _, _) => a,
|
||||
@ -972,6 +976,9 @@ impl Repr for SubregionOrigin {
|
||||
FreeVariable(a, b) => {
|
||||
format!("FreeVariable({}, {})", a.repr(tcx), b)
|
||||
}
|
||||
ProcCapture(a, b) => {
|
||||
format!("ProcCapture({}, {})", a.repr(tcx), b)
|
||||
}
|
||||
IndexSlice(a) => {
|
||||
format!("IndexSlice({})", a.repr(tcx))
|
||||
}
|
||||
|
34
src/test/compile-fail/regions-infer-proc-static-upvar.rs
Normal file
34
src/test/compile-fail/regions-infer-proc-static-upvar.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that, when a variable of type `&T` is captured inside a proc,
|
||||
// we correctly infer/require that its lifetime is 'static.
|
||||
|
||||
fn foo(_p: proc():'static) { }
|
||||
|
||||
static i: int = 3;
|
||||
|
||||
fn capture_local() {
|
||||
let x = 3i;
|
||||
let y = &x; //~ ERROR `x` does not live long enough
|
||||
foo(proc() {
|
||||
let _a = *y;
|
||||
});
|
||||
}
|
||||
|
||||
fn capture_static() {
|
||||
// Legal because &i can have static lifetime:
|
||||
let y = &i;
|
||||
foo(proc() {
|
||||
let _a = *y;
|
||||
});
|
||||
}
|
||||
|
||||
fn main() { }
|
23
src/test/run-pass/regions-infer-static-from-proc.rs
Normal file
23
src/test/run-pass/regions-infer-static-from-proc.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that the 'static bound on a proc influences lifetimes of
|
||||
// region variables contained within (otherwise, region inference will
|
||||
// give `x` a very short lifetime).
|
||||
|
||||
static i: uint = 3;
|
||||
fn foo(_: proc():'static) {}
|
||||
fn read(_: uint) { }
|
||||
pub fn main() {
|
||||
let x = &i;
|
||||
foo(proc() {
|
||||
read(*x);
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user