From 982e1166b238f8cd7abe8a7acb91d42cc8e9f5c4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 17 Jun 2012 16:16:41 -0700 Subject: [PATCH] Issue #2633: remove last_use entries that are subject to a loan --- src/rustc/driver/driver.rs | 3 ++- src/rustc/middle/borrowck.rs | 3 +++ src/rustc/middle/borrowck/check_loans.rs | 21 +++++++++++++++++++++ src/rustc/middle/liveness.rs | 3 +++ src/test/run-pass/issue-2633-2.rs | 8 ++++++++ src/test/run-pass/issue-2633.rs | 4 +--- 6 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/issue-2633-2.rs diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index edda9da0aa8e..b5950037a43a 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -203,7 +203,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, bind middle::tstate::ck::check_crate(ty_cx, crate)); let (root_map, mutbl_map) = time( time_passes, "borrow checking", - bind middle::borrowck::check_crate(ty_cx, method_map, crate)); + bind middle::borrowck::check_crate(ty_cx, method_map, + last_use_map, crate)); time(time_passes, "kind checking", bind kind::check_crate(ty_cx, method_map, last_use_map, crate)); time(time_passes, "lint checking", diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index cd77b3dffd7f..2208409ab500 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -170,9 +170,11 @@ export check_crate, root_map, mutbl_map; fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, + last_use_map: liveness::last_use_map, crate: @ast::crate) -> (root_map, mutbl_map) { let bccx = @{tcx: tcx, method_map: method_map, + last_use_map: last_use_map, root_map: root_map(), mutbl_map: int_hash()}; @@ -186,6 +188,7 @@ fn check_crate(tcx: ty::ctxt, type borrowck_ctxt = @{tcx: ty::ctxt, method_map: typeck::method_map, + last_use_map: liveness::last_use_map, root_map: root_map, mutbl_map: mutbl_map}; diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index c1ebf6888389..572be4f2ac70 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -448,6 +448,23 @@ impl methods for check_loan_ctxt { } } + // Very subtle (#2633): liveness can mark options as last_use even + // when there is an outstanding loan. In that case, it is not + // safe to consider the use a last_use. + fn check_last_use(expr: @ast::expr) { + let cmt = self.bccx.cat_expr(expr); + let lp = alt cmt.lp { + none { ret; } + some(lp) { lp } + }; + for self.walk_loans_of(cmt.id, lp) { |_loan| + #debug["Removing last use entry %? due to outstanding loan", + expr.id]; + self.bccx.last_use_map.remove(expr.id); + ret; + } + } + fn check_call(expr: @ast::expr, callee: option<@ast::expr>, callee_id: ast::node_id, @@ -531,6 +548,10 @@ fn check_loans_in_expr(expr: @ast::expr, self.check_for_conflicting_loans(expr.id); alt expr.node { + ast::expr_path(*) if self.bccx.last_use_map.contains_key(expr.id) { + self.check_last_use(expr); + } + ast::expr_swap(l, r) { self.check_assignment(at_swap, l); self.check_assignment(at_swap, r); diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 38571680ec6b..51d2285d6fea 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -63,6 +63,9 @@ export last_use_map; // the local/argument/etc that the path refers to. However, it also // possible for the expr to be a closure, in which case the list is a // list of closed over variables that can be moved into the closure. +// +// Very subtle (#2633): borrowck will remove entries from this table +// if it detects an outstanding loan (that is, the addr is taken). type last_use_map = hashmap>; enum variable = uint; diff --git a/src/test/run-pass/issue-2633-2.rs b/src/test/run-pass/issue-2633-2.rs new file mode 100644 index 000000000000..1ff294a2d306 --- /dev/null +++ b/src/test/run-pass/issue-2633-2.rs @@ -0,0 +1,8 @@ +fn a_val(&&x: ~int, +y: ~int) -> int { + *x + *y +} + +fn main() { + let z = ~22; + a_val(z, z); +} diff --git a/src/test/run-pass/issue-2633.rs b/src/test/run-pass/issue-2633.rs index b3b7649536a3..53d7861be4f8 100644 --- a/src/test/run-pass/issue-2633.rs +++ b/src/test/run-pass/issue-2633.rs @@ -1,5 +1,3 @@ -// Currently segfaults -// xfail-test class cat { let mut meow: fn@(); new() { self.meow = fn@() { #error("meow"); };} @@ -15,4 +13,4 @@ fn nyan(kitty: cat, _kitty_info: kitty_info) { fn main() { let mut kitty = cat(); nyan(kitty, {kitty: kitty}); -} \ No newline at end of file +}