From 63210ecddb74fb601a17314c6866685d74fa89dc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 16 May 2012 06:57:52 -0700 Subject: [PATCH] correct preservation of explicit borrows like "let x = &*y;" --- src/rustc/middle/borrowck.rs | 6 ++-- .../regions-appearance-constraint.rs | 35 +++++++++++++++++++ .../run-pass/borrowck-preserve-cond-box.rs | 31 ++++++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/regions-appearance-constraint.rs create mode 100644 src/test/run-pass/borrowck-preserve-cond-box.rs diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index 0908bafb2e25..06850c8c7b32 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -1481,7 +1481,7 @@ impl preserve_methods for preserve_ctxt { // Unsafe pointers are the user's problem ok(()) } - cat_deref(_, derefs, gc_ptr) { + cat_deref(base, derefs, gc_ptr) { // GC'd pointers of type @MT: always stable because we can inc // the ref count or keep a GC root as necessary. We need to // insert this id into the root_map, however. @@ -1489,9 +1489,9 @@ impl preserve_methods for preserve_ctxt { some(scope_id) { #debug["Inserting root map entry for %s: \ node %d:%u -> scope %d", - self.bccx.cmt_to_repr(cmt), cmt.id, + self.bccx.cmt_to_repr(cmt), base.id, derefs, scope_id]; - let rk = {id: cmt.id, derefs: derefs}; + let rk = {id: base.id, derefs: derefs}; self.bccx.root_map.insert(rk, scope_id); ok(()) } diff --git a/src/test/compile-fail/regions-appearance-constraint.rs b/src/test/compile-fail/regions-appearance-constraint.rs new file mode 100644 index 000000000000..c37d3c1d2191 --- /dev/null +++ b/src/test/compile-fail/regions-appearance-constraint.rs @@ -0,0 +1,35 @@ +/* + +Tests that borrowing always produces a pointer confined to the +innermost scope. In this case, the variable `a` gets inferred +to the lifetime of the `if` statement because it is assigned +a borrow of `y` which takes place within the `if`. + +Note: If this constraint were lifted (as I contemplated at one point), +it complicates the preservation mechanics in trans, though not +irreperably. I'm partially including this test so that if these +semantics do change we'll remember to test this scenario. + +*/ + +fn testfn(cond: bool) { + let mut x = @3; + let mut y = @4; + + let mut a = &*x; + //!^ ERROR reference is not valid outside of its lifetime + + let mut exp = 3; + if cond { + a = &*y; + + exp = 4; + } + + x = @5; + y = @6; + assert *a == exp; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/run-pass/borrowck-preserve-cond-box.rs b/src/test/run-pass/borrowck-preserve-cond-box.rs new file mode 100644 index 000000000000..13b7fa77c5e5 --- /dev/null +++ b/src/test/run-pass/borrowck-preserve-cond-box.rs @@ -0,0 +1,31 @@ +// compile-flags:--borrowck=err +// exec-env:RUST_POISON_ON_FREE=1 + +fn testfn(cond: bool) { + let mut x = @3; + let mut y = @4; + + // borrow x and y + let mut r_x = &*x; + let mut r_y = &*y; + let mut r = r_x, exp = 3; + + if cond { + r = r_y; + exp = 4; + } + + #debug["*r = %d, exp = %d", *r, exp]; + assert *r == exp; + + x = @5; + y = @6; + + #debug["*r = %d, exp = %d", *r, exp]; + assert *r == exp; +} + +fn main() { + testfn(true); + testfn(false); +} \ No newline at end of file